summaryrefslogtreecommitdiff
path: root/core/fxge/dib
diff options
context:
space:
mode:
authorDan Sinclair <dsinclair@chromium.org>2016-03-14 13:35:12 -0400
committerDan Sinclair <dsinclair@chromium.org>2016-03-14 13:35:12 -0400
commit764ec513eecbebd12781bcc96ce81ed5e736ee92 (patch)
tree12763fde4be1f10ea1183d92185917b2b587e00b /core/fxge/dib
parent97da97662417085774f75c26e535c6fbe70266ae (diff)
downloadpdfium-764ec513eecbebd12781bcc96ce81ed5e736ee92.tar.xz
Move core/src/ up to core/.
This CL moves the core/src/ files up to core/ and fixes up the include guards, includes and build files. R=tsepez@chromium.org Review URL: https://codereview.chromium.org/1800523005 .
Diffstat (limited to 'core/fxge/dib')
-rw-r--r--core/fxge/dib/dib_int.h107
-rw-r--r--core/fxge/dib/fx_dib_composite.cpp5210
-rw-r--r--core/fxge/dib/fx_dib_convert.cpp1227
-rw-r--r--core/fxge/dib/fx_dib_engine.cpp917
-rw-r--r--core/fxge/dib/fx_dib_main.cpp1745
-rw-r--r--core/fxge/dib/fx_dib_transform.cpp948
6 files changed, 10154 insertions, 0 deletions
diff --git a/core/fxge/dib/dib_int.h b/core/fxge/dib/dib_int.h
new file mode 100644
index 0000000000..85888fed50
--- /dev/null
+++ b/core/fxge/dib/dib_int.h
@@ -0,0 +1,107 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXGE_DIB_DIB_INT_H_
+#define CORE_FXGE_DIB_DIB_INT_H_
+
+#include <stdint.h>
+
+#include "core/include/fxcrt/fx_coordinates.h"
+#include "core/include/fxge/fx_dib.h"
+
+class IFX_ScanlineComposer;
+
+extern const int16_t SDP_Table[513];
+
+class CPDF_FixedMatrix {
+ public:
+ CPDF_FixedMatrix(const CFX_Matrix& src, int bits) {
+ base = 1 << bits;
+ a = FXSYS_round(src.a * base);
+ b = FXSYS_round(src.b * base);
+ c = FXSYS_round(src.c * base);
+ d = FXSYS_round(src.d * base);
+ e = FXSYS_round(src.e * base);
+ f = FXSYS_round(src.f * base);
+ }
+ inline void Transform(int x, int y, int& x1, int& y1) {
+ x1 = (a * x + c * y + e + base / 2) / base;
+ y1 = (b * x + d * y + f + base / 2) / base;
+ }
+ int a, b, c, d, e, f;
+ int base;
+};
+#define FPDF_HUGE_IMAGE_SIZE 60000000
+struct PixelWeight {
+ int m_SrcStart;
+ int m_SrcEnd;
+ int m_Weights[1];
+};
+class CWeightTable {
+ public:
+ CWeightTable() { m_pWeightTables = NULL; }
+ ~CWeightTable() {
+ FX_Free(m_pWeightTables);
+ m_pWeightTables = NULL;
+ }
+ void Calc(int dest_len,
+ int dest_min,
+ int dest_max,
+ int src_len,
+ int src_min,
+ int src_max,
+ int flags);
+ PixelWeight* GetPixelWeight(int pixel) {
+ return (PixelWeight*)(m_pWeightTables + (pixel - m_DestMin) * m_ItemSize);
+ }
+ int m_DestMin, m_ItemSize;
+ uint8_t* m_pWeightTables;
+};
+class CStretchEngine {
+ public:
+ CStretchEngine(IFX_ScanlineComposer* pDestBitmap,
+ FXDIB_Format dest_format,
+ int dest_width,
+ int dest_height,
+ const FX_RECT& clip_rect,
+ const CFX_DIBSource* pSrcBitmap,
+ int flags);
+ ~CStretchEngine();
+ FX_BOOL Continue(IFX_Pause* pPause);
+
+ public:
+ FXDIB_Format m_DestFormat;
+ int m_DestBpp, m_SrcBpp, m_bHasAlpha;
+ IFX_ScanlineComposer* m_pDestBitmap;
+ int m_DestWidth, m_DestHeight;
+ FX_RECT m_DestClip;
+ uint8_t* m_pDestScanline;
+ uint8_t* m_pDestMaskScanline;
+ FX_RECT m_SrcClip;
+ const CFX_DIBSource* m_pSource;
+ FX_DWORD* m_pSrcPalette;
+ int m_SrcWidth, m_SrcHeight;
+ int m_SrcPitch, m_InterPitch;
+ int m_ExtraMaskPitch;
+ unsigned char* m_pInterBuf;
+ unsigned char* m_pExtraAlphaBuf;
+ int m_TransMethod;
+ int m_Flags;
+ CWeightTable m_WeightTable;
+ int m_CurRow;
+ FX_BOOL StartStretchHorz();
+ FX_BOOL ContinueStretchHorz(IFX_Pause* pPause);
+ void StretchVert();
+ int m_State;
+};
+
+FX_RECT FXDIB_SwapClipBox(FX_RECT& clip,
+ int width,
+ int height,
+ FX_BOOL bFlipX,
+ FX_BOOL bFlipY);
+
+#endif // CORE_FXGE_DIB_DIB_INT_H_
diff --git a/core/fxge/dib/fx_dib_composite.cpp b/core/fxge/dib/fx_dib_composite.cpp
new file mode 100644
index 0000000000..0bf67ccb71
--- /dev/null
+++ b/core/fxge/dib/fx_dib_composite.cpp
@@ -0,0 +1,5210 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxge/dib/dib_int.h"
+#include "core/include/fxcodec/fx_codec.h"
+#include "core/include/fxge/fx_ge.h"
+
+const uint8_t _color_sqrt[256] = {
+ 0x00, 0x03, 0x07, 0x0B, 0x0F, 0x12, 0x16, 0x19, 0x1D, 0x20, 0x23, 0x26,
+ 0x29, 0x2C, 0x2F, 0x32, 0x35, 0x37, 0x3A, 0x3C, 0x3F, 0x41, 0x43, 0x46,
+ 0x48, 0x4A, 0x4C, 0x4E, 0x50, 0x52, 0x54, 0x56, 0x57, 0x59, 0x5B, 0x5C,
+ 0x5E, 0x60, 0x61, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6B, 0x6C, 0x6D,
+ 0x6E, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
+ 0x7B, 0x7C, 0x7D, 0x7E, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x91,
+ 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C,
+ 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA4, 0xA5,
+ 0xA6, 0xA7, 0xA7, 0xA8, 0xA9, 0xAA, 0xAA, 0xAB, 0xAC, 0xAD, 0xAD, 0xAE,
+ 0xAF, 0xB0, 0xB0, 0xB1, 0xB2, 0xB3, 0xB3, 0xB4, 0xB5, 0xB5, 0xB6, 0xB7,
+ 0xB7, 0xB8, 0xB9, 0xBA, 0xBA, 0xBB, 0xBC, 0xBC, 0xBD, 0xBE, 0xBE, 0xBF,
+ 0xC0, 0xC0, 0xC1, 0xC2, 0xC2, 0xC3, 0xC4, 0xC4, 0xC5, 0xC6, 0xC6, 0xC7,
+ 0xC7, 0xC8, 0xC9, 0xC9, 0xCA, 0xCB, 0xCB, 0xCC, 0xCC, 0xCD, 0xCE, 0xCE,
+ 0xCF, 0xD0, 0xD0, 0xD1, 0xD1, 0xD2, 0xD3, 0xD3, 0xD4, 0xD4, 0xD5, 0xD6,
+ 0xD6, 0xD7, 0xD7, 0xD8, 0xD9, 0xD9, 0xDA, 0xDA, 0xDB, 0xDC, 0xDC, 0xDD,
+ 0xDD, 0xDE, 0xDE, 0xDF, 0xE0, 0xE0, 0xE1, 0xE1, 0xE2, 0xE2, 0xE3, 0xE4,
+ 0xE4, 0xE5, 0xE5, 0xE6, 0xE6, 0xE7, 0xE7, 0xE8, 0xE9, 0xE9, 0xEA, 0xEA,
+ 0xEB, 0xEB, 0xEC, 0xEC, 0xED, 0xED, 0xEE, 0xEE, 0xEF, 0xF0, 0xF0, 0xF1,
+ 0xF1, 0xF2, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4, 0xF5, 0xF5, 0xF6, 0xF6, 0xF7,
+ 0xF7, 0xF8, 0xF8, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC, 0xFD,
+ 0xFD, 0xFE, 0xFE, 0xFF};
+int _BLEND(int blend_mode, int back_color, int src_color) {
+ switch (blend_mode) {
+ case FXDIB_BLEND_NORMAL:
+ return src_color;
+ case FXDIB_BLEND_MULTIPLY:
+ return src_color * back_color / 255;
+ case FXDIB_BLEND_SCREEN:
+ return src_color + back_color - src_color * back_color / 255;
+ case FXDIB_BLEND_OVERLAY:
+ return _BLEND(FXDIB_BLEND_HARDLIGHT, src_color, back_color);
+ case FXDIB_BLEND_DARKEN:
+ return src_color < back_color ? src_color : back_color;
+ case FXDIB_BLEND_LIGHTEN:
+ return src_color > back_color ? src_color : back_color;
+ case FXDIB_BLEND_COLORDODGE: {
+ if (src_color == 255) {
+ return src_color;
+ }
+ int result = back_color * 255 / (255 - src_color);
+ if (result > 255) {
+ return 255;
+ }
+ return result;
+ }
+ case FXDIB_BLEND_COLORBURN: {
+ if (src_color == 0) {
+ return src_color;
+ }
+ int result = (255 - back_color) * 255 / src_color;
+ if (result > 255) {
+ result = 255;
+ }
+ return 255 - result;
+ }
+ case FXDIB_BLEND_HARDLIGHT:
+ if (src_color < 128) {
+ return (src_color * back_color * 2) / 255;
+ }
+ return _BLEND(FXDIB_BLEND_SCREEN, back_color, 2 * src_color - 255);
+ case FXDIB_BLEND_SOFTLIGHT: {
+ if (src_color < 128) {
+ return back_color -
+ (255 - 2 * src_color) * back_color * (255 - back_color) / 255 /
+ 255;
+ }
+ return back_color +
+ (2 * src_color - 255) * (_color_sqrt[back_color] - back_color) /
+ 255;
+ }
+ case FXDIB_BLEND_DIFFERENCE:
+ return back_color < src_color ? src_color - back_color
+ : back_color - src_color;
+ case FXDIB_BLEND_EXCLUSION:
+ return back_color + src_color - 2 * back_color * src_color / 255;
+ }
+ return src_color;
+}
+struct _RGB {
+ int red;
+ int green;
+ int blue;
+};
+static inline int _Lum(_RGB color) {
+ return (color.red * 30 + color.green * 59 + color.blue * 11) / 100;
+}
+static _RGB _ClipColor(_RGB color) {
+ int l = _Lum(color);
+ int n = color.red;
+ if (color.green < n) {
+ n = color.green;
+ }
+ if (color.blue < n) {
+ n = color.blue;
+ }
+ int x = color.red;
+ if (color.green > x) {
+ x = color.green;
+ }
+ if (color.blue > x) {
+ x = color.blue;
+ }
+ if (n < 0) {
+ color.red = l + ((color.red - l) * l / (l - n));
+ color.green = l + ((color.green - l) * l / (l - n));
+ color.blue = l + ((color.blue - l) * l / (l - n));
+ }
+ if (x > 255) {
+ color.red = l + ((color.red - l) * (255 - l) / (x - l));
+ color.green = l + ((color.green - l) * (255 - l) / (x - l));
+ color.blue = l + ((color.blue - l) * (255 - l) / (x - l));
+ }
+ return color;
+}
+static _RGB _SetLum(_RGB color, int l) {
+ int d = l - _Lum(color);
+ color.red += d;
+ color.green += d;
+ color.blue += d;
+ return _ClipColor(color);
+}
+static int _Sat(_RGB color) {
+ int n = color.red;
+ if (color.green < n) {
+ n = color.green;
+ }
+ if (color.blue < n) {
+ n = color.blue;
+ }
+ int x = color.red;
+ if (color.green > x) {
+ x = color.green;
+ }
+ if (color.blue > x) {
+ x = color.blue;
+ }
+ return x - n;
+}
+static _RGB _SetSat(_RGB color, int s) {
+ int* max = &color.red;
+ int* mid = &color.red;
+ int* min = &color.red;
+ if (color.green > *max) {
+ max = &color.green;
+ }
+ if (color.blue > *max) {
+ max = &color.blue;
+ }
+ if (color.green < *min) {
+ min = &color.green;
+ }
+ if (color.blue < *min) {
+ min = &color.blue;
+ }
+ if (*max == *min) {
+ color.red = 0;
+ color.green = 0;
+ color.blue = 0;
+ return color;
+ }
+ if (max == &color.red) {
+ if (min == &color.green) {
+ mid = &color.blue;
+ } else {
+ mid = &color.green;
+ }
+ } else if (max == &color.green) {
+ if (min == &color.red) {
+ mid = &color.blue;
+ } else {
+ mid = &color.red;
+ }
+ } else {
+ if (min == &color.green) {
+ mid = &color.red;
+ } else {
+ mid = &color.green;
+ }
+ }
+ if (*max > *min) {
+ *mid = (*mid - *min) * s / (*max - *min);
+ *max = s;
+ *min = 0;
+ }
+ return color;
+}
+void _RGB_Blend(int blend_mode,
+ const uint8_t* src_scan,
+ uint8_t* dest_scan,
+ int results[3]) {
+ _RGB src, back, result;
+ src.red = src_scan[2];
+ src.green = src_scan[1];
+ src.blue = src_scan[0];
+ back.red = dest_scan[2];
+ back.green = dest_scan[1];
+ back.blue = dest_scan[0];
+ switch (blend_mode) {
+ case FXDIB_BLEND_HUE:
+ result = _SetLum(_SetSat(src, _Sat(back)), _Lum(back));
+ break;
+ case FXDIB_BLEND_SATURATION:
+ result = _SetLum(_SetSat(back, _Sat(src)), _Lum(back));
+ break;
+ case FXDIB_BLEND_COLOR:
+ result = _SetLum(src, _Lum(back));
+ break;
+ case FXDIB_BLEND_LUMINOSITY:
+ result = _SetLum(back, _Lum(src));
+ break;
+ }
+ results[0] = result.blue;
+ results[1] = result.green;
+ results[2] = result.red;
+}
+inline void _CompositeRow_Argb2Mask(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int pixel_count,
+ const uint8_t* clip_scan) {
+ src_scan += 3;
+ for (int col = 0; col < pixel_count; col++) {
+ int src_alpha = *src_scan;
+ if (clip_scan) {
+ src_alpha = clip_scan[col] * src_alpha / 255;
+ }
+ uint8_t back_alpha = *dest_scan;
+ if (!back_alpha) {
+ *dest_scan = src_alpha;
+ } else if (src_alpha) {
+ *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ }
+ dest_scan++;
+ src_scan += 4;
+ }
+}
+void _CompositeRow_Rgba2Mask(uint8_t* dest_scan,
+ const uint8_t* src_alpha_scan,
+ int pixel_count,
+ const uint8_t* clip_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ int src_alpha = *src_alpha_scan++;
+ if (clip_scan) {
+ src_alpha = clip_scan[col] * src_alpha / 255;
+ }
+ uint8_t back_alpha = *dest_scan;
+ if (!back_alpha) {
+ *dest_scan = src_alpha;
+ } else if (src_alpha) {
+ *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ }
+ dest_scan++;
+ }
+}
+void _CompositeRow_Rgb2Mask(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ const uint8_t* clip_scan) {
+ if (clip_scan) {
+ for (int i = 0; i < width; i++) {
+ *dest_scan = FXDIB_ALPHA_UNION(*dest_scan, *clip_scan);
+ dest_scan++;
+ clip_scan++;
+ }
+ } else {
+ FXSYS_memset(dest_scan, 0xff, width);
+ }
+}
+void _CompositeRow_Argb2Graya(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int pixel_count,
+ int blend_type,
+ const uint8_t* clip_scan,
+ const uint8_t* src_alpha_scan,
+ uint8_t* dst_alpha_scan,
+ void* pIccTransform) {
+ ICodec_IccModule* pIccModule = nullptr;
+ if (pIccTransform)
+ pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+
+ if (blend_type) {
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int blended_color;
+ if (src_alpha_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t back_alpha = *dst_alpha_scan;
+ if (back_alpha == 0) {
+ int src_alpha = *src_alpha_scan++;
+ if (clip_scan)
+ src_alpha = clip_scan[col] * src_alpha / 255;
+
+ if (src_alpha) {
+ if (pIccTransform) {
+ pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan,
+ 1);
+ } else {
+ *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+ }
+ *dst_alpha_scan = src_alpha;
+ }
+ dest_scan++;
+ dst_alpha_scan++;
+ src_scan += 3;
+ continue;
+ }
+ uint8_t src_alpha = *src_alpha_scan++;
+ if (clip_scan)
+ src_alpha = clip_scan[col] * src_alpha / 255;
+
+ if (src_alpha == 0) {
+ dest_scan++;
+ dst_alpha_scan++;
+ src_scan += 3;
+ continue;
+ }
+ *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha);
+ int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan);
+ uint8_t gray;
+ if (pIccTransform) {
+ pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
+ } else {
+ gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+ }
+ if (bNonseparableBlend) {
+ blended_color =
+ blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
+ }
+ gray = bNonseparableBlend ? blended_color
+ : _BLEND(blend_type, *dest_scan, gray);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
+ dest_scan++;
+ dst_alpha_scan++;
+ src_scan += 3;
+ }
+ } else {
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t back_alpha = *dst_alpha_scan;
+ if (back_alpha == 0) {
+ int src_alpha = src_scan[3];
+ if (clip_scan)
+ src_alpha = clip_scan[col] * src_alpha / 255;
+
+ if (src_alpha) {
+ if (pIccTransform) {
+ pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan,
+ 1);
+ } else {
+ *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+ }
+ *dst_alpha_scan = src_alpha;
+ }
+ dest_scan++;
+ dst_alpha_scan++;
+ src_scan += 4;
+ continue;
+ }
+ uint8_t src_alpha = src_scan[3];
+ if (clip_scan)
+ src_alpha = clip_scan[col] * src_alpha / 255;
+
+ if (src_alpha == 0) {
+ dest_scan++;
+ dst_alpha_scan++;
+ src_scan += 4;
+ continue;
+ }
+ *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha);
+ int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan);
+ uint8_t gray;
+ if (pIccTransform)
+ pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
+ else
+ gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
+ dest_scan++;
+ dst_alpha_scan++;
+ src_scan += 4;
+ }
+ }
+ return;
+ }
+ if (src_alpha_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t back_alpha = *dst_alpha_scan;
+ if (back_alpha == 0) {
+ int src_alpha = *src_alpha_scan++;
+ if (clip_scan)
+ src_alpha = clip_scan[col] * src_alpha / 255;
+
+ if (src_alpha) {
+ if (pIccTransform) {
+ pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan,
+ 1);
+ } else {
+ *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+ }
+ *dst_alpha_scan = src_alpha;
+ }
+ dest_scan++;
+ dst_alpha_scan++;
+ src_scan += 3;
+ continue;
+ }
+ uint8_t src_alpha = *src_alpha_scan++;
+ if (clip_scan)
+ src_alpha = clip_scan[col] * src_alpha / 255;
+
+ if (src_alpha == 0) {
+ dest_scan++;
+ dst_alpha_scan++;
+ src_scan += 3;
+ continue;
+ }
+ *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha);
+ int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan);
+ uint8_t gray;
+ if (pIccTransform)
+ pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
+ else
+ gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
+ dest_scan++;
+ dst_alpha_scan++;
+ src_scan += 3;
+ }
+ } else {
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t back_alpha = *dst_alpha_scan;
+ if (back_alpha == 0) {
+ int src_alpha = src_scan[3];
+ if (clip_scan)
+ src_alpha = clip_scan[col] * src_alpha / 255;
+
+ if (src_alpha) {
+ if (pIccTransform) {
+ pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan,
+ 1);
+ } else {
+ *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+ }
+ *dst_alpha_scan = src_alpha;
+ }
+ dest_scan++;
+ dst_alpha_scan++;
+ src_scan += 4;
+ continue;
+ }
+ uint8_t src_alpha = src_scan[3];
+ if (clip_scan)
+ src_alpha = clip_scan[col] * src_alpha / 255;
+
+ if (src_alpha == 0) {
+ dest_scan++;
+ dst_alpha_scan++;
+ src_scan += 4;
+ continue;
+ }
+ *dst_alpha_scan = FXDIB_ALPHA_UNION(back_alpha, src_alpha);
+ int alpha_ratio = src_alpha * 255 / (*dst_alpha_scan);
+ uint8_t gray;
+ if (pIccTransform)
+ pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
+ else
+ gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
+ dest_scan++;
+ dst_alpha_scan++;
+ src_scan += 4;
+ }
+ }
+}
+
+inline void _CompositeRow_Argb2Gray(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int pixel_count,
+ int blend_type,
+ const uint8_t* clip_scan,
+ const uint8_t* src_alpha_scan,
+ void* pIccTransform) {
+ ICodec_IccModule* pIccModule = NULL;
+ uint8_t gray;
+ if (pIccTransform)
+ pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+
+ if (blend_type) {
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int blended_color;
+ if (src_alpha_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ int src_alpha = *src_alpha_scan++;
+ if (clip_scan)
+ src_alpha = clip_scan[col] * src_alpha / 255;
+
+ if (src_alpha) {
+ if (pIccTransform)
+ pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
+ else
+ gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+
+ if (bNonseparableBlend) {
+ blended_color =
+ blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
+ }
+ gray = bNonseparableBlend ? blended_color
+ : _BLEND(blend_type, *dest_scan, gray);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
+ }
+ dest_scan++;
+ src_scan += 3;
+ }
+ } else {
+ for (int col = 0; col < pixel_count; col++) {
+ int src_alpha = src_scan[3];
+ if (clip_scan)
+ src_alpha = clip_scan[col] * src_alpha / 255;
+
+ if (src_alpha) {
+ if (pIccTransform)
+ pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
+ else
+ gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+
+ if (bNonseparableBlend) {
+ blended_color =
+ blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
+ }
+ gray = bNonseparableBlend ? blended_color
+ : _BLEND(blend_type, *dest_scan, gray);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
+ }
+ dest_scan++;
+ src_scan += 4;
+ }
+ }
+ return;
+ }
+ if (src_alpha_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ int src_alpha = *src_alpha_scan++;
+ if (clip_scan)
+ src_alpha = clip_scan[col] * src_alpha / 255;
+
+ if (src_alpha) {
+ if (pIccTransform)
+ pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
+ else
+ gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
+ }
+ dest_scan++;
+ src_scan += 3;
+ }
+ } else {
+ for (int col = 0; col < pixel_count; col++) {
+ int src_alpha = src_scan[3];
+ if (clip_scan)
+ src_alpha = clip_scan[col] * src_alpha / 255;
+
+ if (src_alpha) {
+ if (pIccTransform)
+ pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
+ else
+ gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
+ }
+ dest_scan++;
+ src_scan += 4;
+ }
+ }
+}
+
+inline void _CompositeRow_Rgb2Gray(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int src_Bpp,
+ int pixel_count,
+ int blend_type,
+ const uint8_t* clip_scan,
+ void* pIccTransform) {
+ ICodec_IccModule* pIccModule = NULL;
+ uint8_t gray;
+ if (pIccTransform) {
+ pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ }
+ if (blend_type) {
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int blended_color;
+ for (int col = 0; col < pixel_count; col++) {
+ if (pIccTransform) {
+ pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
+ } else {
+ gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+ }
+ if (bNonseparableBlend) {
+ blended_color =
+ blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
+ }
+ gray = bNonseparableBlend ? blended_color
+ : _BLEND(blend_type, *dest_scan, gray);
+ if (clip_scan && clip_scan[col] < 255) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
+ } else {
+ *dest_scan = gray;
+ }
+ dest_scan++;
+ src_scan += src_Bpp;
+ }
+ return;
+ }
+ for (int col = 0; col < pixel_count; col++) {
+ if (pIccTransform) {
+ pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
+ } else {
+ gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+ }
+ if (clip_scan && clip_scan[col] < 255) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
+ } else {
+ *dest_scan = gray;
+ }
+ dest_scan++;
+ src_scan += src_Bpp;
+ }
+}
+void _CompositeRow_Rgb2Graya(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int src_Bpp,
+ int pixel_count,
+ int blend_type,
+ const uint8_t* clip_scan,
+ uint8_t* dest_alpha_scan,
+ void* pIccTransform) {
+ ICodec_IccModule* pIccModule = NULL;
+ if (pIccTransform) {
+ pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ }
+ if (blend_type) {
+ int blended_color;
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ for (int col = 0; col < pixel_count; col++) {
+ int back_alpha = *dest_alpha_scan;
+ if (back_alpha == 0) {
+ if (pIccTransform) {
+ pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 1);
+ } else {
+ *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+ }
+ dest_scan++;
+ dest_alpha_scan++;
+ src_scan += src_Bpp;
+ continue;
+ }
+ int src_alpha = 255;
+ if (clip_scan) {
+ src_alpha = clip_scan[col];
+ }
+ if (src_alpha == 0) {
+ dest_scan++;
+ dest_alpha_scan++;
+ src_scan += src_Bpp;
+ continue;
+ }
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ uint8_t gray;
+ if (pIccTransform) {
+ pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
+ } else {
+ gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+ }
+ if (bNonseparableBlend) {
+ blended_color =
+ blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
+ }
+ gray = bNonseparableBlend ? blended_color
+ : _BLEND(blend_type, *dest_scan, gray);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
+ dest_scan++;
+ src_scan += src_Bpp;
+ }
+ return;
+ }
+ for (int col = 0; col < pixel_count; col++) {
+ int src_alpha = 255;
+ if (clip_scan) {
+ src_alpha = clip_scan[col];
+ }
+ if (src_alpha == 255) {
+ if (pIccTransform) {
+ pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 1);
+ } else {
+ *dest_scan = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+ }
+ dest_scan++;
+ *dest_alpha_scan++ = 255;
+ src_scan += src_Bpp;
+ continue;
+ }
+ if (src_alpha == 0) {
+ dest_scan++;
+ dest_alpha_scan++;
+ src_scan += src_Bpp;
+ continue;
+ }
+ int back_alpha = *dest_alpha_scan;
+ uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ uint8_t gray;
+ if (pIccTransform) {
+ pIccModule->TranslateScanline(pIccTransform, &gray, src_scan, 1);
+ } else {
+ gray = FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan);
+ }
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
+ dest_scan++;
+ src_scan += src_Bpp;
+ }
+}
+void _CompositeRow_Argb2Argb(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int pixel_count,
+ int blend_type,
+ const uint8_t* clip_scan,
+ uint8_t* dest_alpha_scan,
+ const uint8_t* src_alpha_scan) {
+ int blended_colors[3];
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ if (!dest_alpha_scan) {
+ if (!src_alpha_scan) {
+ uint8_t back_alpha = 0;
+ for (int col = 0; col < pixel_count; col++) {
+ back_alpha = dest_scan[3];
+ if (back_alpha == 0) {
+ if (clip_scan) {
+ int src_alpha = clip_scan[col] * src_scan[3] / 255;
+ FXARGB_SETDIB(dest_scan, (FXARGB_GETDIB(src_scan) & 0xffffff) |
+ (src_alpha << 24));
+ } else {
+ FXARGB_COPY(dest_scan, src_scan);
+ }
+ dest_scan += 4;
+ src_scan += 4;
+ continue;
+ }
+ uint8_t src_alpha;
+ if (clip_scan) {
+ src_alpha = clip_scan[col] * src_scan[3] / 255;
+ } else {
+ src_alpha = src_scan[3];
+ }
+ if (src_alpha == 0) {
+ dest_scan += 4;
+ src_scan += 4;
+ continue;
+ }
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ dest_scan[3] = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ if (bNonseparableBlend) {
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ if (blend_type) {
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, *dest_scan, *src_scan);
+ blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ } else {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio);
+ }
+ dest_scan++;
+ src_scan++;
+ }
+ dest_scan++;
+ src_scan++;
+ }
+ } else {
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t back_alpha = dest_scan[3];
+ if (back_alpha == 0) {
+ if (clip_scan) {
+ int src_alpha = clip_scan[col] * (*src_alpha_scan) / 255;
+ FXARGB_SETDIB(dest_scan, FXARGB_MAKE((src_alpha << 24), src_scan[2],
+ src_scan[1], *src_scan));
+ } else {
+ FXARGB_SETDIB(dest_scan,
+ FXARGB_MAKE((*src_alpha_scan << 24), src_scan[2],
+ src_scan[1], *src_scan));
+ }
+ dest_scan += 4;
+ src_scan += 3;
+ src_alpha_scan++;
+ continue;
+ }
+ uint8_t src_alpha;
+ if (clip_scan) {
+ src_alpha = clip_scan[col] * (*src_alpha_scan++) / 255;
+ } else {
+ src_alpha = *src_alpha_scan++;
+ }
+ if (src_alpha == 0) {
+ dest_scan += 4;
+ src_scan += 3;
+ continue;
+ }
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ dest_scan[3] = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ if (bNonseparableBlend) {
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ if (blend_type) {
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, *dest_scan, *src_scan);
+ blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ } else {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio);
+ }
+ dest_scan++;
+ src_scan++;
+ }
+ dest_scan++;
+ }
+ }
+ } else {
+ if (src_alpha_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t back_alpha = *dest_alpha_scan;
+ if (back_alpha == 0) {
+ if (clip_scan) {
+ int src_alpha = clip_scan[col] * (*src_alpha_scan) / 255;
+ *dest_alpha_scan = src_alpha;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ } else {
+ *dest_alpha_scan = *src_alpha_scan;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ }
+ dest_alpha_scan++;
+ src_alpha_scan++;
+ continue;
+ }
+ uint8_t src_alpha;
+ if (clip_scan) {
+ src_alpha = clip_scan[col] * (*src_alpha_scan++) / 255;
+ } else {
+ src_alpha = *src_alpha_scan++;
+ }
+ if (src_alpha == 0) {
+ dest_scan += 3;
+ src_scan += 3;
+ dest_alpha_scan++;
+ continue;
+ }
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ if (bNonseparableBlend) {
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ if (blend_type) {
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, *dest_scan, *src_scan);
+ blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ } else {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio);
+ }
+ dest_scan++;
+ src_scan++;
+ }
+ }
+ } else {
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t back_alpha = *dest_alpha_scan;
+ if (back_alpha == 0) {
+ if (clip_scan) {
+ int src_alpha = clip_scan[col] * src_scan[3] / 255;
+ *dest_alpha_scan = src_alpha;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ } else {
+ *dest_alpha_scan = src_scan[3];
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ }
+ dest_alpha_scan++;
+ src_scan++;
+ continue;
+ }
+ uint8_t src_alpha;
+ if (clip_scan) {
+ src_alpha = clip_scan[col] * src_scan[3] / 255;
+ } else {
+ src_alpha = src_scan[3];
+ }
+ if (src_alpha == 0) {
+ dest_scan += 3;
+ src_scan += 4;
+ dest_alpha_scan++;
+ continue;
+ }
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ if (bNonseparableBlend) {
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ if (blend_type) {
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, *dest_scan, *src_scan);
+ blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ } else {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio);
+ }
+ dest_scan++;
+ src_scan++;
+ }
+ src_scan++;
+ }
+ }
+ }
+}
+void _CompositeRow_Rgb2Argb_Blend_NoClip(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int blend_type,
+ int src_Bpp,
+ uint8_t* dest_alpha_scan) {
+ int blended_colors[3];
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int src_gap = src_Bpp - 3;
+ if (dest_alpha_scan) {
+ for (int col = 0; col < width; col++) {
+ uint8_t back_alpha = *dest_alpha_scan;
+ if (back_alpha == 0) {
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_alpha_scan++ = 0xff;
+ src_scan += src_gap;
+ continue;
+ }
+ *dest_alpha_scan++ = 0xff;
+ if (bNonseparableBlend) {
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ int src_color = *src_scan;
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, *dest_scan, src_color);
+ *dest_scan = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
+ dest_scan++;
+ src_scan++;
+ }
+ src_scan += src_gap;
+ }
+ } else {
+ for (int col = 0; col < width; col++) {
+ uint8_t back_alpha = dest_scan[3];
+ if (back_alpha == 0) {
+ if (src_Bpp == 4) {
+ FXARGB_SETDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
+ } else {
+ FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1],
+ src_scan[0]));
+ }
+ dest_scan += 4;
+ src_scan += src_Bpp;
+ continue;
+ }
+ dest_scan[3] = 0xff;
+ if (bNonseparableBlend) {
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ int src_color = *src_scan;
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, *dest_scan, src_color);
+ *dest_scan = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
+ dest_scan++;
+ src_scan++;
+ }
+ dest_scan++;
+ src_scan += src_gap;
+ }
+ }
+}
+inline void _CompositeRow_Rgb2Argb_Blend_Clip(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int blend_type,
+ int src_Bpp,
+ const uint8_t* clip_scan,
+ uint8_t* dest_alpha_scan) {
+ int blended_colors[3];
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int src_gap = src_Bpp - 3;
+ if (dest_alpha_scan) {
+ for (int col = 0; col < width; col++) {
+ int src_alpha = *clip_scan++;
+ uint8_t back_alpha = *dest_alpha_scan;
+ if (back_alpha == 0) {
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ src_scan += src_gap;
+ dest_alpha_scan++;
+ continue;
+ }
+ if (src_alpha == 0) {
+ dest_scan += 3;
+ dest_alpha_scan++;
+ src_scan += src_Bpp;
+ continue;
+ }
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ if (bNonseparableBlend) {
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ int src_color = *src_scan;
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, *dest_scan, src_color);
+ blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ dest_scan++;
+ src_scan++;
+ }
+ src_scan += src_gap;
+ }
+ } else {
+ for (int col = 0; col < width; col++) {
+ int src_alpha = *clip_scan++;
+ uint8_t back_alpha = dest_scan[3];
+ if (back_alpha == 0) {
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ src_scan += src_gap;
+ dest_scan++;
+ continue;
+ }
+ if (src_alpha == 0) {
+ dest_scan += 4;
+ src_scan += src_Bpp;
+ continue;
+ }
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ dest_scan[3] = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ if (bNonseparableBlend) {
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ int src_color = *src_scan;
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, *dest_scan, src_color);
+ blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ dest_scan++;
+ src_scan++;
+ }
+ dest_scan++;
+ src_scan += src_gap;
+ }
+ }
+}
+inline void _CompositeRow_Rgb2Argb_NoBlend_Clip(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int src_Bpp,
+ const uint8_t* clip_scan,
+ uint8_t* dest_alpha_scan) {
+ int src_gap = src_Bpp - 3;
+ if (dest_alpha_scan) {
+ for (int col = 0; col < width; col++) {
+ int src_alpha = clip_scan[col];
+ if (src_alpha == 255) {
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_alpha_scan++ = 255;
+ src_scan += src_gap;
+ continue;
+ }
+ if (src_alpha == 0) {
+ dest_scan += 3;
+ dest_alpha_scan++;
+ src_scan += src_Bpp;
+ continue;
+ }
+ int back_alpha = *dest_alpha_scan;
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ for (int color = 0; color < 3; color++) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio);
+ dest_scan++;
+ src_scan++;
+ }
+ src_scan += src_gap;
+ }
+ } else {
+ for (int col = 0; col < width; col++) {
+ int src_alpha = clip_scan[col];
+ if (src_alpha == 255) {
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = 255;
+ src_scan += src_gap;
+ continue;
+ }
+ if (src_alpha == 0) {
+ dest_scan += 4;
+ src_scan += src_Bpp;
+ continue;
+ }
+ int back_alpha = dest_scan[3];
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ dest_scan[3] = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ for (int color = 0; color < 3; color++) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, alpha_ratio);
+ dest_scan++;
+ src_scan++;
+ }
+ dest_scan++;
+ src_scan += src_gap;
+ }
+ }
+}
+inline void _CompositeRow_Rgb2Argb_NoBlend_NoClip(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int src_Bpp,
+ uint8_t* dest_alpha_scan) {
+ if (dest_alpha_scan) {
+ int src_gap = src_Bpp - 3;
+ for (int col = 0; col < width; col++) {
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_alpha_scan++ = 0xff;
+ src_scan += src_gap;
+ }
+ } else {
+ for (int col = 0; col < width; col++) {
+ if (src_Bpp == 4) {
+ FXARGB_SETDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
+ } else {
+ FXARGB_SETDIB(dest_scan,
+ FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0]));
+ }
+ dest_scan += 4;
+ src_scan += src_Bpp;
+ }
+ }
+}
+inline void _CompositeRow_Argb2Rgb_Blend(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int blend_type,
+ int dest_Bpp,
+ const uint8_t* clip_scan,
+ const uint8_t* src_alpha_scan) {
+ int blended_colors[3];
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int dest_gap = dest_Bpp - 3;
+ if (src_alpha_scan) {
+ for (int col = 0; col < width; col++) {
+ uint8_t src_alpha;
+ if (clip_scan) {
+ src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255;
+ } else {
+ src_alpha = *src_alpha_scan++;
+ }
+ if (src_alpha == 0) {
+ dest_scan += dest_Bpp;
+ src_scan += 3;
+ continue;
+ }
+ if (bNonseparableBlend) {
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ int back_color = *dest_scan;
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, back_color, *src_scan);
+ *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
+ dest_scan++;
+ src_scan++;
+ }
+ dest_scan += dest_gap;
+ }
+ } else {
+ for (int col = 0; col < width; col++) {
+ uint8_t src_alpha;
+ if (clip_scan) {
+ src_alpha = src_scan[3] * (*clip_scan++) / 255;
+ } else {
+ src_alpha = src_scan[3];
+ }
+ if (src_alpha == 0) {
+ dest_scan += dest_Bpp;
+ src_scan += 4;
+ continue;
+ }
+ if (bNonseparableBlend) {
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ int back_color = *dest_scan;
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, back_color, *src_scan);
+ *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
+ dest_scan++;
+ src_scan++;
+ }
+ dest_scan += dest_gap;
+ src_scan++;
+ }
+ }
+}
+inline void _CompositeRow_Argb2Rgb_NoBlend(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int dest_Bpp,
+ const uint8_t* clip_scan,
+ const uint8_t* src_alpha_scan) {
+ int dest_gap = dest_Bpp - 3;
+ if (src_alpha_scan) {
+ for (int col = 0; col < width; col++) {
+ uint8_t src_alpha;
+ if (clip_scan) {
+ src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255;
+ } else {
+ src_alpha = *src_alpha_scan++;
+ }
+ if (src_alpha == 255) {
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ dest_scan += dest_gap;
+ continue;
+ }
+ if (src_alpha == 0) {
+ dest_scan += dest_Bpp;
+ src_scan += 3;
+ continue;
+ }
+ for (int color = 0; color < 3; color++) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
+ dest_scan++;
+ src_scan++;
+ }
+ dest_scan += dest_gap;
+ }
+ } else {
+ for (int col = 0; col < width; col++) {
+ uint8_t src_alpha;
+ if (clip_scan) {
+ src_alpha = src_scan[3] * (*clip_scan++) / 255;
+ } else {
+ src_alpha = src_scan[3];
+ }
+ if (src_alpha == 255) {
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ dest_scan += dest_gap;
+ src_scan++;
+ continue;
+ }
+ if (src_alpha == 0) {
+ dest_scan += dest_Bpp;
+ src_scan += 4;
+ continue;
+ }
+ for (int color = 0; color < 3; color++) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
+ dest_scan++;
+ src_scan++;
+ }
+ dest_scan += dest_gap;
+ src_scan++;
+ }
+ }
+}
+inline void _CompositeRow_Rgb2Rgb_Blend_NoClip(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int blend_type,
+ int dest_Bpp,
+ int src_Bpp) {
+ int blended_colors[3];
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int dest_gap = dest_Bpp - 3;
+ int src_gap = src_Bpp - 3;
+ for (int col = 0; col < width; col++) {
+ if (bNonseparableBlend) {
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ int back_color = *dest_scan;
+ int src_color = *src_scan;
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, back_color, src_color);
+ *dest_scan = blended;
+ dest_scan++;
+ src_scan++;
+ }
+ dest_scan += dest_gap;
+ src_scan += src_gap;
+ }
+}
+inline void _CompositeRow_Rgb2Rgb_Blend_Clip(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int blend_type,
+ int dest_Bpp,
+ int src_Bpp,
+ const uint8_t* clip_scan) {
+ int blended_colors[3];
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int dest_gap = dest_Bpp - 3;
+ int src_gap = src_Bpp - 3;
+ for (int col = 0; col < width; col++) {
+ uint8_t src_alpha = *clip_scan++;
+ if (src_alpha == 0) {
+ dest_scan += dest_Bpp;
+ src_scan += src_Bpp;
+ continue;
+ }
+ if (bNonseparableBlend) {
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ int src_color = *src_scan;
+ int back_color = *dest_scan;
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, back_color, src_color);
+ *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
+ dest_scan++;
+ src_scan++;
+ }
+ dest_scan += dest_gap;
+ src_scan += src_gap;
+ }
+}
+inline void _CompositeRow_Rgb2Rgb_NoBlend_NoClip(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int dest_Bpp,
+ int src_Bpp) {
+ if (dest_Bpp == src_Bpp) {
+ FXSYS_memcpy(dest_scan, src_scan, width * dest_Bpp);
+ return;
+ }
+ for (int col = 0; col < width; col++) {
+ dest_scan[0] = src_scan[0];
+ dest_scan[1] = src_scan[1];
+ dest_scan[2] = src_scan[2];
+ dest_scan += dest_Bpp;
+ src_scan += src_Bpp;
+ }
+}
+inline void _CompositeRow_Rgb2Rgb_NoBlend_Clip(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int dest_Bpp,
+ int src_Bpp,
+ const uint8_t* clip_scan) {
+ for (int col = 0; col < width; col++) {
+ int src_alpha = clip_scan[col];
+ if (src_alpha == 255) {
+ dest_scan[0] = src_scan[0];
+ dest_scan[1] = src_scan[1];
+ dest_scan[2] = src_scan[2];
+ } else if (src_alpha) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
+ dest_scan++;
+ src_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
+ dest_scan++;
+ src_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_scan, src_alpha);
+ dest_scan += dest_Bpp - 2;
+ src_scan += src_Bpp - 2;
+ continue;
+ }
+ dest_scan += dest_Bpp;
+ src_scan += src_Bpp;
+ }
+}
+void _CompositeRow_Argb2Argb_Transform(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int pixel_count,
+ int blend_type,
+ const uint8_t* clip_scan,
+ uint8_t* dest_alpha_scan,
+ const uint8_t* src_alpha_scan,
+ uint8_t* src_cache_scan,
+ void* pIccTransform) {
+ uint8_t* dp = src_cache_scan;
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ if (src_alpha_scan) {
+ if (dest_alpha_scan) {
+ pIccModule->TranslateScanline(pIccTransform, dp, src_scan, pixel_count);
+ } else {
+ for (int col = 0; col < pixel_count; col++) {
+ pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
+ dp[3] = *src_alpha_scan++;
+ src_scan += 3;
+ dp += 4;
+ }
+ src_alpha_scan = NULL;
+ }
+ } else {
+ if (dest_alpha_scan) {
+ int blended_colors[3];
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ for (int col = 0; col < pixel_count; col++) {
+ pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan,
+ 1);
+ uint8_t back_alpha = *dest_alpha_scan;
+ if (back_alpha == 0) {
+ if (clip_scan) {
+ int src_alpha = clip_scan[col] * src_scan[3] / 255;
+ *dest_alpha_scan = src_alpha;
+ *dest_scan++ = *src_cache_scan++;
+ *dest_scan++ = *src_cache_scan++;
+ *dest_scan++ = *src_cache_scan++;
+ } else {
+ *dest_alpha_scan = src_scan[3];
+ *dest_scan++ = *src_cache_scan++;
+ *dest_scan++ = *src_cache_scan++;
+ *dest_scan++ = *src_cache_scan++;
+ }
+ dest_alpha_scan++;
+ src_scan += 4;
+ continue;
+ }
+ uint8_t src_alpha;
+ if (clip_scan) {
+ src_alpha = clip_scan[col] * src_scan[3] / 255;
+ } else {
+ src_alpha = src_scan[3];
+ }
+ src_scan += 4;
+ if (src_alpha == 0) {
+ dest_scan += 3;
+ src_cache_scan += 3;
+ dest_alpha_scan++;
+ continue;
+ }
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ if (bNonseparableBlend) {
+ _RGB_Blend(blend_type, src_cache_scan, dest_scan, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ if (blend_type) {
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, *dest_scan, *src_cache_scan);
+ blended = FXDIB_ALPHA_MERGE(*src_cache_scan, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ } else {
+ *dest_scan =
+ FXDIB_ALPHA_MERGE(*dest_scan, *src_cache_scan, alpha_ratio);
+ }
+ dest_scan++;
+ src_cache_scan++;
+ }
+ }
+ return;
+ }
+ for (int col = 0; col < pixel_count; col++) {
+ pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
+ dp[3] = src_scan[3];
+ src_scan += 4;
+ dp += 4;
+ }
+ }
+ _CompositeRow_Argb2Argb(dest_scan, src_cache_scan, pixel_count, blend_type,
+ clip_scan, dest_alpha_scan, src_alpha_scan);
+}
+void _CompositeRow_Rgb2Argb_Blend_NoClip_Transform(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int blend_type,
+ int src_Bpp,
+ uint8_t* dest_alpha_scan,
+ uint8_t* src_cache_scan,
+ void* pIccTransform) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ if (src_Bpp == 3) {
+ pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan,
+ width);
+ } else {
+ uint8_t* dp = src_cache_scan;
+ for (int col = 0; col < width; col++) {
+ pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
+ src_scan += 4;
+ dp += 3;
+ }
+ }
+ _CompositeRow_Rgb2Argb_Blend_NoClip(dest_scan, src_cache_scan, width,
+ blend_type, 3, dest_alpha_scan);
+}
+inline void _CompositeRow_Rgb2Argb_Blend_Clip_Transform(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int blend_type,
+ int src_Bpp,
+ const uint8_t* clip_scan,
+ uint8_t* dest_alpha_scan,
+ uint8_t* src_cache_scan,
+ void* pIccTransform) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ if (src_Bpp == 3) {
+ pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan,
+ width);
+ } else {
+ uint8_t* dp = src_cache_scan;
+ for (int col = 0; col < width; col++) {
+ pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
+ src_scan += 4;
+ dp += 3;
+ }
+ }
+ _CompositeRow_Rgb2Argb_Blend_Clip(dest_scan, src_cache_scan, width,
+ blend_type, 3, clip_scan, dest_alpha_scan);
+}
+inline void _CompositeRow_Rgb2Argb_NoBlend_Clip_Transform(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int src_Bpp,
+ const uint8_t* clip_scan,
+ uint8_t* dest_alpha_scan,
+ uint8_t* src_cache_scan,
+ void* pIccTransform) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ if (src_Bpp == 3) {
+ pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan,
+ width);
+ } else {
+ uint8_t* dp = src_cache_scan;
+ for (int col = 0; col < width; col++) {
+ pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
+ src_scan += 4;
+ dp += 3;
+ }
+ }
+ _CompositeRow_Rgb2Argb_NoBlend_Clip(dest_scan, src_cache_scan, width, 3,
+ clip_scan, dest_alpha_scan);
+}
+inline void _CompositeRow_Rgb2Argb_NoBlend_NoClip_Transform(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int src_Bpp,
+ uint8_t* dest_alpha_scan,
+ uint8_t* src_cache_scan,
+ void* pIccTransform) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ if (src_Bpp == 3) {
+ pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan,
+ width);
+ } else {
+ uint8_t* dp = src_cache_scan;
+ for (int col = 0; col < width; col++) {
+ pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
+ src_scan += 4;
+ dp += 3;
+ }
+ }
+ _CompositeRow_Rgb2Argb_NoBlend_NoClip(dest_scan, src_cache_scan, width, 3,
+ dest_alpha_scan);
+}
+inline void _CompositeRow_Argb2Rgb_Blend_Transform(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int blend_type,
+ int dest_Bpp,
+ const uint8_t* clip_scan,
+ const uint8_t* src_alpha_scan,
+ uint8_t* src_cache_scan,
+ void* pIccTransform) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ if (src_alpha_scan) {
+ pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan,
+ width);
+ } else {
+ int blended_colors[3];
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int dest_gap = dest_Bpp - 3;
+ for (int col = 0; col < width; col++) {
+ pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1);
+ uint8_t src_alpha;
+ if (clip_scan) {
+ src_alpha = src_scan[3] * (*clip_scan++) / 255;
+ } else {
+ src_alpha = src_scan[3];
+ }
+ src_scan += 4;
+ if (src_alpha == 0) {
+ dest_scan += dest_Bpp;
+ src_cache_scan += 3;
+ continue;
+ }
+ if (bNonseparableBlend) {
+ _RGB_Blend(blend_type, src_cache_scan, dest_scan, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ int back_color = *dest_scan;
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, back_color, *src_cache_scan);
+ *dest_scan = FXDIB_ALPHA_MERGE(back_color, blended, src_alpha);
+ dest_scan++;
+ src_cache_scan++;
+ }
+ dest_scan += dest_gap;
+ }
+ return;
+ }
+ _CompositeRow_Argb2Rgb_Blend(dest_scan, src_cache_scan, width, blend_type,
+ dest_Bpp, clip_scan, src_alpha_scan);
+}
+inline void _CompositeRow_Argb2Rgb_NoBlend_Transform(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int dest_Bpp,
+ const uint8_t* clip_scan,
+ const uint8_t* src_alpha_scan,
+ uint8_t* src_cache_scan,
+ void* pIccTransform) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ if (src_alpha_scan) {
+ pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan,
+ width);
+ } else {
+ int dest_gap = dest_Bpp - 3;
+ for (int col = 0; col < width; col++) {
+ pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan, 1);
+ uint8_t src_alpha;
+ if (clip_scan) {
+ src_alpha = src_scan[3] * (*clip_scan++) / 255;
+ } else {
+ src_alpha = src_scan[3];
+ }
+ src_scan += 4;
+ if (src_alpha == 255) {
+ *dest_scan++ = *src_cache_scan++;
+ *dest_scan++ = *src_cache_scan++;
+ *dest_scan++ = *src_cache_scan++;
+ dest_scan += dest_gap;
+ continue;
+ }
+ if (src_alpha == 0) {
+ dest_scan += dest_Bpp;
+ src_cache_scan += 3;
+ continue;
+ }
+ for (int color = 0; color < 3; color++) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, *src_cache_scan, src_alpha);
+ dest_scan++;
+ src_cache_scan++;
+ }
+ dest_scan += dest_gap;
+ }
+ return;
+ }
+ _CompositeRow_Argb2Rgb_NoBlend(dest_scan, src_cache_scan, width, dest_Bpp,
+ clip_scan, src_alpha_scan);
+}
+inline void _CompositeRow_Rgb2Rgb_Blend_NoClip_Transform(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int blend_type,
+ int dest_Bpp,
+ int src_Bpp,
+ uint8_t* src_cache_scan,
+ void* pIccTransform) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ if (src_Bpp == 3) {
+ pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan,
+ width);
+ } else {
+ uint8_t* dp = src_cache_scan;
+ for (int col = 0; col < width; col++) {
+ pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
+ src_scan += 4;
+ dp += 3;
+ }
+ }
+ _CompositeRow_Rgb2Rgb_Blend_NoClip(dest_scan, src_cache_scan, width,
+ blend_type, dest_Bpp, 3);
+}
+inline void _CompositeRow_Rgb2Rgb_Blend_Clip_Transform(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int blend_type,
+ int dest_Bpp,
+ int src_Bpp,
+ const uint8_t* clip_scan,
+ uint8_t* src_cache_scan,
+ void* pIccTransform) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ if (src_Bpp == 3) {
+ pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan,
+ width);
+ } else {
+ uint8_t* dp = src_cache_scan;
+ for (int col = 0; col < width; col++) {
+ pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
+ src_scan += 4;
+ dp += 3;
+ }
+ }
+ _CompositeRow_Rgb2Rgb_Blend_Clip(dest_scan, src_cache_scan, width, blend_type,
+ dest_Bpp, 3, clip_scan);
+}
+inline void _CompositeRow_Rgb2Rgb_NoBlend_NoClip_Transform(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int dest_Bpp,
+ int src_Bpp,
+ uint8_t* src_cache_scan,
+ void* pIccTransform) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ if (src_Bpp == 3) {
+ pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan,
+ width);
+ } else {
+ uint8_t* dp = src_cache_scan;
+ for (int col = 0; col < width; col++) {
+ pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
+ src_scan += 4;
+ dp += 3;
+ }
+ }
+ _CompositeRow_Rgb2Rgb_NoBlend_NoClip(dest_scan, src_cache_scan, width,
+ dest_Bpp, 3);
+}
+inline void _CompositeRow_Rgb2Rgb_NoBlend_Clip_Transform(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int dest_Bpp,
+ int src_Bpp,
+ const uint8_t* clip_scan,
+ uint8_t* src_cache_scan,
+ void* pIccTransform) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ if (src_Bpp == 3) {
+ pIccModule->TranslateScanline(pIccTransform, src_cache_scan, src_scan,
+ width);
+ } else {
+ uint8_t* dp = src_cache_scan;
+ for (int col = 0; col < width; col++) {
+ pIccModule->TranslateScanline(pIccTransform, dp, src_scan, 1);
+ src_scan += 4;
+ dp += 3;
+ }
+ }
+ _CompositeRow_Rgb2Rgb_NoBlend_Clip(dest_scan, src_cache_scan, width, dest_Bpp,
+ 3, clip_scan);
+}
+inline void _CompositeRow_8bppPal2Gray(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ const uint8_t* pPalette,
+ int pixel_count,
+ int blend_type,
+ const uint8_t* clip_scan,
+ const uint8_t* src_alpha_scan) {
+ if (src_alpha_scan) {
+ if (blend_type) {
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int blended_color;
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t gray = pPalette[*src_scan];
+ int src_alpha = *src_alpha_scan++;
+ if (clip_scan) {
+ src_alpha = clip_scan[col] * src_alpha / 255;
+ }
+ if (bNonseparableBlend) {
+ blended_color =
+ blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
+ }
+ gray = bNonseparableBlend ? blended_color
+ : _BLEND(blend_type, *dest_scan, gray);
+ if (src_alpha) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
+ } else {
+ *dest_scan = gray;
+ }
+ dest_scan++;
+ src_scan++;
+ }
+ return;
+ }
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t gray = pPalette[*src_scan];
+ int src_alpha = *src_alpha_scan++;
+ if (clip_scan) {
+ src_alpha = clip_scan[col] * src_alpha / 255;
+ }
+ if (src_alpha) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
+ } else {
+ *dest_scan = gray;
+ }
+ dest_scan++;
+ src_scan++;
+ }
+ } else {
+ if (blend_type) {
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int blended_color;
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t gray = pPalette[*src_scan];
+ if (bNonseparableBlend) {
+ blended_color =
+ blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
+ }
+ gray = bNonseparableBlend ? blended_color
+ : _BLEND(blend_type, *dest_scan, gray);
+ if (clip_scan && clip_scan[col] < 255) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
+ } else {
+ *dest_scan = gray;
+ }
+ dest_scan++;
+ src_scan++;
+ }
+ return;
+ }
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t gray = pPalette[*src_scan];
+ if (clip_scan && clip_scan[col] < 255) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
+ } else {
+ *dest_scan = gray;
+ }
+ dest_scan++;
+ src_scan++;
+ }
+ }
+}
+inline void _CompositeRow_8bppPal2Graya(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ const uint8_t* pPalette,
+ int pixel_count,
+ int blend_type,
+ const uint8_t* clip_scan,
+ uint8_t* dest_alpha_scan,
+ const uint8_t* src_alpha_scan) {
+ if (src_alpha_scan) {
+ if (blend_type) {
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int blended_color;
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t gray = pPalette[*src_scan];
+ src_scan++;
+ uint8_t back_alpha = *dest_alpha_scan;
+ if (back_alpha == 0) {
+ int src_alpha = *src_alpha_scan++;
+ if (clip_scan) {
+ src_alpha = clip_scan[col] * src_alpha / 255;
+ }
+ if (src_alpha) {
+ *dest_scan = gray;
+ *dest_alpha_scan = src_alpha;
+ }
+ dest_scan++;
+ dest_alpha_scan++;
+ continue;
+ }
+ uint8_t src_alpha = *src_alpha_scan++;
+ if (clip_scan) {
+ src_alpha = clip_scan[col] * src_alpha / 255;
+ }
+ if (src_alpha == 0) {
+ dest_scan++;
+ dest_alpha_scan++;
+ continue;
+ }
+ *dest_alpha_scan =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ int alpha_ratio = src_alpha * 255 / (*dest_alpha_scan);
+ if (bNonseparableBlend) {
+ blended_color =
+ blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
+ }
+ gray = bNonseparableBlend ? blended_color
+ : _BLEND(blend_type, *dest_scan, gray);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
+ dest_alpha_scan++;
+ dest_scan++;
+ }
+ return;
+ }
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t gray = pPalette[*src_scan];
+ src_scan++;
+ uint8_t back_alpha = *dest_alpha_scan;
+ if (back_alpha == 0) {
+ int src_alpha = *src_alpha_scan++;
+ if (clip_scan) {
+ src_alpha = clip_scan[col] * src_alpha / 255;
+ }
+ if (src_alpha) {
+ *dest_scan = gray;
+ *dest_alpha_scan = src_alpha;
+ }
+ dest_scan++;
+ dest_alpha_scan++;
+ continue;
+ }
+ uint8_t src_alpha = *src_alpha_scan++;
+ if (clip_scan) {
+ src_alpha = clip_scan[col] * src_alpha / 255;
+ }
+ if (src_alpha == 0) {
+ dest_scan++;
+ dest_alpha_scan++;
+ continue;
+ }
+ *dest_alpha_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ int alpha_ratio = src_alpha * 255 / (*dest_alpha_scan);
+ dest_alpha_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
+ dest_scan++;
+ }
+ } else {
+ if (blend_type) {
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int blended_color;
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t gray = pPalette[*src_scan];
+ src_scan++;
+ if (!clip_scan || clip_scan[col] == 255) {
+ *dest_scan++ = gray;
+ *dest_alpha_scan++ = 255;
+ continue;
+ }
+ int src_alpha = clip_scan[col];
+ if (src_alpha == 0) {
+ dest_scan++;
+ dest_alpha_scan++;
+ continue;
+ }
+ int back_alpha = *dest_alpha_scan;
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ if (bNonseparableBlend) {
+ blended_color =
+ blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
+ }
+ gray = bNonseparableBlend ? blended_color
+ : _BLEND(blend_type, *dest_scan, gray);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
+ dest_scan++;
+ }
+ return;
+ }
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t gray = pPalette[*src_scan];
+ src_scan++;
+ if (!clip_scan || clip_scan[col] == 255) {
+ *dest_scan++ = gray;
+ *dest_alpha_scan++ = 255;
+ continue;
+ }
+ int src_alpha = clip_scan[col];
+ if (src_alpha == 0) {
+ dest_scan++;
+ dest_alpha_scan++;
+ continue;
+ }
+ int back_alpha = *dest_alpha_scan;
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
+ dest_scan++;
+ }
+ }
+}
+inline void _CompositeRow_1bppPal2Gray(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int src_left,
+ const uint8_t* pPalette,
+ int pixel_count,
+ int blend_type,
+ const uint8_t* clip_scan) {
+ int reset_gray = pPalette[0];
+ int set_gray = pPalette[1];
+ if (blend_type) {
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int blended_color;
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t gray =
+ (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8)))
+ ? set_gray
+ : reset_gray;
+ if (bNonseparableBlend) {
+ blended_color =
+ blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
+ }
+ gray = bNonseparableBlend ? blended_color
+ : _BLEND(blend_type, *dest_scan, gray);
+ if (clip_scan && clip_scan[col] < 255) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
+ } else {
+ *dest_scan = gray;
+ }
+ dest_scan++;
+ }
+ return;
+ }
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t gray =
+ (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8)))
+ ? set_gray
+ : reset_gray;
+ if (clip_scan && clip_scan[col] < 255) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
+ } else {
+ *dest_scan = gray;
+ }
+ dest_scan++;
+ }
+}
+inline void _CompositeRow_1bppPal2Graya(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int src_left,
+ const uint8_t* pPalette,
+ int pixel_count,
+ int blend_type,
+ const uint8_t* clip_scan,
+ uint8_t* dest_alpha_scan) {
+ int reset_gray = pPalette[0];
+ int set_gray = pPalette[1];
+ if (blend_type) {
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int blended_color;
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t gray =
+ (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8)))
+ ? set_gray
+ : reset_gray;
+ if (!clip_scan || clip_scan[col] == 255) {
+ *dest_scan++ = gray;
+ *dest_alpha_scan++ = 255;
+ continue;
+ }
+ int src_alpha = clip_scan[col];
+ if (src_alpha == 0) {
+ dest_scan++;
+ dest_alpha_scan++;
+ continue;
+ }
+ int back_alpha = *dest_alpha_scan;
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ if (bNonseparableBlend) {
+ blended_color =
+ blend_type == FXDIB_BLEND_LUMINOSITY ? gray : *dest_scan;
+ }
+ gray = bNonseparableBlend ? blended_color
+ : _BLEND(blend_type, *dest_scan, gray);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
+ dest_scan++;
+ }
+ return;
+ }
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t gray =
+ (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8)))
+ ? set_gray
+ : reset_gray;
+ if (!clip_scan || clip_scan[col] == 255) {
+ *dest_scan++ = gray;
+ *dest_alpha_scan++ = 255;
+ continue;
+ }
+ int src_alpha = clip_scan[col];
+ if (src_alpha == 0) {
+ dest_scan++;
+ dest_alpha_scan++;
+ continue;
+ }
+ int back_alpha = *dest_alpha_scan;
+ uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, alpha_ratio);
+ dest_scan++;
+ }
+}
+inline void _CompositeRow_8bppRgb2Rgb_NoBlend(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ FX_DWORD* pPalette,
+ int pixel_count,
+ int DestBpp,
+ const uint8_t* clip_scan,
+ const uint8_t* src_alpha_scan) {
+ if (src_alpha_scan) {
+ int dest_gap = DestBpp - 3;
+ FX_ARGB argb = 0;
+ for (int col = 0; col < pixel_count; col++) {
+ argb = pPalette[*src_scan];
+ int src_r = FXARGB_R(argb);
+ int src_g = FXARGB_G(argb);
+ int src_b = FXARGB_B(argb);
+ src_scan++;
+ uint8_t src_alpha = 0;
+ if (clip_scan) {
+ src_alpha = (*src_alpha_scan++) * (*clip_scan++) / 255;
+ } else {
+ src_alpha = *src_alpha_scan++;
+ }
+ if (src_alpha == 255) {
+ *dest_scan++ = src_b;
+ *dest_scan++ = src_g;
+ *dest_scan++ = src_r;
+ dest_scan += dest_gap;
+ continue;
+ }
+ if (src_alpha == 0) {
+ dest_scan += DestBpp;
+ continue;
+ }
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha);
+ dest_scan++;
+ dest_scan += dest_gap;
+ }
+ } else {
+ FX_ARGB argb = 0;
+ for (int col = 0; col < pixel_count; col++) {
+ argb = pPalette[*src_scan];
+ int src_r = FXARGB_R(argb);
+ int src_g = FXARGB_G(argb);
+ int src_b = FXARGB_B(argb);
+ if (clip_scan && clip_scan[col] < 255) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, clip_scan[col]);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, clip_scan[col]);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, clip_scan[col]);
+ dest_scan++;
+ } else {
+ *dest_scan++ = src_b;
+ *dest_scan++ = src_g;
+ *dest_scan++ = src_r;
+ }
+ if (DestBpp == 4) {
+ dest_scan++;
+ }
+ src_scan++;
+ }
+ }
+}
+inline void _CompositeRow_1bppRgb2Rgb_NoBlend(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int src_left,
+ FX_DWORD* pPalette,
+ int pixel_count,
+ int DestBpp,
+ const uint8_t* clip_scan) {
+ int reset_r, reset_g, reset_b;
+ int set_r, set_g, set_b;
+ reset_r = FXARGB_R(pPalette[0]);
+ reset_g = FXARGB_G(pPalette[0]);
+ reset_b = FXARGB_B(pPalette[0]);
+ set_r = FXARGB_R(pPalette[1]);
+ set_g = FXARGB_G(pPalette[1]);
+ set_b = FXARGB_B(pPalette[1]);
+ for (int col = 0; col < pixel_count; col++) {
+ int src_r, src_g, src_b;
+ if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
+ src_r = set_r;
+ src_g = set_g;
+ src_b = set_b;
+ } else {
+ src_r = reset_r;
+ src_g = reset_g;
+ src_b = reset_b;
+ }
+ if (clip_scan && clip_scan[col] < 255) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, clip_scan[col]);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, clip_scan[col]);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, clip_scan[col]);
+ dest_scan++;
+ } else {
+ *dest_scan++ = src_b;
+ *dest_scan++ = src_g;
+ *dest_scan++ = src_r;
+ }
+ if (DestBpp == 4) {
+ dest_scan++;
+ }
+ }
+}
+inline void _CompositeRow_8bppRgb2Argb_NoBlend(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ FX_DWORD* pPalette,
+ const uint8_t* clip_scan,
+ const uint8_t* src_alpha_scan) {
+ if (src_alpha_scan) {
+ for (int col = 0; col < width; col++) {
+ FX_ARGB argb = pPalette[*src_scan];
+ src_scan++;
+ int src_r = FXARGB_R(argb);
+ int src_g = FXARGB_G(argb);
+ int src_b = FXARGB_B(argb);
+ uint8_t back_alpha = dest_scan[3];
+ if (back_alpha == 0) {
+ if (clip_scan) {
+ int src_alpha = clip_scan[col] * (*src_alpha_scan) / 255;
+ FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
+ } else {
+ FXARGB_SETDIB(dest_scan,
+ FXARGB_MAKE(*src_alpha_scan, src_r, src_g, src_b));
+ }
+ dest_scan += 4;
+ src_alpha_scan++;
+ continue;
+ }
+ uint8_t src_alpha;
+ if (clip_scan) {
+ src_alpha = clip_scan[col] * (*src_alpha_scan++) / 255;
+ } else {
+ src_alpha = *src_alpha_scan++;
+ }
+ if (src_alpha == 0) {
+ dest_scan += 4;
+ continue;
+ }
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ dest_scan[3] = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
+ dest_scan++;
+ dest_scan++;
+ }
+ } else {
+ for (int col = 0; col < width; col++) {
+ FX_ARGB argb = pPalette[*src_scan];
+ int src_r = FXARGB_R(argb);
+ int src_g = FXARGB_G(argb);
+ int src_b = FXARGB_B(argb);
+ if (!clip_scan || clip_scan[col] == 255) {
+ *dest_scan++ = src_b;
+ *dest_scan++ = src_g;
+ *dest_scan++ = src_r;
+ *dest_scan++ = 255;
+ src_scan++;
+ continue;
+ }
+ int src_alpha = clip_scan[col];
+ if (src_alpha == 0) {
+ dest_scan += 4;
+ src_scan++;
+ continue;
+ }
+ int back_alpha = dest_scan[3];
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ dest_scan[3] = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
+ dest_scan++;
+ dest_scan++;
+ src_scan++;
+ }
+ }
+}
+
+void _CompositeRow_8bppRgb2Rgba_NoBlend(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ FX_DWORD* pPalette,
+ const uint8_t* clip_scan,
+ uint8_t* dest_alpha_scan,
+ const uint8_t* src_alpha_scan) {
+ if (src_alpha_scan) {
+ for (int col = 0; col < width; col++) {
+ FX_ARGB argb = pPalette[*src_scan];
+ src_scan++;
+ int src_r = FXARGB_R(argb);
+ int src_g = FXARGB_G(argb);
+ int src_b = FXARGB_B(argb);
+ uint8_t back_alpha = *dest_alpha_scan;
+ if (back_alpha == 0) {
+ if (clip_scan) {
+ int src_alpha = clip_scan[col] * (*src_alpha_scan) / 255;
+ *dest_alpha_scan++ = src_alpha;
+ } else {
+ *dest_alpha_scan++ = *src_alpha_scan;
+ }
+ *dest_scan++ = src_b;
+ *dest_scan++ = src_g;
+ *dest_scan++ = src_r;
+ src_alpha_scan++;
+ continue;
+ }
+ uint8_t src_alpha;
+ if (clip_scan) {
+ src_alpha = clip_scan[col] * (*src_alpha_scan++) / 255;
+ } else {
+ src_alpha = *src_alpha_scan++;
+ }
+ if (src_alpha == 0) {
+ dest_scan += 3;
+ dest_alpha_scan++;
+ continue;
+ }
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
+ dest_scan++;
+ }
+ } else {
+ for (int col = 0; col < width; col++) {
+ FX_ARGB argb = pPalette[*src_scan];
+ int src_r = FXARGB_R(argb);
+ int src_g = FXARGB_G(argb);
+ int src_b = FXARGB_B(argb);
+ if (!clip_scan || clip_scan[col] == 255) {
+ *dest_scan++ = src_b;
+ *dest_scan++ = src_g;
+ *dest_scan++ = src_r;
+ *dest_alpha_scan++ = 255;
+ src_scan++;
+ continue;
+ }
+ int src_alpha = clip_scan[col];
+ if (src_alpha == 0) {
+ dest_scan += 3;
+ dest_alpha_scan++;
+ src_scan++;
+ continue;
+ }
+ int back_alpha = *dest_alpha_scan;
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
+ dest_scan++;
+ src_scan++;
+ }
+ }
+}
+
+inline void _CompositeRow_1bppRgb2Argb_NoBlend(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int src_left,
+ int width,
+ FX_DWORD* pPalette,
+ const uint8_t* clip_scan) {
+ int reset_r, reset_g, reset_b;
+ int set_r, set_g, set_b;
+ reset_r = FXARGB_R(pPalette[0]);
+ reset_g = FXARGB_G(pPalette[0]);
+ reset_b = FXARGB_B(pPalette[0]);
+ set_r = FXARGB_R(pPalette[1]);
+ set_g = FXARGB_G(pPalette[1]);
+ set_b = FXARGB_B(pPalette[1]);
+ for (int col = 0; col < width; col++) {
+ int src_r, src_g, src_b;
+ if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
+ src_r = set_r;
+ src_g = set_g;
+ src_b = set_b;
+ } else {
+ src_r = reset_r;
+ src_g = reset_g;
+ src_b = reset_b;
+ }
+ if (!clip_scan || clip_scan[col] == 255) {
+ *dest_scan++ = src_b;
+ *dest_scan++ = src_g;
+ *dest_scan++ = src_r;
+ *dest_scan++ = 255;
+ continue;
+ }
+ int src_alpha = clip_scan[col];
+ if (src_alpha == 0) {
+ dest_scan += 4;
+ continue;
+ }
+ int back_alpha = dest_scan[3];
+ uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ dest_scan[3] = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
+ dest_scan++;
+ dest_scan++;
+ }
+}
+void _CompositeRow_1bppRgb2Rgba_NoBlend(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int src_left,
+ int width,
+ FX_DWORD* pPalette,
+ const uint8_t* clip_scan,
+ uint8_t* dest_alpha_scan) {
+ int reset_r, reset_g, reset_b;
+ int set_r, set_g, set_b;
+ reset_r = FXARGB_R(pPalette[0]);
+ reset_g = FXARGB_G(pPalette[0]);
+ reset_b = FXARGB_B(pPalette[0]);
+ set_r = FXARGB_R(pPalette[1]);
+ set_g = FXARGB_G(pPalette[1]);
+ set_b = FXARGB_B(pPalette[1]);
+ for (int col = 0; col < width; col++) {
+ int src_r, src_g, src_b;
+ if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
+ src_r = set_r;
+ src_g = set_g;
+ src_b = set_b;
+ } else {
+ src_r = reset_r;
+ src_g = reset_g;
+ src_b = reset_b;
+ }
+ if (!clip_scan || clip_scan[col] == 255) {
+ *dest_scan++ = src_b;
+ *dest_scan++ = src_g;
+ *dest_scan++ = src_r;
+ *dest_alpha_scan++ = 255;
+ continue;
+ }
+ int src_alpha = clip_scan[col];
+ if (src_alpha == 0) {
+ dest_scan += 3;
+ dest_alpha_scan++;
+ continue;
+ }
+ int back_alpha = *dest_alpha_scan;
+ uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
+ dest_scan++;
+ }
+}
+void _CompositeRow_ByteMask2Argb(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int mask_alpha,
+ int src_r,
+ int src_g,
+ int src_b,
+ int pixel_count,
+ int blend_type,
+ const uint8_t* clip_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ int src_alpha;
+ if (clip_scan) {
+ src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
+ } else {
+ src_alpha = mask_alpha * src_scan[col] / 255;
+ }
+ uint8_t back_alpha = dest_scan[3];
+ if (back_alpha == 0) {
+ FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
+ dest_scan += 4;
+ continue;
+ }
+ if (src_alpha == 0) {
+ dest_scan += 4;
+ continue;
+ }
+ uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ dest_scan[3] = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
+ int blended_colors[3];
+ uint8_t src_scan[3];
+ src_scan[0] = src_b;
+ src_scan[1] = src_g;
+ src_scan[2] = src_r;
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ *dest_scan =
+ FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio);
+ dest_scan++;
+ *dest_scan =
+ FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio);
+ dest_scan++;
+ *dest_scan =
+ FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio);
+ } else if (blend_type) {
+ int blended = _BLEND(blend_type, *dest_scan, src_b);
+ blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ dest_scan++;
+ blended = _BLEND(blend_type, *dest_scan, src_g);
+ blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ dest_scan++;
+ blended = _BLEND(blend_type, *dest_scan, src_r);
+ blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ } else {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
+ }
+ dest_scan += 2;
+ }
+}
+void _CompositeRow_ByteMask2Rgba(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int mask_alpha,
+ int src_r,
+ int src_g,
+ int src_b,
+ int pixel_count,
+ int blend_type,
+ const uint8_t* clip_scan,
+ uint8_t* dest_alpha_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ int src_alpha;
+ if (clip_scan) {
+ src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
+ } else {
+ src_alpha = mask_alpha * src_scan[col] / 255;
+ }
+ uint8_t back_alpha = *dest_alpha_scan;
+ if (back_alpha == 0) {
+ *dest_scan++ = src_b;
+ *dest_scan++ = src_g;
+ *dest_scan++ = src_r;
+ *dest_alpha_scan++ = src_alpha;
+ continue;
+ }
+ if (src_alpha == 0) {
+ dest_scan += 3;
+ dest_alpha_scan++;
+ continue;
+ }
+ uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
+ int blended_colors[3];
+ uint8_t src_scan[3];
+ src_scan[0] = src_b;
+ src_scan[1] = src_g;
+ src_scan[2] = src_r;
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ *dest_scan =
+ FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio);
+ dest_scan++;
+ *dest_scan =
+ FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio);
+ dest_scan++;
+ *dest_scan =
+ FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio);
+ dest_scan++;
+ } else if (blend_type) {
+ int blended = _BLEND(blend_type, *dest_scan, src_b);
+ blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ dest_scan++;
+ blended = _BLEND(blend_type, *dest_scan, src_g);
+ blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ dest_scan++;
+ blended = _BLEND(blend_type, *dest_scan, src_r);
+ blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ dest_scan++;
+ } else {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
+ dest_scan++;
+ }
+ }
+}
+void _CompositeRow_ByteMask2Rgb(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int mask_alpha,
+ int src_r,
+ int src_g,
+ int src_b,
+ int pixel_count,
+ int blend_type,
+ int Bpp,
+ const uint8_t* clip_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ int src_alpha;
+ if (clip_scan) {
+ src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
+ } else {
+ src_alpha = mask_alpha * src_scan[col] / 255;
+ }
+ if (src_alpha == 0) {
+ dest_scan += Bpp;
+ continue;
+ }
+ if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
+ int blended_colors[3];
+ uint8_t src_scan[3];
+ src_scan[0] = src_b;
+ src_scan[1] = src_g;
+ src_scan[2] = src_r;
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], src_alpha);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], src_alpha);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], src_alpha);
+ } else if (blend_type) {
+ int blended = _BLEND(blend_type, *dest_scan, src_b);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
+ dest_scan++;
+ blended = _BLEND(blend_type, *dest_scan, src_g);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
+ dest_scan++;
+ blended = _BLEND(blend_type, *dest_scan, src_r);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
+ } else {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha);
+ }
+ dest_scan += Bpp - 2;
+ }
+}
+void _CompositeRow_ByteMask2Mask(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int mask_alpha,
+ int pixel_count,
+ const uint8_t* clip_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ int src_alpha;
+ if (clip_scan) {
+ src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
+ } else {
+ src_alpha = mask_alpha * src_scan[col] / 255;
+ }
+ uint8_t back_alpha = *dest_scan;
+ if (!back_alpha) {
+ *dest_scan = src_alpha;
+ } else if (src_alpha) {
+ *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ }
+ dest_scan++;
+ }
+}
+void _CompositeRow_ByteMask2Gray(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int mask_alpha,
+ int src_gray,
+ int pixel_count,
+ const uint8_t* clip_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ int src_alpha;
+ if (clip_scan) {
+ src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
+ } else {
+ src_alpha = mask_alpha * src_scan[col] / 255;
+ }
+ if (src_alpha) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, src_alpha);
+ }
+ dest_scan++;
+ }
+}
+void _CompositeRow_ByteMask2Graya(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int mask_alpha,
+ int src_gray,
+ int pixel_count,
+ const uint8_t* clip_scan,
+ uint8_t* dest_alpha_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ int src_alpha;
+ if (clip_scan) {
+ src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
+ } else {
+ src_alpha = mask_alpha * src_scan[col] / 255;
+ }
+ uint8_t back_alpha = *dest_alpha_scan;
+ if (back_alpha == 0) {
+ *dest_scan++ = src_gray;
+ *dest_alpha_scan++ = src_alpha;
+ continue;
+ }
+ if (src_alpha == 0) {
+ dest_scan++;
+ dest_alpha_scan++;
+ continue;
+ }
+ uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, alpha_ratio);
+ dest_scan++;
+ }
+}
+void _CompositeRow_BitMask2Argb(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int mask_alpha,
+ int src_r,
+ int src_g,
+ int src_b,
+ int src_left,
+ int pixel_count,
+ int blend_type,
+ const uint8_t* clip_scan) {
+ if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) {
+ FX_ARGB argb = FXARGB_MAKE(0xff, src_r, src_g, src_b);
+ for (int col = 0; col < pixel_count; col++) {
+ if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
+ FXARGB_SETDIB(dest_scan, argb);
+ }
+ dest_scan += 4;
+ }
+ return;
+ }
+ for (int col = 0; col < pixel_count; col++) {
+ if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
+ dest_scan += 4;
+ continue;
+ }
+ int src_alpha;
+ if (clip_scan) {
+ src_alpha = mask_alpha * clip_scan[col] / 255;
+ } else {
+ src_alpha = mask_alpha;
+ }
+ uint8_t back_alpha = dest_scan[3];
+ if (back_alpha == 0) {
+ FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
+ dest_scan += 4;
+ continue;
+ }
+ uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ dest_scan[3] = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
+ int blended_colors[3];
+ uint8_t src_scan[3];
+ src_scan[0] = src_b;
+ src_scan[1] = src_g;
+ src_scan[2] = src_r;
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ *dest_scan =
+ FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio);
+ dest_scan++;
+ *dest_scan =
+ FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio);
+ dest_scan++;
+ *dest_scan =
+ FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio);
+ } else if (blend_type) {
+ int blended = _BLEND(blend_type, *dest_scan, src_b);
+ blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ dest_scan++;
+ blended = _BLEND(blend_type, *dest_scan, src_g);
+ blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ dest_scan++;
+ blended = _BLEND(blend_type, *dest_scan, src_r);
+ blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ } else {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
+ }
+ dest_scan += 2;
+ }
+}
+void _CompositeRow_BitMask2Rgba(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int mask_alpha,
+ int src_r,
+ int src_g,
+ int src_b,
+ int src_left,
+ int pixel_count,
+ int blend_type,
+ const uint8_t* clip_scan,
+ uint8_t* dest_alpha_scan) {
+ if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) {
+ for (int col = 0; col < pixel_count; col++) {
+ if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
+ dest_scan[0] = src_b;
+ dest_scan[1] = src_g;
+ dest_scan[2] = src_r;
+ *dest_alpha_scan = mask_alpha;
+ }
+ dest_scan += 3;
+ dest_alpha_scan++;
+ }
+ return;
+ }
+ for (int col = 0; col < pixel_count; col++) {
+ if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
+ dest_scan += 3;
+ dest_alpha_scan++;
+ continue;
+ }
+ int src_alpha;
+ if (clip_scan) {
+ src_alpha = mask_alpha * clip_scan[col] / 255;
+ } else {
+ src_alpha = mask_alpha;
+ }
+ uint8_t back_alpha = dest_scan[3];
+ if (back_alpha == 0) {
+ *dest_scan++ = src_b;
+ *dest_scan++ = src_g;
+ *dest_scan++ = src_r;
+ *dest_alpha_scan++ = mask_alpha;
+ continue;
+ }
+ uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
+ int blended_colors[3];
+ uint8_t src_scan[3];
+ src_scan[0] = src_b;
+ src_scan[1] = src_g;
+ src_scan[2] = src_r;
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ *dest_scan =
+ FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], alpha_ratio);
+ dest_scan++;
+ *dest_scan =
+ FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], alpha_ratio);
+ dest_scan++;
+ *dest_scan =
+ FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], alpha_ratio);
+ dest_scan++;
+ } else if (blend_type) {
+ int blended = _BLEND(blend_type, *dest_scan, src_b);
+ blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ dest_scan++;
+ blended = _BLEND(blend_type, *dest_scan, src_g);
+ blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ dest_scan++;
+ blended = _BLEND(blend_type, *dest_scan, src_r);
+ blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, alpha_ratio);
+ dest_scan++;
+ } else {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
+ dest_scan++;
+ }
+ }
+}
+void _CompositeRow_BitMask2Rgb(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int mask_alpha,
+ int src_r,
+ int src_g,
+ int src_b,
+ int src_left,
+ int pixel_count,
+ int blend_type,
+ int Bpp,
+ const uint8_t* clip_scan) {
+ if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) {
+ for (int col = 0; col < pixel_count; col++) {
+ if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
+ dest_scan[2] = src_r;
+ dest_scan[1] = src_g;
+ dest_scan[0] = src_b;
+ }
+ dest_scan += Bpp;
+ }
+ return;
+ }
+ for (int col = 0; col < pixel_count; col++) {
+ if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
+ dest_scan += Bpp;
+ continue;
+ }
+ int src_alpha;
+ if (clip_scan) {
+ src_alpha = mask_alpha * clip_scan[col] / 255;
+ } else {
+ src_alpha = mask_alpha;
+ }
+ if (src_alpha == 0) {
+ dest_scan += Bpp;
+ continue;
+ }
+ if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
+ int blended_colors[3];
+ uint8_t src_scan[3];
+ src_scan[0] = src_b;
+ src_scan[1] = src_g;
+ src_scan[2] = src_r;
+ _RGB_Blend(blend_type, src_scan, dest_scan, blended_colors);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[0], src_alpha);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[1], src_alpha);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended_colors[2], src_alpha);
+ } else if (blend_type) {
+ int blended = _BLEND(blend_type, *dest_scan, src_b);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
+ dest_scan++;
+ blended = _BLEND(blend_type, *dest_scan, src_g);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
+ dest_scan++;
+ blended = _BLEND(blend_type, *dest_scan, src_r);
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, blended, src_alpha);
+ } else {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha);
+ }
+ dest_scan += Bpp - 2;
+ }
+}
+void _CompositeRow_BitMask2Mask(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int mask_alpha,
+ int src_left,
+ int pixel_count,
+ const uint8_t* clip_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
+ dest_scan++;
+ continue;
+ }
+ int src_alpha;
+ if (clip_scan) {
+ src_alpha = mask_alpha * clip_scan[col] / 255;
+ } else {
+ src_alpha = mask_alpha;
+ }
+ uint8_t back_alpha = *dest_scan;
+ if (!back_alpha) {
+ *dest_scan = src_alpha;
+ } else if (src_alpha) {
+ *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ }
+ dest_scan++;
+ }
+}
+void _CompositeRow_BitMask2Gray(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int mask_alpha,
+ int src_gray,
+ int src_left,
+ int pixel_count,
+ const uint8_t* clip_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
+ dest_scan++;
+ continue;
+ }
+ int src_alpha;
+ if (clip_scan) {
+ src_alpha = mask_alpha * clip_scan[col] / 255;
+ } else {
+ src_alpha = mask_alpha;
+ }
+ if (src_alpha) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, src_alpha);
+ }
+ dest_scan++;
+ }
+}
+void _CompositeRow_BitMask2Graya(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int mask_alpha,
+ int src_gray,
+ int src_left,
+ int pixel_count,
+ const uint8_t* clip_scan,
+ uint8_t* dest_alpha_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
+ dest_scan++;
+ dest_alpha_scan++;
+ continue;
+ }
+ int src_alpha;
+ if (clip_scan) {
+ src_alpha = mask_alpha * clip_scan[col] / 255;
+ } else {
+ src_alpha = mask_alpha;
+ }
+ uint8_t back_alpha = *dest_alpha_scan;
+ if (back_alpha == 0) {
+ *dest_scan++ = src_gray;
+ *dest_alpha_scan++ = src_alpha;
+ continue;
+ }
+ if (src_alpha == 0) {
+ dest_scan++;
+ dest_alpha_scan++;
+ continue;
+ }
+ uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_alpha_scan++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_gray, alpha_ratio);
+ dest_scan++;
+ }
+}
+void _CompositeRow_Argb2Argb_RgbByteOrder(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int pixel_count,
+ int blend_type,
+ const uint8_t* clip_scan) {
+ int blended_colors[3];
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ for (int col = 0; col < pixel_count; col++) {
+ uint8_t back_alpha = dest_scan[3];
+ if (back_alpha == 0) {
+ if (clip_scan) {
+ int src_alpha = clip_scan[col] * src_scan[3] / 255;
+ dest_scan[3] = src_alpha;
+ dest_scan[0] = src_scan[2];
+ dest_scan[1] = src_scan[1];
+ dest_scan[2] = src_scan[0];
+ } else {
+ FXARGB_RGBORDERCOPY(dest_scan, src_scan);
+ }
+ dest_scan += 4;
+ src_scan += 4;
+ continue;
+ }
+ uint8_t src_alpha;
+ if (clip_scan) {
+ src_alpha = clip_scan[col] * src_scan[3] / 255;
+ } else {
+ src_alpha = src_scan[3];
+ }
+ if (src_alpha == 0) {
+ dest_scan += 4;
+ src_scan += 4;
+ continue;
+ }
+ uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ dest_scan[3] = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ if (bNonseparableBlend) {
+ uint8_t dest_scan_o[3];
+ dest_scan_o[0] = dest_scan[2];
+ dest_scan_o[1] = dest_scan[1];
+ dest_scan_o[2] = dest_scan[0];
+ _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ int index = 2 - color;
+ if (blend_type) {
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, dest_scan[index], *src_scan);
+ blended = FXDIB_ALPHA_MERGE(*src_scan, blended, back_alpha);
+ dest_scan[index] =
+ FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio);
+ } else {
+ dest_scan[index] =
+ FXDIB_ALPHA_MERGE(dest_scan[index], *src_scan, alpha_ratio);
+ }
+ src_scan++;
+ }
+ dest_scan += 4;
+ src_scan++;
+ }
+}
+void _CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int blend_type,
+ int src_Bpp) {
+ int blended_colors[3];
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int src_gap = src_Bpp - 3;
+ for (int col = 0; col < width; col++) {
+ uint8_t back_alpha = dest_scan[3];
+ if (back_alpha == 0) {
+ if (src_Bpp == 4) {
+ FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
+ } else {
+ FXARGB_SETRGBORDERDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[2],
+ src_scan[1], src_scan[0]));
+ }
+ dest_scan += 4;
+ src_scan += src_Bpp;
+ continue;
+ }
+ dest_scan[3] = 0xff;
+ if (bNonseparableBlend) {
+ uint8_t dest_scan_o[3];
+ dest_scan_o[0] = dest_scan[2];
+ dest_scan_o[1] = dest_scan[1];
+ dest_scan_o[2] = dest_scan[0];
+ _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ int index = 2 - color;
+ int src_color = FX_GAMMA(*src_scan);
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, dest_scan[index], src_color);
+ dest_scan[index] = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
+ src_scan++;
+ }
+ dest_scan += 4;
+ src_scan += src_gap;
+ }
+}
+inline void _CompositeRow_Argb2Rgb_Blend_RgbByteOrder(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int blend_type,
+ int dest_Bpp,
+ const uint8_t* clip_scan) {
+ int blended_colors[3];
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ for (int col = 0; col < width; col++) {
+ uint8_t src_alpha;
+ if (clip_scan) {
+ src_alpha = src_scan[3] * (*clip_scan++) / 255;
+ } else {
+ src_alpha = src_scan[3];
+ }
+ if (src_alpha == 0) {
+ dest_scan += dest_Bpp;
+ src_scan += 4;
+ continue;
+ }
+ if (bNonseparableBlend) {
+ uint8_t dest_scan_o[3];
+ dest_scan_o[0] = dest_scan[2];
+ dest_scan_o[1] = dest_scan[1];
+ dest_scan_o[2] = dest_scan[0];
+ _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ int index = 2 - color;
+ int back_color = FX_GAMMA(dest_scan[index]);
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, back_color, *src_scan);
+ dest_scan[index] =
+ FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
+ src_scan++;
+ }
+ dest_scan += dest_Bpp;
+ src_scan++;
+ }
+}
+inline void _CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int src_Bpp) {
+ for (int col = 0; col < width; col++) {
+ if (src_Bpp == 4) {
+ FXARGB_SETRGBORDERDIB(dest_scan, 0xff000000 | FXARGB_GETDIB(src_scan));
+ } else {
+ FXARGB_SETRGBORDERDIB(
+ dest_scan, FXARGB_MAKE(0xff, src_scan[2], src_scan[1], src_scan[0]));
+ }
+ dest_scan += 4;
+ src_scan += src_Bpp;
+ }
+}
+inline void _CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int blend_type,
+ int dest_Bpp,
+ int src_Bpp) {
+ int blended_colors[3];
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int src_gap = src_Bpp - 3;
+ for (int col = 0; col < width; col++) {
+ if (bNonseparableBlend) {
+ uint8_t dest_scan_o[3];
+ dest_scan_o[0] = dest_scan[2];
+ dest_scan_o[1] = dest_scan[1];
+ dest_scan_o[2] = dest_scan[0];
+ _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ int index = 2 - color;
+ int back_color = FX_GAMMA(dest_scan[index]);
+ int src_color = FX_GAMMA(*src_scan);
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, back_color, src_color);
+ dest_scan[index] = FX_GAMMA_INVERSE(blended);
+ src_scan++;
+ }
+ dest_scan += dest_Bpp;
+ src_scan += src_gap;
+ }
+}
+inline void _CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int dest_Bpp,
+ const uint8_t* clip_scan) {
+ for (int col = 0; col < width; col++) {
+ uint8_t src_alpha;
+ if (clip_scan) {
+ src_alpha = src_scan[3] * (*clip_scan++) / 255;
+ } else {
+ src_alpha = src_scan[3];
+ }
+ if (src_alpha == 255) {
+ dest_scan[2] = FX_GAMMA_INVERSE(*src_scan++);
+ dest_scan[1] = FX_GAMMA_INVERSE(*src_scan++);
+ dest_scan[0] = FX_GAMMA_INVERSE(*src_scan++);
+ dest_scan += dest_Bpp;
+ src_scan++;
+ continue;
+ }
+ if (src_alpha == 0) {
+ dest_scan += dest_Bpp;
+ src_scan += 4;
+ continue;
+ }
+ for (int color = 0; color < 3; color++) {
+ int index = 2 - color;
+ dest_scan[index] = FX_GAMMA_INVERSE(
+ FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[index]), *src_scan, src_alpha));
+ src_scan++;
+ }
+ dest_scan += dest_Bpp;
+ src_scan++;
+ }
+}
+inline void _CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int dest_Bpp,
+ int src_Bpp) {
+ for (int col = 0; col < width; col++) {
+ dest_scan[2] = src_scan[0];
+ dest_scan[1] = src_scan[1];
+ dest_scan[0] = src_scan[2];
+ dest_scan += dest_Bpp;
+ src_scan += src_Bpp;
+ }
+}
+inline void _CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int blend_type,
+ int src_Bpp,
+ const uint8_t* clip_scan) {
+ int blended_colors[3];
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int src_gap = src_Bpp - 3;
+ for (int col = 0; col < width; col++) {
+ int src_alpha = *clip_scan++;
+ uint8_t back_alpha = dest_scan[3];
+ if (back_alpha == 0) {
+ dest_scan[2] = FX_GAMMA(*src_scan++);
+ dest_scan[1] = FX_GAMMA(*src_scan++);
+ dest_scan[0] = FX_GAMMA(*src_scan++);
+ src_scan += src_gap;
+ dest_scan += 4;
+ continue;
+ }
+ if (src_alpha == 0) {
+ dest_scan += 4;
+ src_scan += src_Bpp;
+ continue;
+ }
+ uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ dest_scan[3] = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ if (bNonseparableBlend) {
+ uint8_t dest_scan_o[3];
+ dest_scan_o[0] = dest_scan[2];
+ dest_scan_o[1] = dest_scan[1];
+ dest_scan_o[2] = dest_scan[0];
+ _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ int index = 2 - color;
+ int src_color = FX_GAMMA(*src_scan);
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, dest_scan[index], src_color);
+ blended = FXDIB_ALPHA_MERGE(src_color, blended, back_alpha);
+ dest_scan[index] =
+ FXDIB_ALPHA_MERGE(dest_scan[index], blended, alpha_ratio);
+ src_scan++;
+ }
+ dest_scan += 4;
+ src_scan += src_gap;
+ }
+}
+inline void _CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int blend_type,
+ int dest_Bpp,
+ int src_Bpp,
+ const uint8_t* clip_scan) {
+ int blended_colors[3];
+ FX_BOOL bNonseparableBlend = blend_type >= FXDIB_BLEND_NONSEPARABLE;
+ int src_gap = src_Bpp - 3;
+ for (int col = 0; col < width; col++) {
+ uint8_t src_alpha = *clip_scan++;
+ if (src_alpha == 0) {
+ dest_scan += dest_Bpp;
+ src_scan += src_Bpp;
+ continue;
+ }
+ if (bNonseparableBlend) {
+ uint8_t dest_scan_o[3];
+ dest_scan_o[0] = dest_scan[2];
+ dest_scan_o[1] = dest_scan[1];
+ dest_scan_o[2] = dest_scan[0];
+ _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
+ }
+ for (int color = 0; color < 3; color++) {
+ int index = 2 - color;
+ int src_color = FX_GAMMA(*src_scan);
+ int back_color = FX_GAMMA(dest_scan[index]);
+ int blended = bNonseparableBlend
+ ? blended_colors[color]
+ : _BLEND(blend_type, back_color, src_color);
+ dest_scan[index] =
+ FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
+ src_scan++;
+ }
+ dest_scan += dest_Bpp;
+ src_scan += src_gap;
+ }
+}
+inline void _CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int src_Bpp,
+ const uint8_t* clip_scan) {
+ int src_gap = src_Bpp - 3;
+ for (int col = 0; col < width; col++) {
+ int src_alpha = clip_scan[col];
+ if (src_alpha == 255) {
+ dest_scan[2] = FX_GAMMA(*src_scan++);
+ dest_scan[1] = FX_GAMMA(*src_scan++);
+ dest_scan[0] = FX_GAMMA(*src_scan++);
+ dest_scan[3] = 255;
+ dest_scan += 4;
+ src_scan += src_gap;
+ continue;
+ }
+ if (src_alpha == 0) {
+ dest_scan += 4;
+ src_scan += src_Bpp;
+ continue;
+ }
+ int back_alpha = dest_scan[3];
+ uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ dest_scan[3] = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ for (int color = 0; color < 3; color++) {
+ int index = 2 - color;
+ dest_scan[index] =
+ FXDIB_ALPHA_MERGE(dest_scan[index], FX_GAMMA(*src_scan), alpha_ratio);
+ src_scan++;
+ }
+ dest_scan += 4;
+ src_scan += src_gap;
+ }
+}
+inline void _CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ int dest_Bpp,
+ int src_Bpp,
+ const uint8_t* clip_scan) {
+ for (int col = 0; col < width; col++) {
+ int src_alpha = clip_scan[col];
+ if (src_alpha == 255) {
+ dest_scan[2] = src_scan[0];
+ dest_scan[1] = src_scan[1];
+ dest_scan[0] = src_scan[2];
+ } else if (src_alpha) {
+ dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(
+ FX_GAMMA(dest_scan[2]), FX_GAMMA(*src_scan), src_alpha));
+ src_scan++;
+ dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(
+ FX_GAMMA(dest_scan[1]), FX_GAMMA(*src_scan), src_alpha));
+ src_scan++;
+ dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(
+ FX_GAMMA(dest_scan[0]), FX_GAMMA(*src_scan), src_alpha));
+ dest_scan += dest_Bpp;
+ src_scan += src_Bpp - 2;
+ continue;
+ }
+ dest_scan += dest_Bpp;
+ src_scan += src_Bpp;
+ }
+}
+inline void _CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ FX_ARGB* pPalette,
+ int pixel_count,
+ int DestBpp,
+ const uint8_t* clip_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ FX_ARGB argb = pPalette ? pPalette[*src_scan] : (*src_scan) * 0x010101;
+ int src_r = FXARGB_R(argb);
+ int src_g = FXARGB_G(argb);
+ int src_b = FXARGB_B(argb);
+ if (clip_scan && clip_scan[col] < 255) {
+ dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]);
+ dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]);
+ dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]);
+ } else {
+ dest_scan[2] = src_b;
+ dest_scan[1] = src_g;
+ dest_scan[0] = src_r;
+ }
+ dest_scan += DestBpp;
+ src_scan++;
+ }
+}
+inline void _CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int src_left,
+ FX_ARGB* pPalette,
+ int pixel_count,
+ int DestBpp,
+ const uint8_t* clip_scan) {
+ int reset_r, reset_g, reset_b;
+ int set_r, set_g, set_b;
+ if (pPalette) {
+ reset_r = FXARGB_R(pPalette[0]);
+ reset_g = FXARGB_G(pPalette[0]);
+ reset_b = FXARGB_B(pPalette[0]);
+ set_r = FXARGB_R(pPalette[1]);
+ set_g = FXARGB_G(pPalette[1]);
+ set_b = FXARGB_B(pPalette[1]);
+ } else {
+ reset_r = reset_g = reset_b = 0;
+ set_r = set_g = set_b = 255;
+ }
+ for (int col = 0; col < pixel_count; col++) {
+ int src_r, src_g, src_b;
+ if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
+ src_r = set_r;
+ src_g = set_g;
+ src_b = set_b;
+ } else {
+ src_r = reset_r;
+ src_g = reset_g;
+ src_b = reset_b;
+ }
+ if (clip_scan && clip_scan[col] < 255) {
+ dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, clip_scan[col]);
+ dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, clip_scan[col]);
+ dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, clip_scan[col]);
+ } else {
+ dest_scan[2] = src_b;
+ dest_scan[1] = src_g;
+ dest_scan[0] = src_r;
+ }
+ dest_scan += DestBpp;
+ }
+}
+inline void _CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ FX_ARGB* pPalette,
+ const uint8_t* clip_scan) {
+ for (int col = 0; col < width; col++) {
+ int src_r, src_g, src_b;
+ if (pPalette) {
+ FX_ARGB argb = pPalette[*src_scan];
+ src_r = FXARGB_R(argb);
+ src_g = FXARGB_G(argb);
+ src_b = FXARGB_B(argb);
+ } else {
+ src_r = src_g = src_b = *src_scan;
+ }
+ if (!clip_scan || clip_scan[col] == 255) {
+ dest_scan[2] = FX_GAMMA(src_b);
+ dest_scan[1] = FX_GAMMA(src_g);
+ dest_scan[0] = FX_GAMMA(src_r);
+ dest_scan[3] = 255;
+ src_scan++;
+ dest_scan += 4;
+ continue;
+ }
+ int src_alpha = clip_scan[col];
+ if (src_alpha == 0) {
+ dest_scan += 4;
+ src_scan++;
+ continue;
+ }
+ int back_alpha = dest_scan[3];
+ uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ dest_scan[3] = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ dest_scan[2] =
+ FXDIB_ALPHA_MERGE(dest_scan[2], FX_GAMMA(src_b), alpha_ratio);
+ dest_scan[1] =
+ FXDIB_ALPHA_MERGE(dest_scan[1], FX_GAMMA(src_g), alpha_ratio);
+ dest_scan[0] =
+ FXDIB_ALPHA_MERGE(dest_scan[0], FX_GAMMA(src_r), alpha_ratio);
+ dest_scan += 4;
+ src_scan++;
+ }
+}
+inline void _CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int src_left,
+ int width,
+ FX_ARGB* pPalette,
+ const uint8_t* clip_scan) {
+ int reset_r, reset_g, reset_b;
+ int set_r, set_g, set_b;
+ if (pPalette) {
+ reset_r = FXARGB_R(pPalette[0]);
+ reset_g = FXARGB_G(pPalette[0]);
+ reset_b = FXARGB_B(pPalette[0]);
+ set_r = FXARGB_R(pPalette[1]);
+ set_g = FXARGB_G(pPalette[1]);
+ set_b = FXARGB_B(pPalette[1]);
+ } else {
+ reset_r = reset_g = reset_b = 0;
+ set_r = set_g = set_b = 255;
+ }
+ for (int col = 0; col < width; col++) {
+ int src_r, src_g, src_b;
+ if (src_scan[(col + src_left) / 8] & (1 << (7 - (col + src_left) % 8))) {
+ src_r = set_r;
+ src_g = set_g;
+ src_b = set_b;
+ } else {
+ src_r = reset_r;
+ src_g = reset_g;
+ src_b = reset_b;
+ }
+ if (!clip_scan || clip_scan[col] == 255) {
+ dest_scan[2] = FX_GAMMA(src_b);
+ dest_scan[1] = FX_GAMMA(src_g);
+ dest_scan[0] = FX_GAMMA(src_r);
+ dest_scan[3] = 255;
+ dest_scan += 4;
+ continue;
+ }
+ int src_alpha = clip_scan[col];
+ if (src_alpha == 0) {
+ dest_scan += 4;
+ continue;
+ }
+ int back_alpha = dest_scan[3];
+ uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ dest_scan[3] = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ dest_scan[2] =
+ FXDIB_ALPHA_MERGE(dest_scan[2], FX_GAMMA(src_b), alpha_ratio);
+ dest_scan[1] =
+ FXDIB_ALPHA_MERGE(dest_scan[1], FX_GAMMA(src_g), alpha_ratio);
+ dest_scan[0] =
+ FXDIB_ALPHA_MERGE(dest_scan[0], FX_GAMMA(src_r), alpha_ratio);
+ dest_scan += 4;
+ }
+}
+void _CompositeRow_ByteMask2Argb_RgbByteOrder(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int mask_alpha,
+ int src_r,
+ int src_g,
+ int src_b,
+ int pixel_count,
+ int blend_type,
+ const uint8_t* clip_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ int src_alpha;
+ if (clip_scan) {
+ src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
+ } else {
+ src_alpha = mask_alpha * src_scan[col] / 255;
+ }
+ uint8_t back_alpha = dest_scan[3];
+ if (back_alpha == 0) {
+ FXARGB_SETRGBORDERDIB(dest_scan,
+ FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
+ dest_scan += 4;
+ continue;
+ }
+ if (src_alpha == 0) {
+ dest_scan += 4;
+ continue;
+ }
+ uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ dest_scan[3] = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
+ int blended_colors[3];
+ uint8_t src_scan[3];
+ uint8_t dest_scan_o[3];
+ src_scan[0] = src_b;
+ src_scan[1] = src_g;
+ src_scan[2] = src_r;
+ dest_scan_o[0] = dest_scan[2];
+ dest_scan_o[1] = dest_scan[1];
+ dest_scan_o[2] = dest_scan[0];
+ _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
+ dest_scan[2] =
+ FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio);
+ dest_scan[1] =
+ FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio);
+ dest_scan[0] =
+ FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio);
+ } else if (blend_type) {
+ int blended = _BLEND(blend_type, dest_scan[2], src_b);
+ blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
+ dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio);
+ blended = _BLEND(blend_type, dest_scan[1], src_g);
+ blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
+ dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio);
+ blended = _BLEND(blend_type, dest_scan[0], src_r);
+ blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
+ dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio);
+ } else {
+ dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio);
+ dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio);
+ dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio);
+ }
+ dest_scan += 4;
+ }
+}
+void _CompositeRow_ByteMask2Rgb_RgbByteOrder(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int mask_alpha,
+ int src_r,
+ int src_g,
+ int src_b,
+ int pixel_count,
+ int blend_type,
+ int Bpp,
+ const uint8_t* clip_scan) {
+ for (int col = 0; col < pixel_count; col++) {
+ int src_alpha;
+ if (clip_scan) {
+ src_alpha = mask_alpha * clip_scan[col] * src_scan[col] / 255 / 255;
+ } else {
+ src_alpha = mask_alpha * src_scan[col] / 255;
+ }
+ if (src_alpha == 0) {
+ dest_scan += Bpp;
+ continue;
+ }
+ if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
+ int blended_colors[3];
+ uint8_t src_scan[3];
+ uint8_t dest_scan_o[3];
+ src_scan[0] = src_b;
+ src_scan[1] = src_g;
+ src_scan[2] = src_r;
+ dest_scan_o[0] = dest_scan[2];
+ dest_scan_o[1] = dest_scan[1];
+ dest_scan_o[2] = dest_scan[0];
+ _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
+ dest_scan[2] =
+ FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha);
+ dest_scan[1] =
+ FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha);
+ dest_scan[0] =
+ FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha);
+ } else if (blend_type) {
+ int blended = _BLEND(blend_type, dest_scan[2], src_b);
+ dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, src_alpha);
+ blended = _BLEND(blend_type, dest_scan[1], src_g);
+ dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, src_alpha);
+ blended = _BLEND(blend_type, dest_scan[0], src_r);
+ dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, src_alpha);
+ } else {
+ dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, src_alpha);
+ dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, src_alpha);
+ dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, src_alpha);
+ }
+ dest_scan += Bpp;
+ }
+}
+void _CompositeRow_BitMask2Argb_RgbByteOrder(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int mask_alpha,
+ int src_r,
+ int src_g,
+ int src_b,
+ int src_left,
+ int pixel_count,
+ int blend_type,
+ const uint8_t* clip_scan) {
+ if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) {
+ FX_ARGB argb = FXARGB_MAKE(0xff, src_r, src_g, src_b);
+ for (int col = 0; col < pixel_count; col++) {
+ if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
+ FXARGB_SETRGBORDERDIB(dest_scan, argb);
+ }
+ dest_scan += 4;
+ }
+ return;
+ }
+ for (int col = 0; col < pixel_count; col++) {
+ if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
+ dest_scan += 4;
+ continue;
+ }
+ int src_alpha;
+ if (clip_scan) {
+ src_alpha = mask_alpha * clip_scan[col] / 255;
+ } else {
+ src_alpha = mask_alpha;
+ }
+ uint8_t back_alpha = dest_scan[3];
+ if (back_alpha == 0) {
+ FXARGB_SETRGBORDERDIB(dest_scan,
+ FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
+ dest_scan += 4;
+ continue;
+ }
+ uint8_t dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ dest_scan[3] = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
+ int blended_colors[3];
+ uint8_t src_scan[3];
+ uint8_t dest_scan_o[3];
+ src_scan[0] = src_b;
+ src_scan[1] = src_g;
+ src_scan[2] = src_r;
+ dest_scan_o[0] = dest_scan[2];
+ dest_scan_o[1] = dest_scan[1];
+ dest_scan_o[2] = dest_scan[0];
+ _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
+ dest_scan[2] =
+ FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], alpha_ratio);
+ dest_scan[1] =
+ FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], alpha_ratio);
+ dest_scan[0] =
+ FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], alpha_ratio);
+ } else if (blend_type) {
+ int blended = _BLEND(blend_type, dest_scan[2], src_b);
+ blended = FXDIB_ALPHA_MERGE(src_b, blended, back_alpha);
+ dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], blended, alpha_ratio);
+ blended = _BLEND(blend_type, dest_scan[1], src_g);
+ blended = FXDIB_ALPHA_MERGE(src_g, blended, back_alpha);
+ dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], blended, alpha_ratio);
+ blended = _BLEND(blend_type, dest_scan[0], src_r);
+ blended = FXDIB_ALPHA_MERGE(src_r, blended, back_alpha);
+ dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], blended, alpha_ratio);
+ } else {
+ dest_scan[2] = FXDIB_ALPHA_MERGE(dest_scan[2], src_b, alpha_ratio);
+ dest_scan[1] = FXDIB_ALPHA_MERGE(dest_scan[1], src_g, alpha_ratio);
+ dest_scan[0] = FXDIB_ALPHA_MERGE(dest_scan[0], src_r, alpha_ratio);
+ }
+ dest_scan += 4;
+ }
+}
+void _CompositeRow_BitMask2Rgb_RgbByteOrder(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int mask_alpha,
+ int src_r,
+ int src_g,
+ int src_b,
+ int src_left,
+ int pixel_count,
+ int blend_type,
+ int Bpp,
+ const uint8_t* clip_scan) {
+ if (blend_type == FXDIB_BLEND_NORMAL && !clip_scan && mask_alpha == 255) {
+ for (int col = 0; col < pixel_count; col++) {
+ if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {
+ dest_scan[2] = src_b;
+ dest_scan[1] = src_g;
+ dest_scan[0] = src_r;
+ }
+ dest_scan += Bpp;
+ }
+ return;
+ }
+ for (int col = 0; col < pixel_count; col++) {
+ if (!(src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8)))) {
+ dest_scan += Bpp;
+ continue;
+ }
+ int src_alpha;
+ if (clip_scan) {
+ src_alpha = mask_alpha * clip_scan[col] / 255;
+ } else {
+ src_alpha = mask_alpha;
+ }
+ if (src_alpha == 0) {
+ dest_scan += Bpp;
+ continue;
+ }
+ if (blend_type >= FXDIB_BLEND_NONSEPARABLE) {
+ int blended_colors[3];
+ uint8_t src_scan[3];
+ uint8_t dest_scan_o[3];
+ src_scan[0] = src_b;
+ src_scan[1] = src_g;
+ src_scan[2] = src_r;
+ dest_scan_o[0] = dest_scan[2];
+ dest_scan_o[1] = dest_scan[1];
+ dest_scan_o[2] = dest_scan[0];
+ _RGB_Blend(blend_type, src_scan, dest_scan_o, blended_colors);
+ dest_scan[2] =
+ FXDIB_ALPHA_MERGE(dest_scan[2], blended_colors[0], src_alpha);
+ dest_scan[1] =
+ FXDIB_ALPHA_MERGE(dest_scan[1], blended_colors[1], src_alpha);
+ dest_scan[0] =
+ FXDIB_ALPHA_MERGE(dest_scan[0], blended_colors[2], src_alpha);
+ } else if (blend_type) {
+ int back_color = FX_GAMMA(dest_scan[2]);
+ int blended = _BLEND(blend_type, back_color, src_b);
+ dest_scan[2] =
+ FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
+ back_color = FX_GAMMA(dest_scan[1]);
+ blended = _BLEND(blend_type, back_color, src_g);
+ dest_scan[1] =
+ FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
+ back_color = FX_GAMMA(dest_scan[0]);
+ blended = _BLEND(blend_type, back_color, src_r);
+ dest_scan[0] =
+ FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(back_color, blended, src_alpha));
+ } else {
+ dest_scan[2] = FX_GAMMA_INVERSE(
+ FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), src_b, src_alpha));
+ dest_scan[1] = FX_GAMMA_INVERSE(
+ FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), src_g, src_alpha));
+ dest_scan[0] = FX_GAMMA_INVERSE(
+ FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), src_r, src_alpha));
+ }
+ dest_scan += Bpp;
+ }
+}
+inline FX_BOOL _ScanlineCompositor_InitSourceMask(FXDIB_Format dest_format,
+ int alpha_flag,
+ FX_DWORD mask_color,
+ int& mask_alpha,
+ int& mask_red,
+ int& mask_green,
+ int& mask_blue,
+ int& mask_black,
+ void* icc_module,
+ void* pIccTransform) {
+ ICodec_IccModule* pIccModule = (ICodec_IccModule*)icc_module;
+ if (alpha_flag >> 8) {
+ mask_alpha = alpha_flag & 0xff;
+ mask_red = FXSYS_GetCValue(mask_color);
+ mask_green = FXSYS_GetMValue(mask_color);
+ mask_blue = FXSYS_GetYValue(mask_color);
+ mask_black = FXSYS_GetKValue(mask_color);
+ } else {
+ mask_alpha = FXARGB_A(mask_color);
+ mask_red = FXARGB_R(mask_color);
+ mask_green = FXARGB_G(mask_color);
+ mask_blue = FXARGB_B(mask_color);
+ }
+ if (dest_format == FXDIB_8bppMask) {
+ return TRUE;
+ }
+ if ((dest_format & 0xff) == 8) {
+ if (pIccTransform) {
+ mask_color = (alpha_flag >> 8) ? FXCMYK_TODIB(mask_color)
+ : FXARGB_TODIB(mask_color);
+ uint8_t* gray_p = (uint8_t*)&mask_color;
+ pIccModule->TranslateScanline(pIccTransform, gray_p, gray_p, 1);
+ mask_red = dest_format & 0x0400 ? FX_CCOLOR(gray_p[0]) : gray_p[0];
+ } else {
+ if (alpha_flag >> 8) {
+ uint8_t r, g, b;
+ AdobeCMYK_to_sRGB1(mask_red, mask_green, mask_blue, mask_black, r, g,
+ b);
+ mask_red = FXRGB2GRAY(r, g, b);
+ } else {
+ mask_red = FXRGB2GRAY(mask_red, mask_green, mask_blue);
+ }
+ if (dest_format & 0x0400) {
+ mask_red = FX_CCOLOR(mask_red);
+ }
+ }
+ } else {
+ uint8_t* mask_color_p = (uint8_t*)&mask_color;
+ mask_color =
+ (alpha_flag >> 8) ? FXCMYK_TODIB(mask_color) : FXARGB_TODIB(mask_color);
+ if (pIccTransform) {
+ pIccModule->TranslateScanline(pIccTransform, mask_color_p, mask_color_p,
+ 1);
+ mask_red = mask_color_p[2];
+ mask_green = mask_color_p[1];
+ mask_blue = mask_color_p[0];
+ } else if (alpha_flag >> 8) {
+ AdobeCMYK_to_sRGB1(mask_color_p[0], mask_color_p[1], mask_color_p[2],
+ mask_color_p[3], mask_color_p[2], mask_color_p[1],
+ mask_color_p[0]);
+ mask_red = mask_color_p[2];
+ mask_green = mask_color_p[1];
+ mask_blue = mask_color_p[0];
+ }
+ }
+ return TRUE;
+}
+inline void _ScanlineCompositor_InitSourcePalette(FXDIB_Format src_format,
+ FXDIB_Format dest_format,
+ FX_DWORD*& pDestPalette,
+ FX_DWORD* pSrcPalette,
+ void* icc_module,
+ void* pIccTransform) {
+ ICodec_IccModule* pIccModule = (ICodec_IccModule*)icc_module;
+ FX_BOOL isSrcCmyk = !!(src_format & 0x0400);
+ FX_BOOL isDstCmyk = !!(dest_format & 0x0400);
+ pDestPalette = NULL;
+ if (pIccTransform) {
+ if (pSrcPalette) {
+ if ((dest_format & 0xff) == 8) {
+ int pal_count = 1 << (src_format & 0xff);
+ uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count);
+ pDestPalette = (FX_DWORD*)gray_pal;
+ for (int i = 0; i < pal_count; i++) {
+ FX_DWORD color = isSrcCmyk ? FXCMYK_TODIB(pSrcPalette[i])
+ : FXARGB_TODIB(pSrcPalette[i]);
+ pIccModule->TranslateScanline(pIccTransform, gray_pal,
+ (const uint8_t*)&color, 1);
+ gray_pal++;
+ }
+ } else {
+ int palsize = 1 << (src_format & 0xff);
+ pDestPalette = FX_Alloc(FX_DWORD, palsize);
+ for (int i = 0; i < palsize; i++) {
+ FX_DWORD color = isSrcCmyk ? FXCMYK_TODIB(pSrcPalette[i])
+ : FXARGB_TODIB(pSrcPalette[i]);
+ pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&color,
+ (const uint8_t*)&color, 1);
+ pDestPalette[i] =
+ isDstCmyk ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
+ }
+ }
+ } else {
+ int pal_count = 1 << (src_format & 0xff);
+ uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count);
+ if (pal_count == 2) {
+ gray_pal[0] = 0;
+ gray_pal[1] = 255;
+ } else {
+ for (int i = 0; i < pal_count; i++) {
+ gray_pal[i] = i;
+ }
+ }
+ if ((dest_format & 0xff) == 8) {
+ pIccModule->TranslateScanline(pIccTransform, gray_pal, gray_pal,
+ pal_count);
+ pDestPalette = (FX_DWORD*)gray_pal;
+ } else {
+ pDestPalette = FX_Alloc(FX_DWORD, pal_count);
+ for (int i = 0; i < pal_count; i++) {
+ pIccModule->TranslateScanline(
+ pIccTransform, (uint8_t*)&pDestPalette[i], &gray_pal[i], 1);
+ pDestPalette[i] = isDstCmyk ? FXCMYK_TODIB(pDestPalette[i])
+ : FXARGB_TODIB(pDestPalette[i]);
+ }
+ FX_Free(gray_pal);
+ }
+ }
+ } else {
+ if (pSrcPalette) {
+ if ((dest_format & 0xff) == 8) {
+ int pal_count = 1 << (src_format & 0xff);
+ uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count);
+ pDestPalette = (FX_DWORD*)gray_pal;
+ if (isSrcCmyk) {
+ for (int i = 0; i < pal_count; i++) {
+ FX_CMYK cmyk = pSrcPalette[i];
+ uint8_t r, g, b;
+ AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk),
+ FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk), r,
+ g, b);
+ *gray_pal++ = FXRGB2GRAY(r, g, b);
+ }
+ } else {
+ for (int i = 0; i < pal_count; i++) {
+ FX_ARGB argb = pSrcPalette[i];
+ *gray_pal++ =
+ FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb));
+ }
+ }
+ } else {
+ int palsize = 1 << (src_format & 0xff);
+ pDestPalette = FX_Alloc(FX_DWORD, palsize);
+ if (isDstCmyk == isSrcCmyk) {
+ FXSYS_memcpy(pDestPalette, pSrcPalette, palsize * sizeof(FX_DWORD));
+ } else {
+ for (int i = 0; i < palsize; i++) {
+ FX_CMYK cmyk = pSrcPalette[i];
+ uint8_t r, g, b;
+ AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk),
+ FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk), r,
+ g, b);
+ pDestPalette[i] = FXARGB_MAKE(0xff, r, g, b);
+ }
+ }
+ }
+ } else {
+ if ((dest_format & 0xff) == 8) {
+ int pal_count = 1 << (src_format & 0xff);
+ uint8_t* gray_pal = FX_Alloc(uint8_t, pal_count);
+ if (pal_count == 2) {
+ gray_pal[0] = 0;
+ gray_pal[1] = 255;
+ } else {
+ for (int i = 0; i < pal_count; i++) {
+ gray_pal[i] = i;
+ }
+ }
+ pDestPalette = (FX_DWORD*)gray_pal;
+ } else {
+ int palsize = 1 << (src_format & 0xff);
+ pDestPalette = FX_Alloc(FX_DWORD, palsize);
+ if (palsize == 2) {
+ pDestPalette[0] = isSrcCmyk ? 255 : 0xff000000;
+ pDestPalette[1] = isSrcCmyk ? 0 : 0xffffffff;
+ } else {
+ for (int i = 0; i < palsize; i++) {
+ pDestPalette[i] = isSrcCmyk ? FX_CCOLOR(i) : (i * 0x10101);
+ }
+ }
+ if (isSrcCmyk != isDstCmyk) {
+ for (int i = 0; i < palsize; i++) {
+ FX_CMYK cmyk = pDestPalette[i];
+ uint8_t r, g, b;
+ AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk),
+ FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk), r,
+ g, b);
+ pDestPalette[i] = FXARGB_MAKE(0xff, r, g, b);
+ }
+ }
+ }
+ }
+ }
+}
+CFX_ScanlineCompositor::CFX_ScanlineCompositor() {
+ m_pSrcPalette = NULL;
+ m_pCacheScanline = NULL;
+ m_CacheSize = 0;
+ m_bRgbByteOrder = FALSE;
+ m_BlendType = FXDIB_BLEND_NORMAL;
+}
+CFX_ScanlineCompositor::~CFX_ScanlineCompositor() {
+ FX_Free(m_pSrcPalette);
+ FX_Free(m_pCacheScanline);
+}
+FX_BOOL CFX_ScanlineCompositor::Init(FXDIB_Format dest_format,
+ FXDIB_Format src_format,
+ int32_t width,
+ FX_DWORD* pSrcPalette,
+ FX_DWORD mask_color,
+ int blend_type,
+ FX_BOOL bClip,
+ FX_BOOL bRgbByteOrder,
+ int alpha_flag,
+ void* pIccTransform) {
+ m_SrcFormat = src_format;
+ m_DestFormat = dest_format;
+ m_BlendType = blend_type;
+ m_bRgbByteOrder = bRgbByteOrder;
+ ICodec_IccModule* pIccModule = NULL;
+ if (CFX_GEModule::Get()->GetCodecModule()) {
+ pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ }
+ if (!pIccModule) {
+ pIccTransform = NULL;
+ }
+ m_pIccTransform = pIccTransform;
+ if ((dest_format & 0xff) == 1) {
+ return FALSE;
+ }
+ if (m_SrcFormat == FXDIB_1bppMask || m_SrcFormat == FXDIB_8bppMask) {
+ return _ScanlineCompositor_InitSourceMask(
+ dest_format, alpha_flag, mask_color, m_MaskAlpha, m_MaskRed,
+ m_MaskGreen, m_MaskBlue, m_MaskBlack, pIccModule, pIccTransform);
+ }
+ if (!pIccTransform && (~src_format & 0x0400) && (dest_format & 0x0400)) {
+ return FALSE;
+ }
+ if ((m_SrcFormat & 0xff) <= 8) {
+ if (dest_format == FXDIB_8bppMask) {
+ return TRUE;
+ }
+ _ScanlineCompositor_InitSourcePalette(src_format, dest_format,
+ m_pSrcPalette, pSrcPalette,
+ pIccModule, pIccTransform);
+ m_Transparency =
+ (dest_format == FXDIB_Argb ? 1 : 0) + (dest_format & 0x0200 ? 2 : 0) +
+ (dest_format & 0x0400 ? 4 : 0) + ((src_format & 0xff) == 1 ? 8 : 0);
+ return TRUE;
+ }
+ m_Transparency = (src_format & 0x0200 ? 0 : 1) +
+ (dest_format & 0x0200 ? 0 : 2) +
+ (blend_type == FXDIB_BLEND_NORMAL ? 4 : 0) +
+ (bClip ? 8 : 0) + (src_format & 0x0400 ? 16 : 0) +
+ (dest_format & 0x0400 ? 32 : 0) + (pIccTransform ? 64 : 0);
+ return TRUE;
+}
+void CFX_ScanlineCompositor::CompositeRgbBitmapLine(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ const uint8_t* clip_scan,
+ const uint8_t* src_extra_alpha,
+ uint8_t* dst_extra_alpha) {
+ int src_Bpp = (m_SrcFormat & 0xff) >> 3;
+ int dest_Bpp = (m_DestFormat & 0xff) >> 3;
+ if (m_bRgbByteOrder) {
+ switch (m_Transparency) {
+ case 0:
+ case 4:
+ case 8:
+ case 12:
+ _CompositeRow_Argb2Argb_RgbByteOrder(dest_scan, src_scan, width,
+ m_BlendType, clip_scan);
+ break;
+ case 1:
+ _CompositeRow_Rgb2Argb_Blend_NoClip_RgbByteOrder(
+ dest_scan, src_scan, width, m_BlendType, src_Bpp);
+ break;
+ case 2:
+ case 10:
+ _CompositeRow_Argb2Rgb_Blend_RgbByteOrder(
+ dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan);
+ break;
+ case 3:
+ _CompositeRow_Rgb2Rgb_Blend_NoClip_RgbByteOrder(
+ dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp);
+ break;
+ case 5:
+ _CompositeRow_Rgb2Argb_NoBlend_NoClip_RgbByteOrder(dest_scan, src_scan,
+ width, src_Bpp);
+ break;
+ case 6:
+ case 14:
+ _CompositeRow_Argb2Rgb_NoBlend_RgbByteOrder(dest_scan, src_scan, width,
+ dest_Bpp, clip_scan);
+ break;
+ case 7:
+ _CompositeRow_Rgb2Rgb_NoBlend_NoClip_RgbByteOrder(
+ dest_scan, src_scan, width, dest_Bpp, src_Bpp);
+ break;
+ case 9:
+ _CompositeRow_Rgb2Argb_Blend_Clip_RgbByteOrder(
+ dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan);
+ break;
+ case 11:
+ _CompositeRow_Rgb2Rgb_Blend_Clip_RgbByteOrder(
+ dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp,
+ clip_scan);
+ break;
+ case 13:
+ _CompositeRow_Rgb2Argb_NoBlend_Clip_RgbByteOrder(
+ dest_scan, src_scan, width, src_Bpp, clip_scan);
+ break;
+ case 15:
+ _CompositeRow_Rgb2Rgb_NoBlend_Clip_RgbByteOrder(
+ dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan);
+ break;
+ }
+ return;
+ }
+ if (m_DestFormat == FXDIB_8bppMask) {
+ if (m_SrcFormat & 0x0200) {
+ if (m_SrcFormat == FXDIB_Argb) {
+ _CompositeRow_Argb2Mask(dest_scan, src_scan, width, clip_scan);
+ } else {
+ _CompositeRow_Rgba2Mask(dest_scan, src_extra_alpha, width, clip_scan);
+ }
+ } else {
+ _CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan);
+ }
+ } else if ((m_DestFormat & 0xff) == 8) {
+ if (m_DestFormat & 0x0400) {
+ for (int i = 0; i < width; i++) {
+ *dest_scan = ~*dest_scan;
+ dest_scan++;
+ }
+ }
+ if (m_SrcFormat & 0x0200) {
+ if (m_DestFormat & 0x0200) {
+ _CompositeRow_Argb2Graya(dest_scan, src_scan, width, m_BlendType,
+ clip_scan, src_extra_alpha, dst_extra_alpha,
+ m_pIccTransform);
+ } else {
+ _CompositeRow_Argb2Gray(dest_scan, src_scan, width, m_BlendType,
+ clip_scan, src_extra_alpha, m_pIccTransform);
+ }
+ } else {
+ if (m_DestFormat & 0x0200) {
+ _CompositeRow_Rgb2Graya(dest_scan, src_scan, src_Bpp, width,
+ m_BlendType, clip_scan, dst_extra_alpha,
+ m_pIccTransform);
+ } else {
+ _CompositeRow_Rgb2Gray(dest_scan, src_scan, src_Bpp, width, m_BlendType,
+ clip_scan, m_pIccTransform);
+ }
+ }
+ if (m_DestFormat & 0x0400) {
+ for (int i = 0; i < width; i++) {
+ *dest_scan = ~*dest_scan;
+ dest_scan++;
+ }
+ }
+ } else {
+ int dest_Size = width * dest_Bpp + 4;
+ if (dest_Size > m_CacheSize) {
+ m_pCacheScanline = FX_Realloc(uint8_t, m_pCacheScanline, dest_Size);
+ if (!m_pCacheScanline) {
+ return;
+ }
+ m_CacheSize = dest_Size;
+ }
+ switch (m_Transparency) {
+ case 0:
+ case 4:
+ case 8:
+ case 4 + 8: {
+ _CompositeRow_Argb2Argb(dest_scan, src_scan, width, m_BlendType,
+ clip_scan, dst_extra_alpha, src_extra_alpha);
+ } break;
+ case 64:
+ case 4 + 64:
+ case 8 + 64:
+ case 4 + 8 + 64: {
+ _CompositeRow_Argb2Argb_Transform(
+ dest_scan, src_scan, width, m_BlendType, clip_scan, dst_extra_alpha,
+ src_extra_alpha, m_pCacheScanline, m_pIccTransform);
+ } break;
+ case 1:
+ _CompositeRow_Rgb2Argb_Blend_NoClip(
+ dest_scan, src_scan, width, m_BlendType, src_Bpp, dst_extra_alpha);
+ break;
+ case 1 + 64:
+ _CompositeRow_Rgb2Argb_Blend_NoClip_Transform(
+ dest_scan, src_scan, width, m_BlendType, src_Bpp, dst_extra_alpha,
+ m_pCacheScanline, m_pIccTransform);
+ break;
+ case 1 + 8:
+ _CompositeRow_Rgb2Argb_Blend_Clip(dest_scan, src_scan, width,
+ m_BlendType, src_Bpp, clip_scan,
+ dst_extra_alpha);
+ break;
+ case 1 + 8 + 64:
+ _CompositeRow_Rgb2Argb_Blend_Clip_Transform(
+ dest_scan, src_scan, width, m_BlendType, src_Bpp, clip_scan,
+ dst_extra_alpha, m_pCacheScanline, m_pIccTransform);
+ break;
+ case 1 + 4:
+ _CompositeRow_Rgb2Argb_NoBlend_NoClip(dest_scan, src_scan, width,
+ src_Bpp, dst_extra_alpha);
+ break;
+ case 1 + 4 + 64:
+ _CompositeRow_Rgb2Argb_NoBlend_NoClip_Transform(
+ dest_scan, src_scan, width, src_Bpp, dst_extra_alpha,
+ m_pCacheScanline, m_pIccTransform);
+ break;
+ case 1 + 4 + 8:
+ _CompositeRow_Rgb2Argb_NoBlend_Clip(dest_scan, src_scan, width, src_Bpp,
+ clip_scan, dst_extra_alpha);
+ break;
+ case 1 + 4 + 8 + 64:
+ _CompositeRow_Rgb2Argb_NoBlend_Clip_Transform(
+ dest_scan, src_scan, width, src_Bpp, clip_scan, dst_extra_alpha,
+ m_pCacheScanline, m_pIccTransform);
+ break;
+ case 2:
+ case 2 + 8:
+ _CompositeRow_Argb2Rgb_Blend(dest_scan, src_scan, width, m_BlendType,
+ dest_Bpp, clip_scan, src_extra_alpha);
+ break;
+ case 2 + 64:
+ case 2 + 8 + 64:
+ _CompositeRow_Argb2Rgb_Blend_Transform(
+ dest_scan, src_scan, width, m_BlendType, dest_Bpp, clip_scan,
+ src_extra_alpha, m_pCacheScanline, m_pIccTransform);
+ break;
+ case 2 + 4:
+ case 2 + 4 + 8:
+ _CompositeRow_Argb2Rgb_NoBlend(dest_scan, src_scan, width, dest_Bpp,
+ clip_scan, src_extra_alpha);
+ break;
+ case 2 + 4 + 64:
+ case 2 + 4 + 8 + 64:
+ _CompositeRow_Argb2Rgb_NoBlend_Transform(
+ dest_scan, src_scan, width, dest_Bpp, clip_scan, src_extra_alpha,
+ m_pCacheScanline, m_pIccTransform);
+ break;
+ case 1 + 2:
+ _CompositeRow_Rgb2Rgb_Blend_NoClip(dest_scan, src_scan, width,
+ m_BlendType, dest_Bpp, src_Bpp);
+ break;
+ case 1 + 2 + 64:
+ _CompositeRow_Rgb2Rgb_Blend_NoClip_Transform(
+ dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp,
+ m_pCacheScanline, m_pIccTransform);
+ break;
+ case 1 + 2 + 8:
+ _CompositeRow_Rgb2Rgb_Blend_Clip(dest_scan, src_scan, width,
+ m_BlendType, dest_Bpp, src_Bpp,
+ clip_scan);
+ break;
+ case 1 + 2 + 8 + 64:
+ _CompositeRow_Rgb2Rgb_Blend_Clip_Transform(
+ dest_scan, src_scan, width, m_BlendType, dest_Bpp, src_Bpp,
+ clip_scan, m_pCacheScanline, m_pIccTransform);
+ break;
+ case 1 + 2 + 4:
+ _CompositeRow_Rgb2Rgb_NoBlend_NoClip(dest_scan, src_scan, width,
+ dest_Bpp, src_Bpp);
+ break;
+ case 1 + 2 + 4 + 64:
+ _CompositeRow_Rgb2Rgb_NoBlend_NoClip_Transform(
+ dest_scan, src_scan, width, dest_Bpp, src_Bpp, m_pCacheScanline,
+ m_pIccTransform);
+ break;
+ case 1 + 2 + 4 + 8:
+ _CompositeRow_Rgb2Rgb_NoBlend_Clip(dest_scan, src_scan, width, dest_Bpp,
+ src_Bpp, clip_scan);
+ break;
+ case 1 + 2 + 4 + 8 + 64:
+ _CompositeRow_Rgb2Rgb_NoBlend_Clip_Transform(
+ dest_scan, src_scan, width, dest_Bpp, src_Bpp, clip_scan,
+ m_pCacheScanline, m_pIccTransform);
+ break;
+ }
+ }
+}
+void CFX_ScanlineCompositor::CompositePalBitmapLine(
+ uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int src_left,
+ int width,
+ const uint8_t* clip_scan,
+ const uint8_t* src_extra_alpha,
+ uint8_t* dst_extra_alpha) {
+ if (m_bRgbByteOrder) {
+ if (m_SrcFormat == FXDIB_1bppRgb) {
+ if (m_DestFormat == FXDIB_8bppRgb) {
+ return;
+ }
+ if (m_DestFormat == FXDIB_Argb) {
+ _CompositeRow_1bppRgb2Argb_NoBlend_RgbByteOrder(
+ dest_scan, src_scan, src_left, width, m_pSrcPalette, clip_scan);
+ } else {
+ _CompositeRow_1bppRgb2Rgb_NoBlend_RgbByteOrder(
+ dest_scan, src_scan, src_left, m_pSrcPalette, width,
+ (m_DestFormat & 0xff) >> 3, clip_scan);
+ }
+ } else {
+ if (m_DestFormat == FXDIB_8bppRgb) {
+ return;
+ }
+ if (m_DestFormat == FXDIB_Argb) {
+ _CompositeRow_8bppRgb2Argb_NoBlend_RgbByteOrder(
+ dest_scan, src_scan, width, m_pSrcPalette, clip_scan);
+ } else {
+ _CompositeRow_8bppRgb2Rgb_NoBlend_RgbByteOrder(
+ dest_scan, src_scan, m_pSrcPalette, width,
+ (m_DestFormat & 0xff) >> 3, clip_scan);
+ }
+ }
+ return;
+ }
+ if (m_DestFormat == FXDIB_8bppMask) {
+ _CompositeRow_Rgb2Mask(dest_scan, src_scan, width, clip_scan);
+ return;
+ }
+ if ((m_DestFormat & 0xff) == 8) {
+ if (m_Transparency & 8) {
+ if (m_DestFormat & 0x0200) {
+ _CompositeRow_1bppPal2Graya(dest_scan, src_scan, src_left,
+ (const uint8_t*)m_pSrcPalette, width,
+ m_BlendType, clip_scan, dst_extra_alpha);
+ } else {
+ _CompositeRow_1bppPal2Gray(dest_scan, src_scan, src_left,
+ (const uint8_t*)m_pSrcPalette, width,
+ m_BlendType, clip_scan);
+ }
+ } else {
+ if (m_DestFormat & 0x0200)
+ _CompositeRow_8bppPal2Graya(
+ dest_scan, src_scan, (const uint8_t*)m_pSrcPalette, width,
+ m_BlendType, clip_scan, dst_extra_alpha, src_extra_alpha);
+ else
+ _CompositeRow_8bppPal2Gray(dest_scan, src_scan,
+ (const uint8_t*)m_pSrcPalette, width,
+ m_BlendType, clip_scan, src_extra_alpha);
+ }
+ } else {
+ switch (m_Transparency) {
+ case 1 + 2:
+ _CompositeRow_8bppRgb2Argb_NoBlend(dest_scan, src_scan, width,
+ m_pSrcPalette, clip_scan,
+ src_extra_alpha);
+ break;
+ case 1 + 2 + 8:
+ _CompositeRow_1bppRgb2Argb_NoBlend(dest_scan, src_scan, src_left, width,
+ m_pSrcPalette, clip_scan);
+ break;
+ case 0:
+ _CompositeRow_8bppRgb2Rgb_NoBlend(dest_scan, src_scan, m_pSrcPalette,
+ width, (m_DestFormat & 0xff) >> 3,
+ clip_scan, src_extra_alpha);
+ break;
+ case 0 + 8:
+ _CompositeRow_1bppRgb2Rgb_NoBlend(
+ dest_scan, src_scan, src_left, m_pSrcPalette, width,
+ (m_DestFormat & 0xff) >> 3, clip_scan);
+ break;
+ case 0 + 2:
+ _CompositeRow_8bppRgb2Rgb_NoBlend(dest_scan, src_scan, m_pSrcPalette,
+ width, (m_DestFormat & 0xff) >> 3,
+ clip_scan, src_extra_alpha);
+ break;
+ case 0 + 2 + 8:
+ _CompositeRow_1bppRgb2Rgba_NoBlend(dest_scan, src_scan, src_left, width,
+ m_pSrcPalette, clip_scan,
+ dst_extra_alpha);
+ break;
+ break;
+ }
+ }
+}
+void CFX_ScanlineCompositor::CompositeByteMaskLine(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int width,
+ const uint8_t* clip_scan,
+ uint8_t* dst_extra_alpha) {
+ if (m_DestFormat == FXDIB_8bppMask) {
+ _CompositeRow_ByteMask2Mask(dest_scan, src_scan, m_MaskAlpha, width,
+ clip_scan);
+ } else if ((m_DestFormat & 0xff) == 8) {
+ if (m_DestFormat & 0x0200) {
+ _CompositeRow_ByteMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
+ width, clip_scan, dst_extra_alpha);
+ } else {
+ _CompositeRow_ByteMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
+ width, clip_scan);
+ }
+ } else if (m_bRgbByteOrder) {
+ if (m_DestFormat == FXDIB_Argb) {
+ _CompositeRow_ByteMask2Argb_RgbByteOrder(
+ dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
+ width, m_BlendType, clip_scan);
+ } else {
+ _CompositeRow_ByteMask2Rgb_RgbByteOrder(
+ dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
+ width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
+ }
+ return;
+ } else if (m_DestFormat == FXDIB_Argb) {
+ _CompositeRow_ByteMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
+ m_MaskGreen, m_MaskBlue, width, m_BlendType,
+ clip_scan);
+ } else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32) {
+ _CompositeRow_ByteMask2Rgb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
+ m_MaskGreen, m_MaskBlue, width, m_BlendType,
+ (m_DestFormat & 0xff) >> 3, clip_scan);
+ } else if (m_DestFormat == FXDIB_Rgba) {
+ _CompositeRow_ByteMask2Rgba(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
+ m_MaskGreen, m_MaskBlue, width, m_BlendType,
+ clip_scan, dst_extra_alpha);
+ }
+}
+void CFX_ScanlineCompositor::CompositeBitMaskLine(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int src_left,
+ int width,
+ const uint8_t* clip_scan,
+ uint8_t* dst_extra_alpha) {
+ if (m_DestFormat == FXDIB_8bppMask) {
+ _CompositeRow_BitMask2Mask(dest_scan, src_scan, m_MaskAlpha, src_left,
+ width, clip_scan);
+ } else if ((m_DestFormat & 0xff) == 8) {
+ if (m_DestFormat & 0x0200) {
+ _CompositeRow_BitMask2Graya(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
+ src_left, width, clip_scan, dst_extra_alpha);
+ } else {
+ _CompositeRow_BitMask2Gray(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
+ src_left, width, clip_scan);
+ }
+ } else if (m_bRgbByteOrder) {
+ if (m_DestFormat == FXDIB_Argb) {
+ _CompositeRow_BitMask2Argb_RgbByteOrder(
+ dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
+ src_left, width, m_BlendType, clip_scan);
+ } else {
+ _CompositeRow_BitMask2Rgb_RgbByteOrder(
+ dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
+ src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
+ }
+ return;
+ } else if (m_DestFormat == FXDIB_Argb) {
+ _CompositeRow_BitMask2Argb(dest_scan, src_scan, m_MaskAlpha, m_MaskRed,
+ m_MaskGreen, m_MaskBlue, src_left, width,
+ m_BlendType, clip_scan);
+ } else if (m_DestFormat == FXDIB_Rgb || m_DestFormat == FXDIB_Rgb32) {
+ _CompositeRow_BitMask2Rgb(
+ dest_scan, src_scan, m_MaskAlpha, m_MaskRed, m_MaskGreen, m_MaskBlue,
+ src_left, width, m_BlendType, (m_DestFormat & 0xff) >> 3, clip_scan);
+ }
+}
+
+FX_BOOL CFX_DIBitmap::CompositeBitmap(int dest_left,
+ int dest_top,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top,
+ int blend_type,
+ const CFX_ClipRgn* pClipRgn,
+ FX_BOOL bRgbByteOrder,
+ void* pIccTransform) {
+ if (!m_pBuffer) {
+ return FALSE;
+ }
+ ASSERT(!pSrcBitmap->IsAlphaMask());
+ ASSERT(m_bpp >= 8);
+ if (pSrcBitmap->IsAlphaMask() || m_bpp < 8) {
+ return FALSE;
+ }
+ GetOverlapRect(dest_left, dest_top, width, height, pSrcBitmap->GetWidth(),
+ pSrcBitmap->GetHeight(), src_left, src_top, pClipRgn);
+ if (width == 0 || height == 0) {
+ return TRUE;
+ }
+ const CFX_DIBitmap* pClipMask = NULL;
+ FX_RECT clip_box;
+ if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) {
+ ASSERT(pClipRgn->GetType() == CFX_ClipRgn::MaskF);
+ pClipMask = pClipRgn->GetMask();
+ clip_box = pClipRgn->GetBox();
+ }
+ CFX_ScanlineCompositor compositor;
+ if (!compositor.Init(GetFormat(), pSrcBitmap->GetFormat(), width,
+ pSrcBitmap->GetPalette(), 0, blend_type,
+ pClipMask != NULL, bRgbByteOrder, 0, pIccTransform)) {
+ return FALSE;
+ }
+ int dest_Bpp = m_bpp / 8;
+ int src_Bpp = pSrcBitmap->GetBPP() / 8;
+ FX_BOOL bRgb = src_Bpp > 1 && !pSrcBitmap->IsCmykImage();
+ CFX_DIBitmap* pSrcAlphaMask = pSrcBitmap->m_pAlphaMask;
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan =
+ m_pBuffer + (dest_top + row) * m_Pitch + dest_left * dest_Bpp;
+ const uint8_t* src_scan =
+ pSrcBitmap->GetScanline(src_top + row) + src_left * src_Bpp;
+ const uint8_t* src_scan_extra_alpha =
+ pSrcAlphaMask ? pSrcAlphaMask->GetScanline(src_top + row) + src_left
+ : NULL;
+ uint8_t* dst_scan_extra_alpha =
+ m_pAlphaMask
+ ? (uint8_t*)m_pAlphaMask->GetScanline(dest_top + row) + dest_left
+ : NULL;
+ const uint8_t* clip_scan = NULL;
+ if (pClipMask) {
+ clip_scan = pClipMask->m_pBuffer +
+ (dest_top + row - clip_box.top) * pClipMask->m_Pitch +
+ (dest_left - clip_box.left);
+ }
+ if (bRgb) {
+ compositor.CompositeRgbBitmapLine(dest_scan, src_scan, width, clip_scan,
+ src_scan_extra_alpha,
+ dst_scan_extra_alpha);
+ } else {
+ compositor.CompositePalBitmapLine(dest_scan, src_scan, src_left, width,
+ clip_scan, src_scan_extra_alpha,
+ dst_scan_extra_alpha);
+ }
+ }
+ return TRUE;
+}
+FX_BOOL CFX_DIBitmap::CompositeMask(int dest_left,
+ int dest_top,
+ int width,
+ int height,
+ const CFX_DIBSource* pMask,
+ FX_DWORD color,
+ int src_left,
+ int src_top,
+ int blend_type,
+ const CFX_ClipRgn* pClipRgn,
+ FX_BOOL bRgbByteOrder,
+ int alpha_flag,
+ void* pIccTransform) {
+ if (!m_pBuffer) {
+ return FALSE;
+ }
+ ASSERT(pMask->IsAlphaMask());
+ ASSERT(m_bpp >= 8);
+ if (!pMask->IsAlphaMask() || m_bpp < 8) {
+ return FALSE;
+ }
+ GetOverlapRect(dest_left, dest_top, width, height, pMask->GetWidth(),
+ pMask->GetHeight(), src_left, src_top, pClipRgn);
+ if (width == 0 || height == 0) {
+ return TRUE;
+ }
+ int src_alpha =
+ (uint8_t)(alpha_flag >> 8) ? (alpha_flag & 0xff) : FXARGB_A(color);
+ if (src_alpha == 0) {
+ return TRUE;
+ }
+ const CFX_DIBitmap* pClipMask = NULL;
+ FX_RECT clip_box;
+ if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) {
+ ASSERT(pClipRgn->GetType() == CFX_ClipRgn::MaskF);
+ pClipMask = pClipRgn->GetMask();
+ clip_box = pClipRgn->GetBox();
+ }
+ int src_bpp = pMask->GetBPP();
+ int Bpp = GetBPP() / 8;
+ CFX_ScanlineCompositor compositor;
+ if (!compositor.Init(GetFormat(), pMask->GetFormat(), width, NULL, color,
+ blend_type, pClipMask != NULL, bRgbByteOrder, alpha_flag,
+ pIccTransform)) {
+ return FALSE;
+ }
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan =
+ m_pBuffer + (dest_top + row) * m_Pitch + dest_left * Bpp;
+ const uint8_t* src_scan = pMask->GetScanline(src_top + row);
+ uint8_t* dst_scan_extra_alpha =
+ m_pAlphaMask
+ ? (uint8_t*)m_pAlphaMask->GetScanline(dest_top + row) + dest_left
+ : NULL;
+ const uint8_t* clip_scan = NULL;
+ if (pClipMask) {
+ clip_scan = pClipMask->m_pBuffer +
+ (dest_top + row - clip_box.top) * pClipMask->m_Pitch +
+ (dest_left - clip_box.left);
+ }
+ if (src_bpp == 1) {
+ compositor.CompositeBitMaskLine(dest_scan, src_scan, src_left, width,
+ clip_scan, dst_scan_extra_alpha);
+ } else {
+ compositor.CompositeByteMaskLine(dest_scan, src_scan + src_left, width,
+ clip_scan, dst_scan_extra_alpha);
+ }
+ }
+ return TRUE;
+}
+FX_BOOL CFX_DIBitmap::CompositeRect(int left,
+ int top,
+ int width,
+ int height,
+ FX_DWORD color,
+ int alpha_flag,
+ void* pIccTransform) {
+ if (!m_pBuffer) {
+ return FALSE;
+ }
+ int src_alpha = (alpha_flag >> 8) ? (alpha_flag & 0xff) : FXARGB_A(color);
+ if (src_alpha == 0) {
+ return TRUE;
+ }
+ FX_RECT rect(left, top, left + width, top + height);
+ rect.Intersect(0, 0, m_Width, m_Height);
+ if (rect.IsEmpty()) {
+ return TRUE;
+ }
+ width = rect.Width();
+ FX_DWORD dst_color;
+ if (alpha_flag >> 8) {
+ dst_color = FXCMYK_TODIB(color);
+ } else {
+ dst_color = FXARGB_TODIB(color);
+ }
+ uint8_t* color_p = (uint8_t*)&dst_color;
+ if (m_bpp == 8) {
+ uint8_t gray = 255;
+ if (!IsAlphaMask()) {
+ if (pIccTransform && CFX_GEModule::Get()->GetCodecModule() &&
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ pIccModule->TranslateScanline(pIccTransform, &gray, color_p, 1);
+ } else {
+ if (alpha_flag >> 8) {
+ uint8_t r, g, b;
+ AdobeCMYK_to_sRGB1(color_p[0], color_p[1], color_p[2], color_p[3], r,
+ g, b);
+ gray = FXRGB2GRAY(r, g, b);
+ } else {
+ gray = (uint8_t)FXRGB2GRAY((int)color_p[2], color_p[1], color_p[0]);
+ }
+ }
+ if (IsCmykImage()) {
+ gray = ~gray;
+ }
+ }
+ for (int row = rect.top; row < rect.bottom; row++) {
+ uint8_t* dest_scan = m_pBuffer + row * m_Pitch + rect.left;
+ if (src_alpha == 255) {
+ FXSYS_memset(dest_scan, gray, width);
+ } else {
+ for (int col = 0; col < width; col++) {
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
+ dest_scan++;
+ }
+ }
+ }
+ return TRUE;
+ }
+ if (m_bpp == 1) {
+ ASSERT(!IsCmykImage() && (uint8_t)(alpha_flag >> 8) == 0);
+ int left_shift = rect.left % 8;
+ int right_shift = rect.right % 8;
+ int width = rect.right / 8 - rect.left / 8;
+ int index = 0;
+ if (m_pPalette) {
+ for (int i = 0; i < 2; i++) {
+ if (m_pPalette[i] == color) {
+ index = i;
+ }
+ }
+ } else {
+ index = ((uint8_t)color == 0xff) ? 1 : 0;
+ }
+ for (int row = rect.top; row < rect.bottom; row++) {
+ uint8_t* dest_scan_top = (uint8_t*)GetScanline(row) + rect.left / 8;
+ uint8_t* dest_scan_top_r = (uint8_t*)GetScanline(row) + rect.right / 8;
+ uint8_t left_flag = *dest_scan_top & (255 << (8 - left_shift));
+ uint8_t right_flag = *dest_scan_top_r & (255 >> right_shift);
+ if (width) {
+ FXSYS_memset(dest_scan_top + 1, index ? 255 : 0, width - 1);
+ if (!index) {
+ *dest_scan_top &= left_flag;
+ *dest_scan_top_r &= right_flag;
+ } else {
+ *dest_scan_top |= ~left_flag;
+ *dest_scan_top_r |= ~right_flag;
+ }
+ } else {
+ if (!index) {
+ *dest_scan_top &= left_flag | right_flag;
+ } else {
+ *dest_scan_top |= ~(left_flag | right_flag);
+ }
+ }
+ }
+ return TRUE;
+ }
+ ASSERT(m_bpp >= 24);
+ if (m_bpp < 24) {
+ return FALSE;
+ }
+ if (pIccTransform && CFX_GEModule::Get()->GetCodecModule()) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ pIccModule->TranslateScanline(pIccTransform, color_p, color_p, 1);
+ } else {
+ if (alpha_flag >> 8 && !IsCmykImage()) {
+ AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color),
+ FXSYS_GetYValue(color), FXSYS_GetKValue(color),
+ color_p[2], color_p[1], color_p[0]);
+ } else if (!(alpha_flag >> 8) && IsCmykImage()) {
+ return FALSE;
+ }
+ }
+ if (!IsCmykImage()) {
+ color_p[3] = (uint8_t)src_alpha;
+ }
+ int Bpp = m_bpp / 8;
+ FX_BOOL bAlpha = HasAlpha();
+ bool bArgb = GetFormat() == FXDIB_Argb;
+ if (src_alpha == 255) {
+ for (int row = rect.top; row < rect.bottom; row++) {
+ uint8_t* dest_scan = m_pBuffer + row * m_Pitch + rect.left * Bpp;
+ uint8_t* dest_scan_alpha =
+ m_pAlphaMask ? (uint8_t*)m_pAlphaMask->GetScanline(row) + rect.left
+ : NULL;
+ if (dest_scan_alpha) {
+ FXSYS_memset(dest_scan_alpha, 0xff, width);
+ }
+ if (Bpp == 4) {
+ FX_DWORD* scan = (FX_DWORD*)dest_scan;
+ for (int col = 0; col < width; col++) {
+ *scan++ = dst_color;
+ }
+ } else {
+ for (int col = 0; col < width; col++) {
+ *dest_scan++ = color_p[0];
+ *dest_scan++ = color_p[1];
+ *dest_scan++ = color_p[2];
+ }
+ }
+ }
+ return TRUE;
+ }
+ for (int row = rect.top; row < rect.bottom; row++) {
+ uint8_t* dest_scan = m_pBuffer + row * m_Pitch + rect.left * Bpp;
+ if (bAlpha) {
+ if (bArgb) {
+ for (int col = 0; col < width; col++) {
+ uint8_t back_alpha = dest_scan[3];
+ if (back_alpha == 0) {
+ FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, color_p[2],
+ color_p[1], color_p[0]));
+ dest_scan += 4;
+ continue;
+ }
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[0], alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[1], alpha_ratio);
+ dest_scan++;
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[2], alpha_ratio);
+ dest_scan++;
+ *dest_scan++ = dest_alpha;
+ }
+ } else {
+ uint8_t* dest_scan_alpha =
+ (uint8_t*)m_pAlphaMask->GetScanline(row) + rect.left;
+ for (int col = 0; col < width; col++) {
+ uint8_t back_alpha = *dest_scan_alpha;
+ if (back_alpha == 0) {
+ *dest_scan_alpha++ = src_alpha;
+ FXSYS_memcpy(dest_scan, color_p, Bpp);
+ dest_scan += Bpp;
+ continue;
+ }
+ uint8_t dest_alpha =
+ back_alpha + src_alpha - back_alpha * src_alpha / 255;
+ *dest_scan_alpha++ = dest_alpha;
+ int alpha_ratio = src_alpha * 255 / dest_alpha;
+ for (int comps = 0; comps < Bpp; comps++) {
+ *dest_scan =
+ FXDIB_ALPHA_MERGE(*dest_scan, color_p[comps], alpha_ratio);
+ dest_scan++;
+ }
+ }
+ }
+ } else {
+ for (int col = 0; col < width; col++) {
+ for (int comps = 0; comps < Bpp; comps++) {
+ if (comps == 3) {
+ *dest_scan++ = 255;
+ continue;
+ }
+ *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[comps], src_alpha);
+ dest_scan++;
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+CFX_BitmapComposer::CFX_BitmapComposer() {
+ m_pScanlineV = NULL;
+ m_pScanlineAlphaV = NULL;
+ m_pClipScanV = NULL;
+ m_pAddClipScan = NULL;
+ m_bRgbByteOrder = FALSE;
+ m_BlendType = FXDIB_BLEND_NORMAL;
+}
+CFX_BitmapComposer::~CFX_BitmapComposer() {
+ FX_Free(m_pScanlineV);
+ FX_Free(m_pScanlineAlphaV);
+ FX_Free(m_pClipScanV);
+ FX_Free(m_pAddClipScan);
+}
+void CFX_BitmapComposer::Compose(CFX_DIBitmap* pDest,
+ const CFX_ClipRgn* pClipRgn,
+ int bitmap_alpha,
+ FX_DWORD mask_color,
+ FX_RECT& dest_rect,
+ FX_BOOL bVertical,
+ FX_BOOL bFlipX,
+ FX_BOOL bFlipY,
+ FX_BOOL bRgbByteOrder,
+ int alpha_flag,
+ void* pIccTransform,
+ int blend_type) {
+ m_pBitmap = pDest;
+ m_pClipRgn = pClipRgn;
+ m_DestLeft = dest_rect.left;
+ m_DestTop = dest_rect.top;
+ m_DestWidth = dest_rect.Width();
+ m_DestHeight = dest_rect.Height();
+ m_BitmapAlpha = bitmap_alpha;
+ m_MaskColor = mask_color;
+ m_pClipMask = NULL;
+ if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) {
+ m_pClipMask = pClipRgn->GetMask();
+ }
+ m_bVertical = bVertical;
+ m_bFlipX = bFlipX;
+ m_bFlipY = bFlipY;
+ m_AlphaFlag = alpha_flag;
+ m_pIccTransform = pIccTransform;
+ m_bRgbByteOrder = bRgbByteOrder;
+ m_BlendType = blend_type;
+}
+FX_BOOL CFX_BitmapComposer::SetInfo(int width,
+ int height,
+ FXDIB_Format src_format,
+ FX_DWORD* pSrcPalette) {
+ m_SrcFormat = src_format;
+ if (!m_Compositor.Init(m_pBitmap->GetFormat(), src_format, width, pSrcPalette,
+ m_MaskColor, FXDIB_BLEND_NORMAL,
+ m_pClipMask != NULL || (m_BitmapAlpha < 255),
+ m_bRgbByteOrder, m_AlphaFlag, m_pIccTransform)) {
+ return FALSE;
+ }
+ if (m_bVertical) {
+ m_pScanlineV = FX_Alloc(uint8_t, m_pBitmap->GetBPP() / 8 * width + 4);
+ m_pClipScanV = FX_Alloc(uint8_t, m_pBitmap->GetHeight());
+ if (m_pBitmap->m_pAlphaMask) {
+ m_pScanlineAlphaV = FX_Alloc(uint8_t, width + 4);
+ }
+ }
+ if (m_BitmapAlpha < 255) {
+ m_pAddClipScan = FX_Alloc(
+ uint8_t, m_bVertical ? m_pBitmap->GetHeight() : m_pBitmap->GetWidth());
+ }
+ return TRUE;
+}
+void CFX_BitmapComposer::DoCompose(uint8_t* dest_scan,
+ const uint8_t* src_scan,
+ int dest_width,
+ const uint8_t* clip_scan,
+ const uint8_t* src_extra_alpha,
+ uint8_t* dst_extra_alpha) {
+ if (m_BitmapAlpha < 255) {
+ if (clip_scan) {
+ for (int i = 0; i < dest_width; i++) {
+ m_pAddClipScan[i] = clip_scan[i] * m_BitmapAlpha / 255;
+ }
+ } else {
+ FXSYS_memset(m_pAddClipScan, m_BitmapAlpha, dest_width);
+ }
+ clip_scan = m_pAddClipScan;
+ }
+ if (m_SrcFormat == FXDIB_8bppMask) {
+ m_Compositor.CompositeByteMaskLine(dest_scan, src_scan, dest_width,
+ clip_scan, dst_extra_alpha);
+ } else if ((m_SrcFormat & 0xff) == 8) {
+ m_Compositor.CompositePalBitmapLine(dest_scan, src_scan, 0, dest_width,
+ clip_scan, src_extra_alpha,
+ dst_extra_alpha);
+ } else {
+ m_Compositor.CompositeRgbBitmapLine(dest_scan, src_scan, dest_width,
+ clip_scan, src_extra_alpha,
+ dst_extra_alpha);
+ }
+}
+void CFX_BitmapComposer::ComposeScanline(int line,
+ const uint8_t* scanline,
+ const uint8_t* scan_extra_alpha) {
+ if (m_bVertical) {
+ ComposeScanlineV(line, scanline, scan_extra_alpha);
+ return;
+ }
+ const uint8_t* clip_scan = NULL;
+ if (m_pClipMask)
+ clip_scan = m_pClipMask->GetBuffer() +
+ (m_DestTop + line - m_pClipRgn->GetBox().top) *
+ m_pClipMask->GetPitch() +
+ (m_DestLeft - m_pClipRgn->GetBox().left);
+ uint8_t* dest_scan = (uint8_t*)m_pBitmap->GetScanline(line + m_DestTop) +
+ m_DestLeft * m_pBitmap->GetBPP() / 8;
+ uint8_t* dest_alpha_scan =
+ m_pBitmap->m_pAlphaMask
+ ? (uint8_t*)m_pBitmap->m_pAlphaMask->GetScanline(line + m_DestTop) +
+ m_DestLeft
+ : NULL;
+ DoCompose(dest_scan, scanline, m_DestWidth, clip_scan, scan_extra_alpha,
+ dest_alpha_scan);
+}
+void CFX_BitmapComposer::ComposeScanlineV(int line,
+ const uint8_t* scanline,
+ const uint8_t* scan_extra_alpha) {
+ int i;
+ int Bpp = m_pBitmap->GetBPP() / 8;
+ int dest_pitch = m_pBitmap->GetPitch();
+ int dest_alpha_pitch =
+ m_pBitmap->m_pAlphaMask ? m_pBitmap->m_pAlphaMask->GetPitch() : 0;
+ int dest_x = m_DestLeft + (m_bFlipX ? (m_DestWidth - line - 1) : line);
+ uint8_t* dest_buf =
+ m_pBitmap->GetBuffer() + dest_x * Bpp + m_DestTop * dest_pitch;
+ uint8_t* dest_alpha_buf = m_pBitmap->m_pAlphaMask
+ ? m_pBitmap->m_pAlphaMask->GetBuffer() +
+ dest_x + m_DestTop * dest_alpha_pitch
+ : NULL;
+ if (m_bFlipY) {
+ dest_buf += dest_pitch * (m_DestHeight - 1);
+ dest_alpha_buf += dest_alpha_pitch * (m_DestHeight - 1);
+ }
+ int y_step = dest_pitch;
+ int y_alpha_step = dest_alpha_pitch;
+ if (m_bFlipY) {
+ y_step = -y_step;
+ y_alpha_step = -y_alpha_step;
+ }
+ uint8_t* src_scan = m_pScanlineV;
+ uint8_t* dest_scan = dest_buf;
+ for (i = 0; i < m_DestHeight; i++) {
+ for (int j = 0; j < Bpp; j++) {
+ *src_scan++ = dest_scan[j];
+ }
+ dest_scan += y_step;
+ }
+ uint8_t* src_alpha_scan = m_pScanlineAlphaV;
+ uint8_t* dest_alpha_scan = dest_alpha_buf;
+ if (dest_alpha_scan) {
+ for (i = 0; i < m_DestHeight; i++) {
+ *src_alpha_scan++ = *dest_alpha_scan;
+ dest_alpha_scan += y_alpha_step;
+ }
+ }
+ uint8_t* clip_scan = NULL;
+ if (m_pClipMask) {
+ clip_scan = m_pClipScanV;
+ int clip_pitch = m_pClipMask->GetPitch();
+ const uint8_t* src_clip =
+ m_pClipMask->GetBuffer() +
+ (m_DestTop - m_pClipRgn->GetBox().top) * clip_pitch +
+ (dest_x - m_pClipRgn->GetBox().left);
+ if (m_bFlipY) {
+ src_clip += clip_pitch * (m_DestHeight - 1);
+ clip_pitch = -clip_pitch;
+ }
+ for (i = 0; i < m_DestHeight; i++) {
+ clip_scan[i] = *src_clip;
+ src_clip += clip_pitch;
+ }
+ }
+ DoCompose(m_pScanlineV, scanline, m_DestHeight, clip_scan, scan_extra_alpha,
+ m_pScanlineAlphaV);
+ src_scan = m_pScanlineV;
+ dest_scan = dest_buf;
+ for (i = 0; i < m_DestHeight; i++) {
+ for (int j = 0; j < Bpp; j++) {
+ dest_scan[j] = *src_scan++;
+ }
+ dest_scan += y_step;
+ }
+ src_alpha_scan = m_pScanlineAlphaV;
+ dest_alpha_scan = dest_alpha_buf;
+ if (dest_alpha_scan) {
+ for (i = 0; i < m_DestHeight; i++) {
+ *dest_alpha_scan = *src_alpha_scan++;
+ dest_alpha_scan += y_alpha_step;
+ }
+ }
+}
diff --git a/core/fxge/dib/fx_dib_convert.cpp b/core/fxge/dib/fx_dib_convert.cpp
new file mode 100644
index 0000000000..a1c18ae121
--- /dev/null
+++ b/core/fxge/dib/fx_dib_convert.cpp
@@ -0,0 +1,1227 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/include/fxcodec/fx_codec.h"
+#include "core/include/fxge/fx_dib.h"
+#include "core/include/fxge/fx_ge.h"
+
+const FX_DWORD g_dwWinPalette[256] = {
+ 0xff000000, 0xff800000, 0xff008000, 0xff808000, 0xff000080, 0xff800080,
+ 0xff008080, 0xff808080, 0xffC0DCC0, 0xffA6CAF0, 0xff2A3FAA, 0xff2A3FFF,
+ 0xff2A5F00, 0xff2A5F55, 0xff2A5FAA, 0xff2A5FFF, 0xff2A7F00, 0xff2A7F55,
+ 0xff2A7FAA, 0xff2A7FFF, 0xff2A9F00, 0xff2A9F55, 0xff2A9FAA, 0xff2A9FFF,
+ 0xff2ABF00, 0xff2ABF55, 0xff2ABFAA, 0xff2ABFFF, 0xff2ADF00, 0xff2ADF55,
+ 0xff2ADFAA, 0xff2ADFFF, 0xff2AFF00, 0xff2AFF55, 0xff2AFFAA, 0xff2AFFFF,
+ 0xff550000, 0xff550055, 0xff5500AA, 0xff5500FF, 0xff551F00, 0xff551F55,
+ 0xff551FAA, 0xff551FFF, 0xff553F00, 0xff553F55, 0xff553FAA, 0xff553FFF,
+ 0xff555F00, 0xff555F55, 0xff555FAA, 0xff555FFF, 0xff557F00, 0xff557F55,
+ 0xff557FAA, 0xff557FFF, 0xff559F00, 0xff559F55, 0xff559FAA, 0xff559FFF,
+ 0xff55BF00, 0xff55BF55, 0xff55BFAA, 0xff55BFFF, 0xff55DF00, 0xff55DF55,
+ 0xff55DFAA, 0xff55DFFF, 0xff55FF00, 0xff55FF55, 0xff55FFAA, 0xff55FFFF,
+ 0xff7F0000, 0xff7F0055, 0xff7F00AA, 0xff7F00FF, 0xff7F1F00, 0xff7F1F55,
+ 0xff7F1FAA, 0xff7F1FFF, 0xff7F3F00, 0xff7F3F55, 0xff7F3FAA, 0xff7F3FFF,
+ 0xff7F5F00, 0xff7F5F55, 0xff7F5FAA, 0xff7F5FFF, 0xff7F7F00, 0xff7F7F55,
+ 0xff7F7FAA, 0xff7F7FFF, 0xff7F9F00, 0xff7F9F55, 0xff7F9FAA, 0xff7F9FFF,
+ 0xff7FBF00, 0xff7FBF55, 0xff7FBFAA, 0xff7FBFFF, 0xff7FDF00, 0xff7FDF55,
+ 0xff7FDFAA, 0xff7FDFFF, 0xff00FF7F, 0xff7FFF55, 0xff7FFFAA, 0xff7FFFFF,
+ 0xffAA0000, 0xffAA0055, 0xffAA00AA, 0xffAA00FF, 0xffAA1F00, 0xffAA1F55,
+ 0xffAA1FAA, 0xffAA1FFF, 0xffAA3F00, 0xffAA3F55, 0xffAA3FAA, 0xffAA3FFF,
+ 0xffAA5F00, 0xffAA5F55, 0xffAA5FAA, 0xffAA5FFF, 0xffAA7F00, 0xffAA7F55,
+ 0xffAA7FAA, 0xffAA7FFF, 0xffAA9F00, 0xffAA9F55, 0xffAA9FAA, 0xffAA9FFF,
+ 0xffAABF00, 0xffAABF55, 0xffAABFAA, 0xffAABFFF, 0xffAADF00, 0xffAADF55,
+ 0xffAADFAA, 0xffAADFFF, 0xffAAFF00, 0xffAAFF55, 0xffAAFFAA, 0xffAAFFFF,
+ 0xffD40000, 0xffD40055, 0xffD400AA, 0xffD400FF, 0xffD41F00, 0xffD41F55,
+ 0xffD41FAA, 0xffD41FFF, 0xffD43F00, 0xffD43F55, 0xffD43FAA, 0xffD43FFF,
+ 0xffD45F00, 0xffD45F55, 0xffD45FAA, 0xffD45FFF, 0xffD47F00, 0xffD47F55,
+ 0xffD47FAA, 0xffD4F7FF, 0xffD49F00, 0xffD49F55, 0xffD49FAA, 0xffD49FFF,
+ 0xffD4BF00, 0xffD4BF55, 0xffD4BFAA, 0xffD4BFFF, 0xffD4DF00, 0xffD4DF55,
+ 0xffD4DFAA, 0xffD4DFFF, 0xffD4FF00, 0xffD4FF55, 0xffD4FFAA, 0xffD4FFFF,
+ 0xffFF0055, 0xffFF00AA, 0xffFF1F00, 0xffFF1F55, 0xffFF1FAA, 0xffFF1FFF,
+ 0xffFF3F00, 0xffFF3F55, 0xffFF3FAA, 0xffFF3FFF, 0xffFF5F00, 0xffFF5F55,
+ 0xffFF5FAA, 0xffFF5FFF, 0xffFF7F00, 0xffFF7F55, 0xffFF7FAA, 0xffFF7FFF,
+ 0xffFF9F00, 0xffFF9F55, 0xffFF9FAA, 0xffFF9FFF, 0xffFFBF00, 0xffFFBF55,
+ 0xffFFBFAA, 0xffFFBFFF, 0xffFFDF00, 0xffFFDF55, 0xffFFDFAA, 0xffFFDFFF,
+ 0xffFFFF55, 0xffFFFFAA, 0xffCCCCFF, 0xffFFCCFF, 0xff33FFFF, 0xff66FFFF,
+ 0xff99FFFF, 0xffCCFFFF, 0xff007F00, 0xff007F55, 0xff007FAA, 0xff007FFF,
+ 0xff009F00, 0xff009F55, 0xff009FAA, 0xff009FFF, 0xff00BF00, 0xff00BF55,
+ 0xff00BFAA, 0xff00BFFF, 0xff00DF00, 0xff00DF55, 0xff00DFAA, 0xff00DFFF,
+ 0xff00FF55, 0xff00FFAA, 0xff2A0000, 0xff2A0055, 0xff2A00AA, 0xff2A00FF,
+ 0xff2A1F00, 0xff2A1F55, 0xff2A1FAA, 0xff2A1FFF, 0xff2A3F00, 0xff2A3F55,
+ 0xffFFFBF0, 0xffA0A0A4, 0xff808080, 0xffFF0000, 0xff00FF00, 0xffFF0000,
+ 0xff0000FF, 0xffFF00FF, 0xff00FFFF, 0xffFFFFFF};
+const FX_DWORD g_dwMacPalette[256] = {
+ 0xffFFFFFF, 0xffFFFFCC, 0xffFFFF99, 0xffFFFF66, 0xffFFFF33, 0xffFFFF00,
+ 0xffFFCCFF, 0xffFFCCCC, 0xffFFCC99, 0xffFFCC66, 0xffFFCC33, 0xffFFCC00,
+ 0xffFF99FF, 0xffFF99CC, 0xffFF9999, 0xffFF9966, 0xffFF9933, 0xffFF9900,
+ 0xffFF66FF, 0xffFF66CC, 0xffFF6699, 0xffFF6666, 0xffFF6633, 0xffFF6600,
+ 0xffFF33FF, 0xffFF33CC, 0xffFF3399, 0xffFF3366, 0xffFF3333, 0xffFF3300,
+ 0xffFF00FF, 0xffFF00CC, 0xffFF0099, 0xffFF0066, 0xffFF0033, 0xffFF0000,
+ 0xffCCFFFF, 0xffCCFFCC, 0xffCCFF99, 0xffCCFF66, 0xffCCFF33, 0xffCCFF00,
+ 0xffCCCCFF, 0xffCCCCCC, 0xffCCCC99, 0xffCCCC66, 0xffCCCC33, 0xffCCCC00,
+ 0xffCC99FF, 0xffCC99CC, 0xffCC9999, 0xffCC9966, 0xffCC9933, 0xffCC9900,
+ 0xffCC66FF, 0xffCC66CC, 0xffCC6699, 0xffCC6666, 0xffCC6633, 0xffCC6600,
+ 0xffCC33FF, 0xffCC33CC, 0xffCC3399, 0xffCC3366, 0xffCC3333, 0xffCC3300,
+ 0xffCC00FF, 0xffCC00CC, 0xffCC0099, 0xffCC0066, 0xffCC0033, 0xffCC0000,
+ 0xff99FFFF, 0xff99FFCC, 0xff99FF99, 0xff99FF66, 0xff99FF33, 0xff99FF00,
+ 0xff99CCFF, 0xff99CCCC, 0xff99CC99, 0xff99CC66, 0xff99CC33, 0xff99CC00,
+ 0xff9999FF, 0xff9999CC, 0xff999999, 0xff999966, 0xff999933, 0xff999900,
+ 0xff9966FF, 0xff9966CC, 0xff996699, 0xff996666, 0xff996633, 0xff996600,
+ 0xff9933FF, 0xff9933CC, 0xff993399, 0xff993366, 0xff993333, 0xff993300,
+ 0xff9900FF, 0xff9900CC, 0xff990099, 0xff990066, 0xff990033, 0xff990000,
+ 0xff66FFFF, 0xff66FFCC, 0xff66FF99, 0xff66FF66, 0xff66FF33, 0xff66FF00,
+ 0xff66CCFF, 0xff66CCCC, 0xff66CC99, 0xff66CC66, 0xff66CC33, 0xff66CC00,
+ 0xff6699FF, 0xff6699CC, 0xff669999, 0xff669966, 0xff669933, 0xff669900,
+ 0xff6666FF, 0xff6666CC, 0xff666699, 0xff666666, 0xff666633, 0xff666600,
+ 0xff6633FF, 0xff6633CC, 0xff663399, 0xff663366, 0xff663333, 0xff663300,
+ 0xff6600FF, 0xff6600CC, 0xff660099, 0xff660066, 0xff660033, 0xff660000,
+ 0xff33FFFF, 0xff33FFCC, 0xff33FF99, 0xff33FF66, 0xff33FF33, 0xff33FF00,
+ 0xff33CCFF, 0xff33CCCC, 0xff33CC99, 0xff33CC66, 0xff33CC33, 0xff33CC00,
+ 0xff3399FF, 0xff3399CC, 0xff339999, 0xff339966, 0xff339933, 0xff339900,
+ 0xff3366FF, 0xff3366CC, 0xff336699, 0xff336666, 0xff336633, 0xff336600,
+ 0xff3333FF, 0xff3333CC, 0xff333399, 0xff333366, 0xff333333, 0xff333300,
+ 0xff3300FF, 0xff3300CC, 0xff330099, 0xff330066, 0xff330033, 0xff330000,
+ 0xff00FFFF, 0xff00FFCC, 0xff00FF99, 0xff00FF66, 0xff00FF33, 0xff00FF00,
+ 0xff00CCFF, 0xff00CCCC, 0xff00CC99, 0xff00CC66, 0xff00CC33, 0xff00CC00,
+ 0xff0099FF, 0xff0099CC, 0xff009999, 0xff009966, 0xff009933, 0xff009900,
+ 0xff0066FF, 0xff0066CC, 0xff006699, 0xff006666, 0xff006633, 0xff006600,
+ 0xff0033FF, 0xff0033CC, 0xff003399, 0xff003366, 0xff003333, 0xff003300,
+ 0xff0000FF, 0xff0000CC, 0xff000099, 0xff000066, 0xff000033, 0xffEE0000,
+ 0xffDD0000, 0xffBB0000, 0xffAA0000, 0xff880000, 0xff770000, 0xff550000,
+ 0xff440000, 0xff220000, 0xff110000, 0xff00EE00, 0xff00DD00, 0xff00BB00,
+ 0xff00AA00, 0xff008800, 0xff007700, 0xff005500, 0xff004400, 0xff002200,
+ 0xff001100, 0xff0000EE, 0xff0000DD, 0xff0000BB, 0xff0000AA, 0xff000088,
+ 0xff000077, 0xff000055, 0xff000044, 0xff000022, 0xff000011, 0xffEEEEEE,
+ 0xffDDDDDD, 0xffBBBBBB, 0xffAAAAAA, 0xff888888, 0xff777777, 0xff555555,
+ 0xff444444, 0xff222222, 0xff111111, 0xff000000};
+class CFX_Palette {
+ public:
+ CFX_Palette();
+ ~CFX_Palette();
+
+ public:
+ FX_BOOL BuildPalette(const CFX_DIBSource* pBitmap, int dwPaletteType);
+ FX_DWORD* GetPalette() const { return m_pPalette; }
+
+ FX_DWORD* GetColorLut() const { return m_cLut; }
+ FX_DWORD* GetAmountLut() const { return m_aLut; }
+ int32_t Getlut() const { return m_lut; }
+
+ protected:
+ FX_DWORD* m_pPalette;
+ FX_DWORD* m_cLut;
+ FX_DWORD* m_aLut;
+ int m_lut;
+};
+int _Partition(FX_DWORD* alut, FX_DWORD* clut, int l, int r) {
+ FX_DWORD p_a = alut[l];
+ FX_DWORD p_c = clut[l];
+ while (l < r) {
+ while (l < r && alut[r] >= p_a) {
+ r--;
+ }
+ if (l < r) {
+ alut[l] = alut[r];
+ clut[l++] = clut[r];
+ }
+ while (l < r && alut[l] <= p_a) {
+ l++;
+ }
+ if (l < r) {
+ alut[r] = alut[l];
+ clut[r--] = clut[l];
+ }
+ }
+ alut[l] = p_a;
+ clut[l] = p_c;
+ return l;
+}
+void _Qsort(FX_DWORD* alut, FX_DWORD* clut, int l, int r) {
+ if (l < r) {
+ int pI = _Partition(alut, clut, l, r);
+ _Qsort(alut, clut, l, pI - 1);
+ _Qsort(alut, clut, pI + 1, r);
+ }
+}
+void _ColorDecode(FX_DWORD pal_v, uint8_t& r, uint8_t& g, uint8_t& b) {
+ r = (uint8_t)((pal_v & 0xf00) >> 4);
+ g = (uint8_t)(pal_v & 0x0f0);
+ b = (uint8_t)((pal_v & 0x00f) << 4);
+}
+void _Obtain_Pal(FX_DWORD* aLut,
+ FX_DWORD* cLut,
+ FX_DWORD* dest_pal,
+ int pal_type,
+ FX_DWORD* win_mac_pal,
+ FX_DWORD lut) {
+ int row, col;
+ FX_DWORD lut_1 = lut - 1;
+ if (pal_type == FXDIB_PALETTE_LOC) {
+ for (row = 0; row < 256; row++) {
+ int lut_offset = lut_1 - row;
+ if (lut_offset < 0) {
+ lut_offset += 256;
+ }
+ FX_DWORD color = cLut[lut_offset];
+ uint8_t r, g, b;
+ _ColorDecode(color, r, g, b);
+ dest_pal[row] = ((FX_DWORD)r << 16) | ((FX_DWORD)g << 8) | b | 0xff000000;
+ aLut[lut_offset] = row;
+ }
+ } else {
+ for (row = 0; row < 256; row++) {
+ int lut_offset = lut_1 - row;
+ if (lut_offset < 0) {
+ lut_offset += 256;
+ }
+ uint8_t r, g, b;
+ _ColorDecode(cLut[lut_offset], r, g, b);
+ int error, min_error = 1000000;
+ int c_index = 0;
+ for (col = 0; col < 256; col++) {
+ FX_DWORD p_color = win_mac_pal[col];
+ int d_r = r - (uint8_t)(p_color >> 16);
+ int d_g = g - (uint8_t)(p_color >> 8);
+ int d_b = b - (uint8_t)p_color;
+ error = d_r * d_r + d_g * d_g + d_b * d_b;
+ if (error < min_error) {
+ min_error = error;
+ c_index = col;
+ }
+ }
+ dest_pal[row] = win_mac_pal[c_index];
+ aLut[lut_offset] = row;
+ }
+ }
+}
+CFX_Palette::CFX_Palette() {
+ m_pPalette = NULL;
+ m_cLut = NULL;
+ m_aLut = NULL;
+ m_lut = 0;
+}
+CFX_Palette::~CFX_Palette() {
+ FX_Free(m_pPalette);
+ FX_Free(m_cLut);
+ FX_Free(m_aLut);
+ m_lut = 0;
+}
+FX_BOOL CFX_Palette::BuildPalette(const CFX_DIBSource* pBitmap, int pal_type) {
+ if (!pBitmap) {
+ return FALSE;
+ }
+ FX_Free(m_pPalette);
+ m_pPalette = FX_Alloc(FX_DWORD, 256);
+ int bpp = pBitmap->GetBPP() / 8;
+ int width = pBitmap->GetWidth();
+ int height = pBitmap->GetHeight();
+ FX_Free(m_cLut);
+ m_cLut = NULL;
+ FX_Free(m_aLut);
+ m_aLut = NULL;
+ m_cLut = FX_Alloc(FX_DWORD, 4096);
+ m_aLut = FX_Alloc(FX_DWORD, 4096);
+ int row, col;
+ m_lut = 0;
+ for (row = 0; row < height; row++) {
+ uint8_t* scan_line = (uint8_t*)pBitmap->GetScanline(row);
+ for (col = 0; col < width; col++) {
+ uint8_t* src_port = scan_line + col * bpp;
+ FX_DWORD b = src_port[0] & 0xf0;
+ FX_DWORD g = src_port[1] & 0xf0;
+ FX_DWORD r = src_port[2] & 0xf0;
+ FX_DWORD index = (r << 4) + g + (b >> 4);
+ m_aLut[index]++;
+ }
+ }
+ for (row = 0; row < 4096; row++) {
+ if (m_aLut[row] != 0) {
+ m_aLut[m_lut] = m_aLut[row];
+ m_cLut[m_lut] = row;
+ m_lut++;
+ }
+ }
+ _Qsort(m_aLut, m_cLut, 0, m_lut - 1);
+ FX_DWORD* win_mac_pal = NULL;
+ if (pal_type == FXDIB_PALETTE_WIN) {
+ win_mac_pal = (FX_DWORD*)g_dwWinPalette;
+ } else if (pal_type == FXDIB_PALETTE_MAC) {
+ win_mac_pal = (FX_DWORD*)g_dwMacPalette;
+ }
+ _Obtain_Pal(m_aLut, m_cLut, m_pPalette, pal_type, win_mac_pal, m_lut);
+ return TRUE;
+}
+FX_BOOL ConvertBuffer_1bppMask2Gray(uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top) {
+ uint8_t set_gray, reset_gray;
+ set_gray = 0xff;
+ reset_gray = 0x00;
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ FXSYS_memset(dest_scan, reset_gray, width);
+ const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
+ for (int col = src_left; col < src_left + width; col++) {
+ if (src_scan[col / 8] & (1 << (7 - col % 8))) {
+ *dest_scan = set_gray;
+ }
+ dest_scan++;
+ }
+ }
+ return TRUE;
+}
+FX_BOOL ConvertBuffer_8bppMask2Gray(uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top) {
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left;
+ FXSYS_memcpy(dest_scan, src_scan, width);
+ }
+ return TRUE;
+}
+FX_BOOL ConvertBuffer_1bppPlt2Gray(uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top,
+ void* pIccTransform) {
+ FX_DWORD* src_plt = pSrcBitmap->GetPalette();
+ uint8_t gray[2];
+ if (pIccTransform) {
+ FX_DWORD plt[2];
+ if (pSrcBitmap->IsCmykImage()) {
+ plt[0] = FXCMYK_TODIB(src_plt[0]);
+ plt[1] = FXCMYK_TODIB(src_plt[1]);
+ } else {
+ uint8_t* bgr_ptr = (uint8_t*)plt;
+ bgr_ptr[0] = FXARGB_B(src_plt[0]);
+ bgr_ptr[1] = FXARGB_G(src_plt[0]);
+ bgr_ptr[2] = FXARGB_R(src_plt[0]);
+ bgr_ptr[3] = FXARGB_B(src_plt[1]);
+ bgr_ptr[4] = FXARGB_G(src_plt[1]);
+ bgr_ptr[5] = FXARGB_R(src_plt[1]);
+ }
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ pIccModule->TranslateScanline(pIccTransform, gray, (const uint8_t*)plt, 2);
+ } else {
+ uint8_t reset_r, reset_g, reset_b, set_r, set_g, set_b;
+ if (pSrcBitmap->IsCmykImage()) {
+ AdobeCMYK_to_sRGB1(
+ FXSYS_GetCValue(src_plt[0]), FXSYS_GetMValue(src_plt[0]),
+ FXSYS_GetYValue(src_plt[0]), FXSYS_GetKValue(src_plt[0]), reset_r,
+ reset_g, reset_b);
+ AdobeCMYK_to_sRGB1(FXSYS_GetCValue(src_plt[1]),
+ FXSYS_GetMValue(src_plt[1]),
+ FXSYS_GetYValue(src_plt[1]),
+ FXSYS_GetKValue(src_plt[1]), set_r, set_g, set_b);
+ } else {
+ reset_r = FXARGB_R(src_plt[0]);
+ reset_g = FXARGB_G(src_plt[0]);
+ reset_b = FXARGB_B(src_plt[0]);
+ set_r = FXARGB_R(src_plt[1]);
+ set_g = FXARGB_G(src_plt[1]);
+ set_b = FXARGB_B(src_plt[1]);
+ }
+ gray[0] = FXRGB2GRAY(reset_r, reset_g, reset_b);
+ gray[1] = FXRGB2GRAY(set_r, set_g, set_b);
+ }
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ FXSYS_memset(dest_scan, gray[0], width);
+ const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
+ for (int col = src_left; col < src_left + width; col++) {
+ if (src_scan[col / 8] & (1 << (7 - col % 8))) {
+ *dest_scan = gray[1];
+ }
+ dest_scan++;
+ }
+ }
+ return TRUE;
+}
+FX_BOOL ConvertBuffer_8bppPlt2Gray(uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top,
+ void* pIccTransform) {
+ FX_DWORD* src_plt = pSrcBitmap->GetPalette();
+ uint8_t gray[256];
+ if (pIccTransform) {
+ FX_DWORD plt[256];
+ if (pSrcBitmap->IsCmykImage()) {
+ for (int i = 0; i < 256; i++) {
+ plt[i] = FXCMYK_TODIB(src_plt[i]);
+ }
+ } else {
+ uint8_t* bgr_ptr = (uint8_t*)plt;
+ for (int i = 0; i < 256; i++) {
+ *bgr_ptr++ = FXARGB_B(src_plt[i]);
+ *bgr_ptr++ = FXARGB_G(src_plt[i]);
+ *bgr_ptr++ = FXARGB_R(src_plt[i]);
+ }
+ }
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ pIccModule->TranslateScanline(pIccTransform, gray, (const uint8_t*)plt,
+ 256);
+ } else {
+ if (pSrcBitmap->IsCmykImage()) {
+ uint8_t r, g, b;
+ for (int i = 0; i < 256; i++) {
+ AdobeCMYK_to_sRGB1(
+ FXSYS_GetCValue(src_plt[i]), FXSYS_GetMValue(src_plt[i]),
+ FXSYS_GetYValue(src_plt[i]), FXSYS_GetKValue(src_plt[i]), r, g, b);
+ gray[i] = FXRGB2GRAY(r, g, b);
+ }
+ } else {
+ for (int i = 0; i < 256; i++) {
+ gray[i] = FXRGB2GRAY(FXARGB_R(src_plt[i]), FXARGB_G(src_plt[i]),
+ FXARGB_B(src_plt[i]));
+ }
+ }
+ }
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left;
+ for (int col = 0; col < width; col++) {
+ *dest_scan++ = gray[*src_scan++];
+ }
+ }
+ return TRUE;
+}
+FX_BOOL ConvertBuffer_RgbOrCmyk2Gray(uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top,
+ void* pIccTransform) {
+ int Bpp = pSrcBitmap->GetBPP() / 8;
+ if (pIccTransform) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ if (Bpp == 3 || pSrcBitmap->IsCmykImage()) {
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan =
+ pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp;
+ pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan,
+ width);
+ }
+ } else {
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan =
+ pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
+ for (int col = 0; col < width; col++) {
+ pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 1);
+ dest_scan++;
+ src_scan += 4;
+ }
+ }
+ }
+ } else {
+ if (pSrcBitmap->IsCmykImage()) {
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan =
+ pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
+ for (int col = 0; col < width; col++) {
+ uint8_t r, g, b;
+ AdobeCMYK_to_sRGB1(FXSYS_GetCValue((FX_DWORD)src_scan[0]),
+ FXSYS_GetMValue((FX_DWORD)src_scan[1]),
+ FXSYS_GetYValue((FX_DWORD)src_scan[2]),
+ FXSYS_GetKValue((FX_DWORD)src_scan[3]), r, g, b);
+ *dest_scan++ = FXRGB2GRAY(r, g, b);
+ src_scan += 4;
+ }
+ }
+ } else {
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan =
+ pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp;
+ for (int col = 0; col < width; col++) {
+ *dest_scan++ = FXRGB2GRAY(src_scan[2], src_scan[1], src_scan[0]);
+ src_scan += Bpp;
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+inline void ConvertBuffer_IndexCopy(uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top) {
+ if (pSrcBitmap->GetBPP() == 1) {
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ FXSYS_memset(dest_scan, 0, width);
+ const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
+ for (int col = src_left; col < src_left + width; col++) {
+ if (src_scan[col / 8] & (1 << (7 - col % 8))) {
+ *dest_scan = 1;
+ }
+ dest_scan++;
+ }
+ }
+ } else {
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan =
+ pSrcBitmap->GetScanline(src_top + row) + src_left;
+ FXSYS_memcpy(dest_scan, src_scan, width);
+ }
+ }
+}
+FX_BOOL ConvertBuffer_Plt2PltRgb8(uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top,
+ FX_DWORD* dst_plt,
+ void* pIccTransform) {
+ ConvertBuffer_IndexCopy(dest_buf, dest_pitch, width, height, pSrcBitmap,
+ src_left, src_top);
+ FX_DWORD* src_plt = pSrcBitmap->GetPalette();
+ int plt_size = pSrcBitmap->GetPaletteSize();
+ if (pIccTransform) {
+ FX_DWORD plt[256];
+ uint8_t* bgr_ptr = (uint8_t*)plt;
+ if (pSrcBitmap->IsCmykImage()) {
+ for (int i = 0; i < plt_size; i++) {
+ plt[i] = FXCMYK_TODIB(src_plt[i]);
+ }
+ } else {
+ for (int i = 0; i < plt_size; i++) {
+ *bgr_ptr++ = FXARGB_B(src_plt[i]);
+ *bgr_ptr++ = FXARGB_G(src_plt[i]);
+ *bgr_ptr++ = FXARGB_R(src_plt[i]);
+ }
+ bgr_ptr = (uint8_t*)plt;
+ }
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ pIccModule->TranslateScanline(pIccTransform, (uint8_t*)plt,
+ (const uint8_t*)plt, plt_size);
+ for (int i = 0; i < plt_size; i++) {
+ dst_plt[i] = FXARGB_MAKE(0xff, bgr_ptr[2], bgr_ptr[1], bgr_ptr[0]);
+ bgr_ptr += 3;
+ }
+ } else {
+ if (pSrcBitmap->IsCmykImage()) {
+ for (int i = 0; i < plt_size; i++) {
+ uint8_t r, g, b;
+ AdobeCMYK_to_sRGB1(
+ FXSYS_GetCValue(src_plt[i]), FXSYS_GetMValue(src_plt[i]),
+ FXSYS_GetYValue(src_plt[i]), FXSYS_GetKValue(src_plt[i]), r, g, b);
+ dst_plt[i] = FXARGB_MAKE(0xff, r, g, b);
+ }
+ } else {
+ FXSYS_memcpy(dst_plt, src_plt, plt_size * 4);
+ }
+ }
+ return TRUE;
+}
+FX_BOOL ConvertBuffer_Rgb2PltRgb8_NoTransform(uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top,
+ FX_DWORD* dst_plt) {
+ int bpp = pSrcBitmap->GetBPP() / 8;
+ int row, col;
+ CFX_Palette palette;
+ palette.BuildPalette(pSrcBitmap, FXDIB_PALETTE_LOC);
+ FX_DWORD* cLut = palette.GetColorLut();
+ FX_DWORD* aLut = palette.GetAmountLut();
+ if (!cLut || !aLut) {
+ return FALSE;
+ }
+ int lut = palette.Getlut();
+ FX_DWORD* pPalette = palette.GetPalette();
+ if (lut > 256) {
+ int err, min_err;
+ int lut_256 = lut - 256;
+ for (row = 0; row < lut_256; row++) {
+ min_err = 1000000;
+ uint8_t r, g, b;
+ _ColorDecode(cLut[row], r, g, b);
+ int clrindex = 0;
+ for (int col = 0; col < 256; col++) {
+ FX_DWORD p_color = *(pPalette + col);
+ int d_r = r - (uint8_t)(p_color >> 16);
+ int d_g = g - (uint8_t)(p_color >> 8);
+ int d_b = b - (uint8_t)(p_color);
+ err = d_r * d_r + d_g * d_g + d_b * d_b;
+ if (err < min_err) {
+ min_err = err;
+ clrindex = col;
+ }
+ }
+ aLut[row] = clrindex;
+ }
+ }
+ int32_t lut_1 = lut - 1;
+ for (row = 0; row < height; row++) {
+ uint8_t* src_scan =
+ (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left;
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ for (col = 0; col < width; col++) {
+ uint8_t* src_port = src_scan + col * bpp;
+ int r = src_port[2] & 0xf0;
+ int g = src_port[1] & 0xf0;
+ int b = src_port[0] & 0xf0;
+ FX_DWORD clrindex = (r << 4) + g + (b >> 4);
+ for (int i = lut_1; i >= 0; i--)
+ if (clrindex == cLut[i]) {
+ *(dest_scan + col) = (uint8_t)(aLut[i]);
+ break;
+ }
+ }
+ }
+ FXSYS_memcpy(dst_plt, pPalette, sizeof(FX_DWORD) * 256);
+ return TRUE;
+}
+FX_BOOL ConvertBuffer_Rgb2PltRgb8(uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top,
+ FX_DWORD* dst_plt,
+ void* pIccTransform) {
+ FX_BOOL ret = ConvertBuffer_Rgb2PltRgb8_NoTransform(
+ dest_buf, dest_pitch, width, height, pSrcBitmap, src_left, src_top,
+ dst_plt);
+ if (ret && pIccTransform) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ for (int i = 0; i < 256; i++) {
+ FX_ARGB* plt = dst_plt + i;
+ FX_ARGB plt_entry = FXARGB_TODIB(*plt);
+ pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&plt_entry,
+ (const uint8_t*)&plt_entry, 1);
+ *plt = FXARGB_TODIB(plt_entry);
+ }
+ }
+ return ret;
+}
+FX_BOOL ConvertBuffer_1bppMask2Rgb(FXDIB_Format dst_format,
+ uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top) {
+ int comps = (dst_format & 0xff) / 8;
+ uint8_t set_gray, reset_gray;
+ set_gray = 0xff;
+ reset_gray = 0x00;
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
+ for (int col = src_left; col < src_left + width; col++) {
+ if (src_scan[col / 8] & (1 << (7 - col % 8))) {
+ dest_scan[0] = set_gray;
+ dest_scan[1] = set_gray;
+ dest_scan[2] = set_gray;
+ } else {
+ dest_scan[0] = reset_gray;
+ dest_scan[1] = reset_gray;
+ dest_scan[2] = reset_gray;
+ }
+ dest_scan += comps;
+ }
+ }
+ return TRUE;
+}
+FX_BOOL ConvertBuffer_8bppMask2Rgb(FXDIB_Format dst_format,
+ uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top) {
+ int comps = (dst_format & 0xff) / 8;
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left;
+ uint8_t src_pixel;
+ for (int col = 0; col < width; col++) {
+ src_pixel = *src_scan++;
+ *dest_scan++ = src_pixel;
+ *dest_scan++ = src_pixel;
+ *dest_scan = src_pixel;
+ dest_scan += comps - 2;
+ }
+ }
+ return TRUE;
+}
+FX_BOOL ConvertBuffer_1bppPlt2Rgb(FXDIB_Format dst_format,
+ uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top,
+ void* pIccTransform) {
+ int comps = (dst_format & 0xff) / 8;
+ FX_DWORD* src_plt = pSrcBitmap->GetPalette();
+ FX_DWORD plt[2];
+ uint8_t* bgr_ptr = (uint8_t*)plt;
+ if (pSrcBitmap->IsCmykImage()) {
+ plt[0] = FXCMYK_TODIB(src_plt[0]);
+ plt[1] = FXCMYK_TODIB(src_plt[1]);
+ } else {
+ bgr_ptr[0] = FXARGB_B(src_plt[0]);
+ bgr_ptr[1] = FXARGB_G(src_plt[0]);
+ bgr_ptr[2] = FXARGB_R(src_plt[0]);
+ bgr_ptr[3] = FXARGB_B(src_plt[1]);
+ bgr_ptr[4] = FXARGB_G(src_plt[1]);
+ bgr_ptr[5] = FXARGB_R(src_plt[1]);
+ }
+ if (pIccTransform) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ pIccModule->TranslateScanline(pIccTransform, (uint8_t*)plt,
+ (const uint8_t*)plt, 2);
+ } else {
+ if (pSrcBitmap->IsCmykImage()) {
+ AdobeCMYK_to_sRGB1(
+ FXSYS_GetCValue(src_plt[0]), FXSYS_GetMValue(src_plt[0]),
+ FXSYS_GetYValue(src_plt[0]), FXSYS_GetKValue(src_plt[0]), bgr_ptr[2],
+ bgr_ptr[1], bgr_ptr[0]);
+ AdobeCMYK_to_sRGB1(
+ FXSYS_GetCValue(src_plt[1]), FXSYS_GetMValue(src_plt[1]),
+ FXSYS_GetYValue(src_plt[1]), FXSYS_GetKValue(src_plt[1]), bgr_ptr[5],
+ bgr_ptr[4], bgr_ptr[3]);
+ }
+ }
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
+ for (int col = src_left; col < src_left + width; col++) {
+ if (src_scan[col / 8] & (1 << (7 - col % 8))) {
+ *dest_scan++ = bgr_ptr[3];
+ *dest_scan++ = bgr_ptr[4];
+ *dest_scan = bgr_ptr[5];
+ } else {
+ *dest_scan++ = bgr_ptr[0];
+ *dest_scan++ = bgr_ptr[1];
+ *dest_scan = bgr_ptr[2];
+ }
+ dest_scan += comps - 2;
+ }
+ }
+ return TRUE;
+}
+FX_BOOL ConvertBuffer_8bppPlt2Rgb(FXDIB_Format dst_format,
+ uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top,
+ void* pIccTransform) {
+ int comps = (dst_format & 0xff) / 8;
+ FX_DWORD* src_plt = pSrcBitmap->GetPalette();
+ FX_DWORD plt[256];
+ uint8_t* bgr_ptr = (uint8_t*)plt;
+ if (!pSrcBitmap->IsCmykImage()) {
+ for (int i = 0; i < 256; i++) {
+ *bgr_ptr++ = FXARGB_B(src_plt[i]);
+ *bgr_ptr++ = FXARGB_G(src_plt[i]);
+ *bgr_ptr++ = FXARGB_R(src_plt[i]);
+ }
+ bgr_ptr = (uint8_t*)plt;
+ }
+ if (pIccTransform) {
+ if (pSrcBitmap->IsCmykImage()) {
+ for (int i = 0; i < 256; i++) {
+ plt[i] = FXCMYK_TODIB(src_plt[i]);
+ }
+ }
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ pIccModule->TranslateScanline(pIccTransform, (uint8_t*)plt,
+ (const uint8_t*)plt, 256);
+ } else {
+ if (pSrcBitmap->IsCmykImage()) {
+ for (int i = 0; i < 256; i++) {
+ AdobeCMYK_to_sRGB1(
+ FXSYS_GetCValue(src_plt[i]), FXSYS_GetMValue(src_plt[i]),
+ FXSYS_GetYValue(src_plt[i]), FXSYS_GetKValue(src_plt[i]),
+ bgr_ptr[2], bgr_ptr[1], bgr_ptr[0]);
+ bgr_ptr += 3;
+ }
+ bgr_ptr = (uint8_t*)plt;
+ }
+ }
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left;
+ for (int col = 0; col < width; col++) {
+ uint8_t* src_pixel = bgr_ptr + 3 * (*src_scan++);
+ *dest_scan++ = *src_pixel++;
+ *dest_scan++ = *src_pixel++;
+ *dest_scan = *src_pixel++;
+ dest_scan += comps - 2;
+ }
+ }
+ return TRUE;
+}
+FX_BOOL ConvertBuffer_24bppRgb2Rgb24(uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top,
+ void* pIccTransform) {
+ if (pIccTransform) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan =
+ pSrcBitmap->GetScanline(src_top + row) + src_left * 3;
+ pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, width);
+ }
+ } else {
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan =
+ pSrcBitmap->GetScanline(src_top + row) + src_left * 3;
+ FXSYS_memcpy(dest_scan, src_scan, width * 3);
+ }
+ }
+ return TRUE;
+}
+FX_BOOL ConvertBuffer_32bppRgb2Rgb24(uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top,
+ void* pIccTransform) {
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan =
+ pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
+ for (int col = 0; col < width; col++) {
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ src_scan++;
+ }
+ }
+ if (pIccTransform) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ pIccModule->TranslateScanline(pIccTransform, dest_scan, dest_scan, width);
+ }
+ }
+ return TRUE;
+}
+FX_BOOL ConvertBuffer_Rgb2Rgb32(uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top,
+ void* pIccTransform) {
+ int comps = pSrcBitmap->GetBPP() / 8;
+ if (pIccTransform) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan =
+ pSrcBitmap->GetScanline(src_top + row) + src_left * comps;
+ for (int col = 0; col < width; col++) {
+ pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 1);
+ dest_scan += 4;
+ src_scan += comps;
+ }
+ }
+ } else {
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan =
+ pSrcBitmap->GetScanline(src_top + row) + src_left * comps;
+ for (int col = 0; col < width; col++) {
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ dest_scan++;
+ src_scan += comps - 3;
+ }
+ }
+ }
+ return TRUE;
+}
+FX_BOOL ConvertBuffer_32bppCmyk2Rgb32(uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top,
+ void* pIccTransform) {
+ if (pIccTransform) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan =
+ pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
+ for (int col = 0; col < width; col++) {
+ pIccModule->TranslateScanline(pIccTransform, dest_scan, src_scan, 1);
+ dest_scan += 4;
+ src_scan += 4;
+ }
+ }
+ } else {
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = dest_buf + row * dest_pitch;
+ const uint8_t* src_scan =
+ pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
+ for (int col = 0; col < width; col++) {
+ AdobeCMYK_to_sRGB1(src_scan[0], src_scan[1], src_scan[2], src_scan[3],
+ dest_scan[2], dest_scan[1], dest_scan[0]);
+ dest_scan += 4;
+ src_scan += 4;
+ }
+ }
+ }
+ return TRUE;
+}
+FX_BOOL ConvertBuffer(FXDIB_Format dest_format,
+ uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top,
+ FX_DWORD*& d_pal,
+ void* pIccTransform) {
+ FXDIB_Format src_format = pSrcBitmap->GetFormat();
+ if (!CFX_GEModule::Get()->GetCodecModule() ||
+ !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) {
+ pIccTransform = NULL;
+ }
+ switch (dest_format) {
+ case FXDIB_Invalid:
+ case FXDIB_1bppCmyk:
+ case FXDIB_1bppMask:
+ case FXDIB_1bppRgb:
+ ASSERT(FALSE);
+ return FALSE;
+ case FXDIB_8bppMask: {
+ if ((src_format & 0xff) == 1) {
+ if (pSrcBitmap->GetPalette()) {
+ return ConvertBuffer_1bppPlt2Gray(dest_buf, dest_pitch, width, height,
+ pSrcBitmap, src_left, src_top,
+ pIccTransform);
+ }
+ return ConvertBuffer_1bppMask2Gray(dest_buf, dest_pitch, width, height,
+ pSrcBitmap, src_left, src_top);
+ }
+ if ((src_format & 0xff) == 8) {
+ if (pSrcBitmap->GetPalette()) {
+ return ConvertBuffer_8bppPlt2Gray(dest_buf, dest_pitch, width, height,
+ pSrcBitmap, src_left, src_top,
+ pIccTransform);
+ }
+ return ConvertBuffer_8bppMask2Gray(dest_buf, dest_pitch, width, height,
+ pSrcBitmap, src_left, src_top);
+ }
+ if ((src_format & 0xff) >= 24) {
+ return ConvertBuffer_RgbOrCmyk2Gray(dest_buf, dest_pitch, width, height,
+ pSrcBitmap, src_left, src_top,
+ pIccTransform);
+ }
+ return FALSE;
+ }
+ case FXDIB_8bppRgb:
+ case FXDIB_8bppRgba: {
+ if ((src_format & 0xff) == 8 && !pSrcBitmap->GetPalette()) {
+ return ConvertBuffer(FXDIB_8bppMask, dest_buf, dest_pitch, width,
+ height, pSrcBitmap, src_left, src_top, d_pal,
+ pIccTransform);
+ }
+ d_pal = FX_Alloc(FX_DWORD, 256);
+ if (((src_format & 0xff) == 1 || (src_format & 0xff) == 8) &&
+ pSrcBitmap->GetPalette()) {
+ return ConvertBuffer_Plt2PltRgb8(dest_buf, dest_pitch, width, height,
+ pSrcBitmap, src_left, src_top, d_pal,
+ pIccTransform);
+ }
+ if ((src_format & 0xff) >= 24) {
+ return ConvertBuffer_Rgb2PltRgb8(dest_buf, dest_pitch, width, height,
+ pSrcBitmap, src_left, src_top, d_pal,
+ pIccTransform);
+ }
+ return FALSE;
+ }
+ case FXDIB_Rgb:
+ case FXDIB_Rgba: {
+ if ((src_format & 0xff) == 1) {
+ if (pSrcBitmap->GetPalette()) {
+ return ConvertBuffer_1bppPlt2Rgb(dest_format, dest_buf, dest_pitch,
+ width, height, pSrcBitmap, src_left,
+ src_top, pIccTransform);
+ }
+ return ConvertBuffer_1bppMask2Rgb(dest_format, dest_buf, dest_pitch,
+ width, height, pSrcBitmap, src_left,
+ src_top);
+ }
+ if ((src_format & 0xff) == 8) {
+ if (pSrcBitmap->GetPalette()) {
+ return ConvertBuffer_8bppPlt2Rgb(dest_format, dest_buf, dest_pitch,
+ width, height, pSrcBitmap, src_left,
+ src_top, pIccTransform);
+ }
+ return ConvertBuffer_8bppMask2Rgb(dest_format, dest_buf, dest_pitch,
+ width, height, pSrcBitmap, src_left,
+ src_top);
+ }
+ if ((src_format & 0xff) == 24) {
+ return ConvertBuffer_24bppRgb2Rgb24(dest_buf, dest_pitch, width, height,
+ pSrcBitmap, src_left, src_top,
+ pIccTransform);
+ }
+ if ((src_format & 0xff) == 32) {
+ return ConvertBuffer_32bppRgb2Rgb24(dest_buf, dest_pitch, width, height,
+ pSrcBitmap, src_left, src_top,
+ pIccTransform);
+ }
+ return FALSE;
+ }
+ case FXDIB_Argb:
+ case FXDIB_Rgb32: {
+ if ((src_format & 0xff) == 1) {
+ if (pSrcBitmap->GetPalette()) {
+ return ConvertBuffer_1bppPlt2Rgb(dest_format, dest_buf, dest_pitch,
+ width, height, pSrcBitmap, src_left,
+ src_top, pIccTransform);
+ }
+ return ConvertBuffer_1bppMask2Rgb(dest_format, dest_buf, dest_pitch,
+ width, height, pSrcBitmap, src_left,
+ src_top);
+ }
+ if ((src_format & 0xff) == 8) {
+ if (pSrcBitmap->GetPalette()) {
+ return ConvertBuffer_8bppPlt2Rgb(dest_format, dest_buf, dest_pitch,
+ width, height, pSrcBitmap, src_left,
+ src_top, pIccTransform);
+ }
+ return ConvertBuffer_8bppMask2Rgb(dest_format, dest_buf, dest_pitch,
+ width, height, pSrcBitmap, src_left,
+ src_top);
+ }
+ if ((src_format & 0xff) >= 24) {
+ if (src_format & 0x0400) {
+ return ConvertBuffer_32bppCmyk2Rgb32(dest_buf, dest_pitch, width,
+ height, pSrcBitmap, src_left,
+ src_top, pIccTransform);
+ }
+ return ConvertBuffer_Rgb2Rgb32(dest_buf, dest_pitch, width, height,
+ pSrcBitmap, src_left, src_top,
+ pIccTransform);
+ }
+ return FALSE;
+ }
+ default:
+ return FALSE;
+ }
+ return FALSE;
+}
+CFX_DIBitmap* CFX_DIBSource::CloneConvert(FXDIB_Format dest_format,
+ const FX_RECT* pClip,
+ void* pIccTransform) const {
+ if (dest_format == GetFormat() && !pIccTransform) {
+ return Clone(pClip);
+ }
+ if (pClip) {
+ CFX_DIBitmap* pClone = Clone(pClip);
+ if (!pClone) {
+ return NULL;
+ }
+ if (!pClone->ConvertFormat(dest_format, pIccTransform)) {
+ delete pClone;
+ return NULL;
+ }
+ return pClone;
+ }
+ CFX_DIBitmap* pClone = new CFX_DIBitmap;
+ if (!pClone->Create(m_Width, m_Height, dest_format)) {
+ delete pClone;
+ return NULL;
+ }
+ FX_BOOL ret = TRUE;
+ CFX_DIBitmap* pSrcAlpha = NULL;
+ if (HasAlpha()) {
+ pSrcAlpha = (GetFormat() == FXDIB_Argb) ? GetAlphaMask() : m_pAlphaMask;
+ if (!pSrcAlpha) {
+ delete pClone;
+ return NULL;
+ }
+ }
+ if (dest_format & 0x0200) {
+ if (dest_format == FXDIB_Argb) {
+ ret = pSrcAlpha ? pClone->LoadChannel(FXDIB_Alpha, pSrcAlpha, FXDIB_Alpha)
+ : pClone->LoadChannel(FXDIB_Alpha, 0xff);
+ } else {
+ ret = pClone->CopyAlphaMask(pSrcAlpha);
+ }
+ }
+ if (pSrcAlpha && pSrcAlpha != m_pAlphaMask) {
+ delete pSrcAlpha;
+ pSrcAlpha = NULL;
+ }
+ if (!ret) {
+ delete pClone;
+ return NULL;
+ }
+ FX_DWORD* pal_8bpp = NULL;
+ ret = ConvertBuffer(dest_format, pClone->GetBuffer(), pClone->GetPitch(),
+ m_Width, m_Height, this, 0, 0, pal_8bpp, pIccTransform);
+ if (!ret) {
+ FX_Free(pal_8bpp);
+ delete pClone;
+ return NULL;
+ }
+ if (pal_8bpp) {
+ pClone->CopyPalette(pal_8bpp);
+ FX_Free(pal_8bpp);
+ pal_8bpp = NULL;
+ }
+ return pClone;
+}
+FX_BOOL CFX_DIBitmap::ConvertFormat(FXDIB_Format dest_format,
+ void* pIccTransform) {
+ FXDIB_Format src_format = GetFormat();
+ if (dest_format == src_format && !pIccTransform) {
+ return TRUE;
+ }
+ if (dest_format == FXDIB_8bppMask && src_format == FXDIB_8bppRgb &&
+ !m_pPalette) {
+ m_AlphaFlag = 1;
+ return TRUE;
+ }
+ if (dest_format == FXDIB_Argb && src_format == FXDIB_Rgb32 &&
+ !pIccTransform) {
+ m_AlphaFlag = 2;
+ for (int row = 0; row < m_Height; row++) {
+ uint8_t* scanline = m_pBuffer + row * m_Pitch + 3;
+ for (int col = 0; col < m_Width; col++) {
+ *scanline = 0xff;
+ scanline += 4;
+ }
+ }
+ return TRUE;
+ }
+ int dest_bpp = dest_format & 0xff;
+ int dest_pitch = (dest_bpp * m_Width + 31) / 32 * 4;
+ uint8_t* dest_buf = FX_TryAlloc(uint8_t, dest_pitch * m_Height + 4);
+ if (!dest_buf) {
+ return FALSE;
+ }
+ CFX_DIBitmap* pAlphaMask = NULL;
+ if (dest_format == FXDIB_Argb) {
+ FXSYS_memset(dest_buf, 0xff, dest_pitch * m_Height + 4);
+ if (m_pAlphaMask) {
+ for (int row = 0; row < m_Height; row++) {
+ uint8_t* pDstScanline = dest_buf + row * dest_pitch + 3;
+ const uint8_t* pSrcScanline = m_pAlphaMask->GetScanline(row);
+ for (int col = 0; col < m_Width; col++) {
+ *pDstScanline = *pSrcScanline++;
+ pDstScanline += 4;
+ }
+ }
+ }
+ } else if (dest_format & 0x0200) {
+ if (src_format == FXDIB_Argb) {
+ pAlphaMask = GetAlphaMask();
+ if (!pAlphaMask) {
+ FX_Free(dest_buf);
+ return FALSE;
+ }
+ } else {
+ if (!m_pAlphaMask) {
+ if (!BuildAlphaMask()) {
+ FX_Free(dest_buf);
+ return FALSE;
+ }
+ pAlphaMask = m_pAlphaMask;
+ m_pAlphaMask = NULL;
+ } else {
+ pAlphaMask = m_pAlphaMask;
+ }
+ }
+ }
+ FX_BOOL ret = FALSE;
+ FX_DWORD* pal_8bpp = NULL;
+ ret = ConvertBuffer(dest_format, dest_buf, dest_pitch, m_Width, m_Height,
+ this, 0, 0, pal_8bpp, pIccTransform);
+ if (!ret) {
+ FX_Free(pal_8bpp);
+ if (pAlphaMask != m_pAlphaMask) {
+ delete pAlphaMask;
+ }
+ FX_Free(dest_buf);
+ return FALSE;
+ }
+ if (m_pAlphaMask && pAlphaMask != m_pAlphaMask) {
+ delete m_pAlphaMask;
+ }
+ m_pAlphaMask = pAlphaMask;
+ FX_Free(m_pPalette);
+ m_pPalette = pal_8bpp;
+ if (!m_bExtBuf) {
+ FX_Free(m_pBuffer);
+ }
+ m_bExtBuf = FALSE;
+ m_pBuffer = dest_buf;
+ m_bpp = (uint8_t)dest_format;
+ m_AlphaFlag = (uint8_t)(dest_format >> 8);
+ m_Pitch = dest_pitch;
+ return TRUE;
+}
diff --git a/core/fxge/dib/fx_dib_engine.cpp b/core/fxge/dib/fx_dib_engine.cpp
new file mode 100644
index 0000000000..10e5e67bbc
--- /dev/null
+++ b/core/fxge/dib/fx_dib_engine.cpp
@@ -0,0 +1,917 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include <limits.h>
+
+#include "core/fxge/dib/dib_int.h"
+#include "core/include/fxge/fx_dib.h"
+#include "core/include/fxge/fx_ge.h"
+
+void CWeightTable::Calc(int dest_len,
+ int dest_min,
+ int dest_max,
+ int src_len,
+ int src_min,
+ int src_max,
+ int flags) {
+ FX_Free(m_pWeightTables);
+ m_pWeightTables = NULL;
+ double scale, base;
+ scale = (FX_FLOAT)src_len / (FX_FLOAT)dest_len;
+ if (dest_len < 0) {
+ base = (FX_FLOAT)(src_len);
+ } else {
+ base = 0;
+ }
+ int ext_size = flags & FXDIB_BICUBIC_INTERPOL ? 3 : 1;
+ m_ItemSize =
+ sizeof(int) * 2 +
+ (int)(sizeof(int) * (FXSYS_ceil(FXSYS_fabs((FX_FLOAT)scale)) + ext_size));
+ m_DestMin = dest_min;
+ if ((dest_max - dest_min) > (int)((1U << 30) - 4) / m_ItemSize) {
+ return;
+ }
+ m_pWeightTables =
+ FX_TryAlloc(uint8_t, (dest_max - dest_min) * m_ItemSize + 4);
+ if (!m_pWeightTables) {
+ return;
+ }
+ if ((flags & FXDIB_NOSMOOTH) != 0 || FXSYS_fabs((FX_FLOAT)scale) < 1.0f) {
+ for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel++) {
+ PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel);
+ double src_pos = dest_pixel * scale + scale / 2 + base;
+ if (flags & FXDIB_INTERPOL) {
+ pixel_weights.m_SrcStart =
+ (int)FXSYS_floor((FX_FLOAT)src_pos - 1.0f / 2);
+ pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_FLOAT)src_pos + 1.0f / 2);
+ if (pixel_weights.m_SrcStart < src_min) {
+ pixel_weights.m_SrcStart = src_min;
+ }
+ if (pixel_weights.m_SrcEnd >= src_max) {
+ pixel_weights.m_SrcEnd = src_max - 1;
+ }
+ if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) {
+ pixel_weights.m_Weights[0] = 65536;
+ } else {
+ pixel_weights.m_Weights[1] = FXSYS_round(
+ (FX_FLOAT)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) *
+ 65536);
+ pixel_weights.m_Weights[0] = 65536 - pixel_weights.m_Weights[1];
+ }
+ } else if (flags & FXDIB_BICUBIC_INTERPOL) {
+ pixel_weights.m_SrcStart =
+ (int)FXSYS_floor((FX_FLOAT)src_pos - 1.0f / 2);
+ pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_FLOAT)src_pos + 1.0f / 2);
+ int start = pixel_weights.m_SrcStart - 1;
+ int end = pixel_weights.m_SrcEnd + 1;
+ if (start < src_min) {
+ start = src_min;
+ }
+ if (end >= src_max) {
+ end = src_max - 1;
+ }
+ if (pixel_weights.m_SrcStart < src_min) {
+ src_pos += src_min - pixel_weights.m_SrcStart;
+ pixel_weights.m_SrcStart = src_min;
+ }
+ if (pixel_weights.m_SrcEnd >= src_max) {
+ pixel_weights.m_SrcEnd = src_max - 1;
+ }
+ int weight;
+ weight = FXSYS_round(
+ (FX_FLOAT)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * 256);
+ if (start == end) {
+ pixel_weights.m_Weights[0] =
+ (SDP_Table[256 + weight] + SDP_Table[weight] +
+ SDP_Table[256 - weight] + SDP_Table[512 - weight])
+ << 8;
+ } else if ((start == pixel_weights.m_SrcStart &&
+ (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd ||
+ end == pixel_weights.m_SrcEnd) &&
+ start < end) ||
+ (start < pixel_weights.m_SrcStart &&
+ pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd &&
+ end == pixel_weights.m_SrcEnd)) {
+ if (start < pixel_weights.m_SrcStart) {
+ pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8;
+ pixel_weights.m_Weights[1] =
+ (SDP_Table[weight] + SDP_Table[256 - weight] +
+ SDP_Table[512 - weight])
+ << 8;
+ } else {
+ if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) {
+ pixel_weights.m_Weights[0] =
+ (SDP_Table[256 + weight] + SDP_Table[weight] +
+ SDP_Table[256 - weight])
+ << 8;
+ pixel_weights.m_Weights[1] = SDP_Table[512 - weight] << 8;
+ } else {
+ pixel_weights.m_Weights[0] =
+ (SDP_Table[256 + weight] + SDP_Table[weight]) << 8;
+ pixel_weights.m_Weights[1] =
+ (SDP_Table[256 - weight] + SDP_Table[512 - weight]) << 8;
+ }
+ }
+ if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) {
+ pixel_weights.m_SrcEnd = end;
+ }
+ if (start < pixel_weights.m_SrcStart) {
+ pixel_weights.m_SrcStart = start;
+ }
+ } else if (start == pixel_weights.m_SrcStart &&
+ start < pixel_weights.m_SrcEnd &&
+ pixel_weights.m_SrcEnd < end) {
+ pixel_weights.m_Weights[0] =
+ (SDP_Table[256 + weight] + SDP_Table[weight]) << 8;
+ pixel_weights.m_Weights[1] = SDP_Table[256 - weight] << 8;
+ pixel_weights.m_Weights[2] = SDP_Table[512 - weight] << 8;
+ pixel_weights.m_SrcEnd = end;
+ } else if (start < pixel_weights.m_SrcStart &&
+ pixel_weights.m_SrcStart < pixel_weights.m_SrcEnd &&
+ pixel_weights.m_SrcEnd == end) {
+ pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8;
+ pixel_weights.m_Weights[1] = SDP_Table[weight] << 8;
+ pixel_weights.m_Weights[2] =
+ (SDP_Table[256 - weight] + SDP_Table[512 - weight]) << 8;
+ pixel_weights.m_SrcStart = start;
+ } else {
+ pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8;
+ pixel_weights.m_Weights[1] = SDP_Table[weight] << 8;
+ pixel_weights.m_Weights[2] = SDP_Table[256 - weight] << 8;
+ pixel_weights.m_Weights[3] = SDP_Table[512 - weight] << 8;
+ pixel_weights.m_SrcStart = start;
+ pixel_weights.m_SrcEnd = end;
+ }
+ } else {
+ pixel_weights.m_SrcStart = pixel_weights.m_SrcEnd =
+ (int)FXSYS_floor((FX_FLOAT)src_pos);
+ if (pixel_weights.m_SrcStart < src_min) {
+ pixel_weights.m_SrcStart = src_min;
+ }
+ if (pixel_weights.m_SrcEnd >= src_max) {
+ pixel_weights.m_SrcEnd = src_max - 1;
+ }
+ pixel_weights.m_Weights[0] = 65536;
+ }
+ }
+ return;
+ }
+ for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel++) {
+ PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel);
+ double src_start = dest_pixel * scale + base;
+ double src_end = src_start + scale;
+ int start_i, end_i;
+ if (src_start < src_end) {
+ start_i = (int)FXSYS_floor((FX_FLOAT)src_start);
+ end_i = (int)FXSYS_ceil((FX_FLOAT)src_end);
+ } else {
+ start_i = (int)FXSYS_floor((FX_FLOAT)src_end);
+ end_i = (int)FXSYS_ceil((FX_FLOAT)src_start);
+ }
+ if (start_i < src_min) {
+ start_i = src_min;
+ }
+ if (end_i >= src_max) {
+ end_i = src_max - 1;
+ }
+ if (start_i > end_i) {
+ if (start_i >= src_max) {
+ start_i = src_max - 1;
+ }
+ pixel_weights.m_SrcStart = start_i;
+ pixel_weights.m_SrcEnd = start_i;
+ continue;
+ }
+ pixel_weights.m_SrcStart = start_i;
+ pixel_weights.m_SrcEnd = end_i;
+ for (int j = start_i; j <= end_i; j++) {
+ double dest_start = ((FX_FLOAT)j - base) / scale;
+ double dest_end = ((FX_FLOAT)(j + 1) - base) / scale;
+ if (dest_start > dest_end) {
+ double temp = dest_start;
+ dest_start = dest_end;
+ dest_end = temp;
+ }
+ double area_start = dest_start > (FX_FLOAT)(dest_pixel)
+ ? dest_start
+ : (FX_FLOAT)(dest_pixel);
+ double area_end = dest_end > (FX_FLOAT)(dest_pixel + 1)
+ ? (FX_FLOAT)(dest_pixel + 1)
+ : dest_end;
+ double weight = area_start >= area_end ? 0.0f : area_end - area_start;
+ if (weight == 0 && j == end_i) {
+ pixel_weights.m_SrcEnd--;
+ break;
+ }
+ pixel_weights.m_Weights[j - start_i] =
+ FXSYS_round((FX_FLOAT)(weight * 65536));
+ }
+ }
+}
+CStretchEngine::CStretchEngine(IFX_ScanlineComposer* pDestBitmap,
+ FXDIB_Format dest_format,
+ int dest_width,
+ int dest_height,
+ const FX_RECT& clip_rect,
+ const CFX_DIBSource* pSrcBitmap,
+ int flags) {
+ m_State = 0;
+ m_DestFormat = dest_format;
+ m_DestBpp = dest_format & 0xff;
+ m_SrcBpp = pSrcBitmap->GetFormat() & 0xff;
+ m_bHasAlpha = pSrcBitmap->GetFormat() & 0x200;
+ m_pSrcPalette = pSrcBitmap->GetPalette();
+ m_pDestBitmap = pDestBitmap;
+ m_DestWidth = dest_width;
+ m_DestHeight = dest_height;
+ m_pInterBuf = NULL;
+ m_pExtraAlphaBuf = NULL;
+ m_pDestMaskScanline = NULL;
+ m_DestClip = clip_rect;
+ FX_DWORD size = clip_rect.Width();
+ if (size && m_DestBpp > (int)(INT_MAX / size)) {
+ return;
+ }
+ size *= m_DestBpp;
+ if (size > INT_MAX - 31) {
+ return;
+ }
+ size += 31;
+ size = size / 32 * 4;
+ m_pDestScanline = FX_TryAlloc(uint8_t, size);
+ if (!m_pDestScanline) {
+ return;
+ }
+ if (dest_format == FXDIB_Rgb32) {
+ FXSYS_memset(m_pDestScanline, 255, size);
+ }
+ m_InterPitch = (m_DestClip.Width() * m_DestBpp + 31) / 32 * 4;
+ m_ExtraMaskPitch = (m_DestClip.Width() * 8 + 31) / 32 * 4;
+ m_pInterBuf = NULL;
+ m_pSource = pSrcBitmap;
+ m_SrcWidth = pSrcBitmap->GetWidth();
+ m_SrcHeight = pSrcBitmap->GetHeight();
+ m_SrcPitch = (m_SrcWidth * m_SrcBpp + 31) / 32 * 4;
+ if ((flags & FXDIB_NOSMOOTH) == 0) {
+ FX_BOOL bInterpol =
+ flags & FXDIB_INTERPOL || flags & FXDIB_BICUBIC_INTERPOL;
+ if (!bInterpol && FXSYS_abs(dest_width) != 0 &&
+ FXSYS_abs(dest_height) <
+ m_SrcWidth * m_SrcHeight * 8 / FXSYS_abs(dest_width)) {
+ flags = FXDIB_INTERPOL;
+ }
+ m_Flags = flags;
+ } else {
+ m_Flags = FXDIB_NOSMOOTH;
+ if (flags & FXDIB_DOWNSAMPLE) {
+ m_Flags |= FXDIB_DOWNSAMPLE;
+ }
+ }
+ double scale_x = (FX_FLOAT)m_SrcWidth / (FX_FLOAT)m_DestWidth;
+ double scale_y = (FX_FLOAT)m_SrcHeight / (FX_FLOAT)m_DestHeight;
+ double base_x = m_DestWidth > 0 ? 0.0f : (FX_FLOAT)(m_DestWidth);
+ double base_y = m_DestHeight > 0 ? 0.0f : (FX_FLOAT)(m_DestHeight);
+ double src_left = scale_x * ((FX_FLOAT)(clip_rect.left) + base_x);
+ double src_right = scale_x * ((FX_FLOAT)(clip_rect.right) + base_x);
+ double src_top = scale_y * ((FX_FLOAT)(clip_rect.top) + base_y);
+ double src_bottom = scale_y * ((FX_FLOAT)(clip_rect.bottom) + base_y);
+ if (src_left > src_right) {
+ double temp = src_left;
+ src_left = src_right;
+ src_right = temp;
+ }
+ if (src_top > src_bottom) {
+ double temp = src_top;
+ src_top = src_bottom;
+ src_bottom = temp;
+ }
+ m_SrcClip.left = (int)FXSYS_floor((FX_FLOAT)src_left);
+ m_SrcClip.right = (int)FXSYS_ceil((FX_FLOAT)src_right);
+ m_SrcClip.top = (int)FXSYS_floor((FX_FLOAT)src_top);
+ m_SrcClip.bottom = (int)FXSYS_ceil((FX_FLOAT)src_bottom);
+ FX_RECT src_rect(0, 0, m_SrcWidth, m_SrcHeight);
+ m_SrcClip.Intersect(src_rect);
+ if (m_SrcBpp == 1) {
+ if (m_DestBpp == 8) {
+ m_TransMethod = 1;
+ } else {
+ m_TransMethod = 2;
+ }
+ } else if (m_SrcBpp == 8) {
+ if (m_DestBpp == 8) {
+ if (!m_bHasAlpha) {
+ m_TransMethod = 3;
+ } else {
+ m_TransMethod = 4;
+ }
+ } else {
+ if (!m_bHasAlpha) {
+ m_TransMethod = 5;
+ } else {
+ m_TransMethod = 6;
+ }
+ }
+ } else {
+ if (!m_bHasAlpha) {
+ m_TransMethod = 7;
+ } else {
+ m_TransMethod = 8;
+ }
+ }
+}
+FX_BOOL CStretchEngine::Continue(IFX_Pause* pPause) {
+ while (m_State == 1) {
+ if (ContinueStretchHorz(pPause)) {
+ return TRUE;
+ }
+ m_State = 2;
+ StretchVert();
+ }
+ return FALSE;
+}
+CStretchEngine::~CStretchEngine() {
+ FX_Free(m_pDestScanline);
+ FX_Free(m_pInterBuf);
+ FX_Free(m_pExtraAlphaBuf);
+ FX_Free(m_pDestMaskScanline);
+}
+FX_BOOL CStretchEngine::StartStretchHorz() {
+ if (m_DestWidth == 0 || !m_pDestScanline ||
+ m_SrcClip.Height() > (int)((1U << 29) / m_InterPitch) ||
+ m_SrcClip.Height() == 0) {
+ return FALSE;
+ }
+ m_pInterBuf = FX_TryAlloc(unsigned char, m_SrcClip.Height() * m_InterPitch);
+ if (!m_pInterBuf) {
+ return FALSE;
+ }
+ if (m_pSource && m_bHasAlpha && m_pSource->m_pAlphaMask) {
+ m_pExtraAlphaBuf =
+ FX_Alloc2D(unsigned char, m_SrcClip.Height(), m_ExtraMaskPitch);
+ FX_DWORD size = (m_DestClip.Width() * 8 + 31) / 32 * 4;
+ m_pDestMaskScanline = FX_TryAlloc(unsigned char, size);
+ if (!m_pDestMaskScanline) {
+ return FALSE;
+ }
+ }
+ m_WeightTable.Calc(m_DestWidth, m_DestClip.left, m_DestClip.right, m_SrcWidth,
+ m_SrcClip.left, m_SrcClip.right, m_Flags);
+ if (!m_WeightTable.m_pWeightTables) {
+ return FALSE;
+ }
+ m_CurRow = m_SrcClip.top;
+ m_State = 1;
+ return TRUE;
+}
+#define FX_STRECH_PAUSE_ROWS 10
+FX_BOOL CStretchEngine::ContinueStretchHorz(IFX_Pause* pPause) {
+ if (!m_DestWidth) {
+ return 0;
+ }
+ if (m_pSource->SkipToScanline(m_CurRow, pPause)) {
+ return TRUE;
+ }
+ int Bpp = m_DestBpp / 8;
+ int rows_to_go = FX_STRECH_PAUSE_ROWS;
+ for (; m_CurRow < m_SrcClip.bottom; m_CurRow++) {
+ if (rows_to_go == 0) {
+ if (pPause && pPause->NeedToPauseNow()) {
+ return TRUE;
+ }
+ rows_to_go = FX_STRECH_PAUSE_ROWS;
+ }
+ const uint8_t* src_scan = m_pSource->GetScanline(m_CurRow);
+ uint8_t* dest_scan =
+ m_pInterBuf + (m_CurRow - m_SrcClip.top) * m_InterPitch;
+ const uint8_t* src_scan_mask = NULL;
+ uint8_t* dest_scan_mask = NULL;
+ if (m_pExtraAlphaBuf) {
+ src_scan_mask = m_pSource->m_pAlphaMask->GetScanline(m_CurRow);
+ dest_scan_mask =
+ m_pExtraAlphaBuf + (m_CurRow - m_SrcClip.top) * m_ExtraMaskPitch;
+ }
+ switch (m_TransMethod) {
+ case 1:
+ case 2: {
+ for (int col = m_DestClip.left; col < m_DestClip.right; col++) {
+ PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col);
+ int dest_a = 0;
+ for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
+ j++) {
+ int pixel_weight =
+ pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+ if (src_scan[j / 8] & (1 << (7 - j % 8))) {
+ dest_a += pixel_weight * 255;
+ }
+ }
+ if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+ dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 16711680 : dest_a;
+ }
+ *dest_scan++ = (uint8_t)(dest_a >> 16);
+ }
+ break;
+ }
+ case 3: {
+ for (int col = m_DestClip.left; col < m_DestClip.right; col++) {
+ PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col);
+ int dest_a = 0;
+ for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
+ j++) {
+ int pixel_weight =
+ pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+ dest_a += pixel_weight * src_scan[j];
+ }
+ if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+ dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 16711680 : dest_a;
+ }
+ *dest_scan++ = (uint8_t)(dest_a >> 16);
+ }
+ break;
+ }
+ case 4: {
+ for (int col = m_DestClip.left; col < m_DestClip.right; col++) {
+ PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col);
+ int dest_a = 0, dest_r = 0;
+ for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
+ j++) {
+ int pixel_weight =
+ pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+ pixel_weight = pixel_weight * src_scan_mask[j] / 255;
+ dest_r += pixel_weight * src_scan[j];
+ dest_a += pixel_weight;
+ }
+ if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+ dest_r = dest_r < 0 ? 0 : dest_r > 16711680 ? 16711680 : dest_r;
+ dest_a = dest_a < 0 ? 0 : dest_a > 65536 ? 65536 : dest_a;
+ }
+ *dest_scan++ = (uint8_t)(dest_r >> 16);
+ *dest_scan_mask++ = (uint8_t)((dest_a * 255) >> 16);
+ }
+ break;
+ }
+ case 5: {
+ for (int col = m_DestClip.left; col < m_DestClip.right; col++) {
+ PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col);
+ int dest_r_y = 0, dest_g_m = 0, dest_b_c = 0;
+ for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
+ j++) {
+ int pixel_weight =
+ pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+ unsigned long argb_cmyk = m_pSrcPalette[src_scan[j]];
+ if (m_DestFormat == FXDIB_Rgb) {
+ dest_r_y += pixel_weight * (uint8_t)(argb_cmyk >> 16);
+ dest_g_m += pixel_weight * (uint8_t)(argb_cmyk >> 8);
+ dest_b_c += pixel_weight * (uint8_t)argb_cmyk;
+ } else {
+ dest_b_c += pixel_weight * (uint8_t)(argb_cmyk >> 24);
+ dest_g_m += pixel_weight * (uint8_t)(argb_cmyk >> 16);
+ dest_r_y += pixel_weight * (uint8_t)(argb_cmyk >> 8);
+ }
+ }
+ if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+ dest_r_y =
+ dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y;
+ dest_g_m =
+ dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m;
+ dest_b_c =
+ dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c;
+ }
+ *dest_scan++ = (uint8_t)(dest_b_c >> 16);
+ *dest_scan++ = (uint8_t)(dest_g_m >> 16);
+ *dest_scan++ = (uint8_t)(dest_r_y >> 16);
+ }
+ break;
+ }
+ case 6: {
+ for (int col = m_DestClip.left; col < m_DestClip.right; col++) {
+ PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col);
+ int dest_a = 0, dest_r_y = 0, dest_g_m = 0, dest_b_c = 0;
+ for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
+ j++) {
+ int pixel_weight =
+ pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+ pixel_weight = pixel_weight * src_scan_mask[j] / 255;
+ unsigned long argb_cmyk = m_pSrcPalette[src_scan[j]];
+ if (m_DestFormat == FXDIB_Rgba) {
+ dest_r_y += pixel_weight * (uint8_t)(argb_cmyk >> 16);
+ dest_g_m += pixel_weight * (uint8_t)(argb_cmyk >> 8);
+ dest_b_c += pixel_weight * (uint8_t)argb_cmyk;
+ } else {
+ dest_b_c += pixel_weight * (uint8_t)(argb_cmyk >> 24);
+ dest_g_m += pixel_weight * (uint8_t)(argb_cmyk >> 16);
+ dest_r_y += pixel_weight * (uint8_t)(argb_cmyk >> 8);
+ }
+ dest_a += pixel_weight;
+ }
+ if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+ dest_b_c =
+ dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c;
+ dest_g_m =
+ dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m;
+ dest_r_y =
+ dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y;
+ dest_a = dest_a < 0 ? 0 : dest_a > 65536 ? 65536 : dest_a;
+ }
+ *dest_scan++ = (uint8_t)(dest_b_c >> 16);
+ *dest_scan++ = (uint8_t)(dest_g_m >> 16);
+ *dest_scan++ = (uint8_t)(dest_r_y >> 16);
+ *dest_scan_mask++ = (uint8_t)((dest_a * 255) >> 16);
+ }
+ break;
+ }
+ case 7: {
+ for (int col = m_DestClip.left; col < m_DestClip.right; col++) {
+ PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col);
+ int dest_r_y = 0, dest_g_m = 0, dest_b_c = 0;
+ for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
+ j++) {
+ int pixel_weight =
+ pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+ const uint8_t* src_pixel = src_scan + j * Bpp;
+ dest_b_c += pixel_weight * (*src_pixel++);
+ dest_g_m += pixel_weight * (*src_pixel++);
+ dest_r_y += pixel_weight * (*src_pixel);
+ }
+ if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+ dest_b_c =
+ dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c;
+ dest_g_m =
+ dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m;
+ dest_r_y =
+ dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y;
+ }
+ *dest_scan++ = (uint8_t)((dest_b_c) >> 16);
+ *dest_scan++ = (uint8_t)((dest_g_m) >> 16);
+ *dest_scan++ = (uint8_t)((dest_r_y) >> 16);
+ dest_scan += Bpp - 3;
+ }
+ break;
+ }
+ case 8: {
+ for (int col = m_DestClip.left; col < m_DestClip.right; col++) {
+ PixelWeight* pPixelWeights = m_WeightTable.GetPixelWeight(col);
+ int dest_a = 0, dest_r_y = 0, dest_g_m = 0, dest_b_c = 0;
+ for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
+ j++) {
+ int pixel_weight =
+ pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+ const uint8_t* src_pixel = src_scan + j * Bpp;
+ if (m_DestFormat == FXDIB_Argb) {
+ pixel_weight = pixel_weight * src_pixel[3] / 255;
+ } else {
+ pixel_weight = pixel_weight * src_scan_mask[j] / 255;
+ }
+ dest_b_c += pixel_weight * (*src_pixel++);
+ dest_g_m += pixel_weight * (*src_pixel++);
+ dest_r_y += pixel_weight * (*src_pixel);
+ dest_a += pixel_weight;
+ }
+ if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+ dest_r_y =
+ dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y;
+ dest_g_m =
+ dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m;
+ dest_b_c =
+ dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c;
+ dest_a = dest_a < 0 ? 0 : dest_a > 65536 ? 65536 : dest_a;
+ }
+ *dest_scan++ = (uint8_t)((dest_b_c) >> 16);
+ *dest_scan++ = (uint8_t)((dest_g_m) >> 16);
+ *dest_scan++ = (uint8_t)((dest_r_y) >> 16);
+ if (m_DestFormat == FXDIB_Argb) {
+ *dest_scan = (uint8_t)((dest_a * 255) >> 16);
+ }
+ if (dest_scan_mask) {
+ *dest_scan_mask++ = (uint8_t)((dest_a * 255) >> 16);
+ }
+ dest_scan += Bpp - 3;
+ }
+ break;
+ }
+ }
+ rows_to_go--;
+ }
+ return FALSE;
+}
+void CStretchEngine::StretchVert() {
+ if (m_DestHeight == 0) {
+ return;
+ }
+ CWeightTable table;
+ table.Calc(m_DestHeight, m_DestClip.top, m_DestClip.bottom, m_SrcHeight,
+ m_SrcClip.top, m_SrcClip.bottom, m_Flags);
+ if (!table.m_pWeightTables) {
+ return;
+ }
+ int DestBpp = m_DestBpp / 8;
+ for (int row = m_DestClip.top; row < m_DestClip.bottom; row++) {
+ unsigned char* dest_scan = m_pDestScanline;
+ unsigned char* dest_sacn_mask = m_pDestMaskScanline;
+ PixelWeight* pPixelWeights = table.GetPixelWeight(row);
+ switch (m_TransMethod) {
+ case 1:
+ case 2:
+ case 3: {
+ for (int col = m_DestClip.left; col < m_DestClip.right; col++) {
+ unsigned char* src_scan =
+ m_pInterBuf + (col - m_DestClip.left) * DestBpp;
+ int dest_a = 0;
+ for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
+ j++) {
+ int pixel_weight =
+ pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+ dest_a +=
+ pixel_weight * src_scan[(j - m_SrcClip.top) * m_InterPitch];
+ }
+ if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+ dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 16711680 : dest_a;
+ }
+ *dest_scan = (uint8_t)(dest_a >> 16);
+ dest_scan += DestBpp;
+ }
+ break;
+ }
+ case 4: {
+ for (int col = m_DestClip.left; col < m_DestClip.right; col++) {
+ unsigned char* src_scan =
+ m_pInterBuf + (col - m_DestClip.left) * DestBpp;
+ unsigned char* src_scan_mask =
+ m_pExtraAlphaBuf + (col - m_DestClip.left);
+ int dest_a = 0, dest_k = 0;
+ for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
+ j++) {
+ int pixel_weight =
+ pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+ dest_k +=
+ pixel_weight * src_scan[(j - m_SrcClip.top) * m_InterPitch];
+ dest_a += pixel_weight *
+ src_scan_mask[(j - m_SrcClip.top) * m_ExtraMaskPitch];
+ }
+ if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+ dest_k = dest_k < 0 ? 0 : dest_k > 16711680 ? 16711680 : dest_k;
+ dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 16711680 : dest_a;
+ }
+ *dest_scan = (uint8_t)(dest_k >> 16);
+ dest_scan += DestBpp;
+ *dest_sacn_mask++ = (uint8_t)(dest_a >> 16);
+ }
+ break;
+ }
+ case 5:
+ case 7: {
+ for (int col = m_DestClip.left; col < m_DestClip.right; col++) {
+ unsigned char* src_scan =
+ m_pInterBuf + (col - m_DestClip.left) * DestBpp;
+ int dest_r_y = 0, dest_g_m = 0, dest_b_c = 0;
+ for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
+ j++) {
+ int pixel_weight =
+ pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+ const uint8_t* src_pixel =
+ src_scan + (j - m_SrcClip.top) * m_InterPitch;
+ dest_b_c += pixel_weight * (*src_pixel++);
+ dest_g_m += pixel_weight * (*src_pixel++);
+ dest_r_y += pixel_weight * (*src_pixel);
+ }
+ if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+ dest_r_y =
+ dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y;
+ dest_g_m =
+ dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m;
+ dest_b_c =
+ dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c;
+ }
+ dest_scan[0] = (uint8_t)((dest_b_c) >> 16);
+ dest_scan[1] = (uint8_t)((dest_g_m) >> 16);
+ dest_scan[2] = (uint8_t)((dest_r_y) >> 16);
+ dest_scan += DestBpp;
+ }
+ break;
+ }
+ case 6:
+ case 8: {
+ for (int col = m_DestClip.left; col < m_DestClip.right; col++) {
+ unsigned char* src_scan =
+ m_pInterBuf + (col - m_DestClip.left) * DestBpp;
+ unsigned char* src_scan_mask = NULL;
+ if (m_DestFormat != FXDIB_Argb) {
+ src_scan_mask = m_pExtraAlphaBuf + (col - m_DestClip.left);
+ }
+ int dest_a = 0, dest_r_y = 0, dest_g_m = 0, dest_b_c = 0;
+ for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
+ j++) {
+ int pixel_weight =
+ pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
+ const uint8_t* src_pixel =
+ src_scan + (j - m_SrcClip.top) * m_InterPitch;
+ int mask_v = 255;
+ if (src_scan_mask) {
+ mask_v = src_scan_mask[(j - m_SrcClip.top) * m_ExtraMaskPitch];
+ }
+ dest_b_c += pixel_weight * (*src_pixel++);
+ dest_g_m += pixel_weight * (*src_pixel++);
+ dest_r_y += pixel_weight * (*src_pixel);
+ if (m_DestFormat == FXDIB_Argb) {
+ dest_a += pixel_weight * (*(src_pixel + 1));
+ } else {
+ dest_a += pixel_weight * mask_v;
+ }
+ }
+ if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+ dest_r_y =
+ dest_r_y < 0 ? 0 : dest_r_y > 16711680 ? 16711680 : dest_r_y;
+ dest_g_m =
+ dest_g_m < 0 ? 0 : dest_g_m > 16711680 ? 16711680 : dest_g_m;
+ dest_b_c =
+ dest_b_c < 0 ? 0 : dest_b_c > 16711680 ? 16711680 : dest_b_c;
+ dest_a = dest_a < 0 ? 0 : dest_a > 16711680 ? 16711680 : dest_a;
+ }
+ if (dest_a) {
+ int r = ((FX_DWORD)dest_r_y) * 255 / dest_a;
+ int g = ((FX_DWORD)dest_g_m) * 255 / dest_a;
+ int b = ((FX_DWORD)dest_b_c) * 255 / dest_a;
+ dest_scan[0] = b > 255 ? 255 : b < 0 ? 0 : b;
+ dest_scan[1] = g > 255 ? 255 : g < 0 ? 0 : g;
+ dest_scan[2] = r > 255 ? 255 : r < 0 ? 0 : r;
+ }
+ if (m_DestFormat == FXDIB_Argb) {
+ dest_scan[3] = (uint8_t)((dest_a) >> 16);
+ } else {
+ *dest_sacn_mask = (uint8_t)((dest_a) >> 16);
+ }
+ dest_scan += DestBpp;
+ if (dest_sacn_mask) {
+ dest_sacn_mask++;
+ }
+ }
+ break;
+ }
+ }
+ m_pDestBitmap->ComposeScanline(row - m_DestClip.top, m_pDestScanline,
+ m_pDestMaskScanline);
+ }
+}
+CFX_ImageStretcher::CFX_ImageStretcher() {
+ m_pScanline = NULL;
+ m_pStretchEngine = NULL;
+ m_pMaskScanline = NULL;
+}
+CFX_ImageStretcher::~CFX_ImageStretcher() {
+ FX_Free(m_pScanline);
+ delete m_pStretchEngine;
+ FX_Free(m_pMaskScanline);
+}
+FXDIB_Format _GetStretchedFormat(const CFX_DIBSource* pSrc) {
+ FXDIB_Format format = pSrc->GetFormat();
+ if (format == FXDIB_1bppMask) {
+ format = FXDIB_8bppMask;
+ } else if (format == FXDIB_1bppRgb) {
+ format = FXDIB_8bppRgb;
+ } else if (format == FXDIB_8bppRgb) {
+ if (pSrc->GetPalette()) {
+ format = FXDIB_Rgb;
+ }
+ }
+ return format;
+}
+FX_BOOL CFX_ImageStretcher::Start(IFX_ScanlineComposer* pDest,
+ const CFX_DIBSource* pSource,
+ int dest_width,
+ int dest_height,
+ const FX_RECT& rect,
+ FX_DWORD flags) {
+ 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()) {
+ 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);
+ for (int i = 0; i < 256; i++) {
+ int a = a0 + (a1 - a0) * i / 255;
+ int r = r0 + (r1 - r0) * i / 255;
+ int g = g0 + (g1 - g0) * i / 255;
+ int b = b0 + (b1 - b0) * i / 255;
+ pal[i] = ArgbEncode(a, r, g, b);
+ }
+ if (!pDest->SetInfo(rect.Width(), rect.Height(), m_DestFormat, pal)) {
+ return FALSE;
+ }
+ } else if (pSource->GetFormat() == FXDIB_1bppCmyk && 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);
+ for (int i = 0; i < 256; i++) {
+ int c = c0 + (c1 - c0) * i / 255;
+ int m = m0 + (m1 - m0) * i / 255;
+ int y = y0 + (y1 - y0) * i / 255;
+ int k = k0 + (k1 - k0) * i / 255;
+ pal[i] = CmykEncode(c, m, y, k);
+ }
+ if (!pDest->SetInfo(rect.Width(), rect.Height(), m_DestFormat, pal)) {
+ return FALSE;
+ }
+ } else if (!pDest->SetInfo(rect.Width(), rect.Height(), m_DestFormat, NULL)) {
+ return FALSE;
+ }
+ if (flags & FXDIB_DOWNSAMPLE) {
+ return StartQuickStretch();
+ }
+ return StartStretch();
+}
+FX_BOOL CFX_ImageStretcher::Continue(IFX_Pause* pPause) {
+ if (m_Flags & FXDIB_DOWNSAMPLE) {
+ return ContinueQuickStretch(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->StartStretchHorz();
+ if (m_pSource->GetWidth() * m_pSource->GetHeight() <
+ MAX_PROGRESSIVE_STRETCH_PIXELS) {
+ m_pStretchEngine->Continue(NULL);
+ 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;
+ }
+ if (m_DestHeight < 0) {
+ m_bFlipY = TRUE;
+ m_DestHeight = -m_DestHeight;
+ }
+ m_LineIndex = 0;
+ FX_DWORD 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);
+ return FALSE;
+ }
+ return TRUE;
+}
+FX_BOOL CFX_ImageStretcher::ContinueQuickStretch(IFX_Pause* pPause) {
+ if (!m_pScanline) {
+ return FALSE;
+ }
+ int result_width = m_ClipRect.Width(), result_height = m_ClipRect.Height();
+ int src_height = m_pSource->GetHeight();
+ for (; m_LineIndex < result_height; m_LineIndex++) {
+ int dest_y, src_y;
+ if (m_bFlipY) {
+ dest_y = result_height - m_LineIndex - 1;
+ src_y = (m_DestHeight - (dest_y + m_ClipRect.top) - 1) * src_height /
+ m_DestHeight;
+ } else {
+ 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)) {
+ return TRUE;
+ }
+ m_pSource->DownSampleScanline(src_y, m_pScanline, 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);
+ }
+ m_pDest->ComposeScanline(dest_y, m_pScanline, m_pMaskScanline);
+ }
+ return FALSE;
+}
diff --git a/core/fxge/dib/fx_dib_main.cpp b/core/fxge/dib/fx_dib_main.cpp
new file mode 100644
index 0000000000..8ce20568df
--- /dev/null
+++ b/core/fxge/dib/fx_dib_main.cpp
@@ -0,0 +1,1745 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/include/fxge/fx_dib.h"
+
+#include <limits.h>
+
+#include "core/fxge/dib/dib_int.h"
+#include "core/include/fxcodec/fx_codec.h"
+#include "core/include/fxge/fx_ge.h"
+
+FX_BOOL ConvertBuffer(FXDIB_Format dest_format,
+ uint8_t* dest_buf,
+ int dest_pitch,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top,
+ FX_DWORD*& pal,
+ void* pIccTransform);
+void CmykDecode(FX_DWORD cmyk, int& c, int& m, int& y, int& k) {
+ c = FXSYS_GetCValue(cmyk);
+ m = FXSYS_GetMValue(cmyk);
+ y = FXSYS_GetYValue(cmyk);
+ k = FXSYS_GetKValue(cmyk);
+}
+void ArgbDecode(FX_DWORD argb, int& a, int& r, int& g, int& b) {
+ a = FXARGB_A(argb);
+ r = FXARGB_R(argb);
+ g = FXARGB_G(argb);
+ b = FXARGB_B(argb);
+}
+void ArgbDecode(FX_DWORD argb, int& a, FX_COLORREF& rgb) {
+ a = FXARGB_A(argb);
+ rgb = FXSYS_RGB(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb));
+}
+FX_DWORD ArgbEncode(int a, FX_COLORREF rgb) {
+ return FXARGB_MAKE(a, FXSYS_GetRValue(rgb), FXSYS_GetGValue(rgb),
+ FXSYS_GetBValue(rgb));
+}
+
+CFX_DIBSource::CFX_DIBSource() {
+ m_bpp = 0;
+ m_AlphaFlag = 0;
+ m_Width = m_Height = 0;
+ m_Pitch = 0;
+ m_pPalette = NULL;
+ m_pAlphaMask = NULL;
+}
+
+CFX_DIBSource::~CFX_DIBSource() {
+ FX_Free(m_pPalette);
+ delete m_pAlphaMask;
+}
+
+uint8_t* CFX_DIBSource::GetBuffer() const {
+ return NULL;
+}
+
+FX_BOOL CFX_DIBSource::SkipToScanline(int line, IFX_Pause* pPause) const {
+ return FALSE;
+}
+
+CFX_DIBitmap::CFX_DIBitmap() {
+ m_bExtBuf = FALSE;
+ m_pBuffer = NULL;
+ m_pPalette = NULL;
+}
+
+#define _MAX_OOM_LIMIT_ 12000000
+FX_BOOL CFX_DIBitmap::Create(int width,
+ int height,
+ FXDIB_Format format,
+ uint8_t* pBuffer,
+ int pitch) {
+ m_pBuffer = NULL;
+ m_bpp = (uint8_t)format;
+ m_AlphaFlag = (uint8_t)(format >> 8);
+ m_Width = m_Height = m_Pitch = 0;
+ if (width <= 0 || height <= 0 || pitch < 0) {
+ return FALSE;
+ }
+ if ((INT_MAX - 31) / width < (format & 0xff)) {
+ return FALSE;
+ }
+ if (!pitch) {
+ pitch = (width * (format & 0xff) + 31) / 32 * 4;
+ }
+ if ((1 << 30) / pitch < height) {
+ return FALSE;
+ }
+ if (pBuffer) {
+ m_pBuffer = pBuffer;
+ m_bExtBuf = TRUE;
+ } else {
+ int size = pitch * height + 4;
+ int oomlimit = _MAX_OOM_LIMIT_;
+ if (oomlimit >= 0 && size >= oomlimit) {
+ m_pBuffer = FX_TryAlloc(uint8_t, size);
+ if (!m_pBuffer) {
+ return FALSE;
+ }
+ } else {
+ m_pBuffer = FX_Alloc(uint8_t, size);
+ }
+ }
+ m_Width = width;
+ m_Height = height;
+ m_Pitch = pitch;
+ if (HasAlpha() && format != FXDIB_Argb) {
+ FX_BOOL ret = TRUE;
+ ret = BuildAlphaMask();
+ if (!ret) {
+ if (!m_bExtBuf) {
+ FX_Free(m_pBuffer);
+ m_pBuffer = NULL;
+ m_Width = m_Height = m_Pitch = 0;
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+FX_BOOL CFX_DIBitmap::Copy(const CFX_DIBSource* pSrc) {
+ if (m_pBuffer) {
+ return FALSE;
+ }
+ if (!Create(pSrc->GetWidth(), pSrc->GetHeight(), pSrc->GetFormat())) {
+ return FALSE;
+ }
+ CopyPalette(pSrc->GetPalette());
+ CopyAlphaMask(pSrc->m_pAlphaMask);
+ for (int row = 0; row < pSrc->GetHeight(); row++) {
+ FXSYS_memcpy(m_pBuffer + row * m_Pitch, pSrc->GetScanline(row), m_Pitch);
+ }
+ return TRUE;
+}
+
+CFX_DIBitmap::~CFX_DIBitmap() {
+ if (!m_bExtBuf)
+ FX_Free(m_pBuffer);
+
+ m_pBuffer = nullptr;
+}
+
+uint8_t* CFX_DIBitmap::GetBuffer() const {
+ return m_pBuffer;
+}
+
+const uint8_t* CFX_DIBitmap::GetScanline(int line) const {
+ return m_pBuffer ? m_pBuffer + line * m_Pitch : nullptr;
+}
+
+void CFX_DIBitmap::TakeOver(CFX_DIBitmap* pSrcBitmap) {
+ if (!m_bExtBuf)
+ FX_Free(m_pBuffer);
+
+ FX_Free(m_pPalette);
+ delete m_pAlphaMask;
+ m_pBuffer = pSrcBitmap->m_pBuffer;
+ m_pPalette = pSrcBitmap->m_pPalette;
+ m_pAlphaMask = pSrcBitmap->m_pAlphaMask;
+ pSrcBitmap->m_pBuffer = nullptr;
+ pSrcBitmap->m_pPalette = nullptr;
+ pSrcBitmap->m_pAlphaMask = nullptr;
+ m_bpp = pSrcBitmap->m_bpp;
+ m_bExtBuf = pSrcBitmap->m_bExtBuf;
+ m_AlphaFlag = pSrcBitmap->m_AlphaFlag;
+ m_Width = pSrcBitmap->m_Width;
+ m_Height = pSrcBitmap->m_Height;
+ m_Pitch = pSrcBitmap->m_Pitch;
+}
+
+CFX_DIBitmap* CFX_DIBSource::Clone(const FX_RECT* pClip) const {
+ FX_RECT rect(0, 0, m_Width, m_Height);
+ if (pClip) {
+ rect.Intersect(*pClip);
+ if (rect.IsEmpty()) {
+ return NULL;
+ }
+ }
+ CFX_DIBitmap* pNewBitmap = new CFX_DIBitmap;
+ if (!pNewBitmap->Create(rect.Width(), rect.Height(), GetFormat())) {
+ delete pNewBitmap;
+ return NULL;
+ }
+ pNewBitmap->CopyPalette(m_pPalette);
+ pNewBitmap->CopyAlphaMask(m_pAlphaMask, pClip);
+ if (GetBPP() == 1 && rect.left % 8 != 0) {
+ int left_shift = rect.left % 32;
+ int right_shift = 32 - left_shift;
+ int dword_count = pNewBitmap->m_Pitch / 4;
+ for (int row = rect.top; row < rect.bottom; row++) {
+ FX_DWORD* src_scan = (FX_DWORD*)GetScanline(row) + rect.left / 32;
+ FX_DWORD* dest_scan = (FX_DWORD*)pNewBitmap->GetScanline(row - rect.top);
+ for (int i = 0; i < dword_count; i++) {
+ dest_scan[i] =
+ (src_scan[i] << left_shift) | (src_scan[i + 1] >> right_shift);
+ }
+ }
+ } else {
+ int copy_len = (pNewBitmap->GetWidth() * pNewBitmap->GetBPP() + 7) / 8;
+ if (m_Pitch < (FX_DWORD)copy_len) {
+ copy_len = m_Pitch;
+ }
+ for (int row = rect.top; row < rect.bottom; row++) {
+ const uint8_t* src_scan = GetScanline(row) + rect.left * m_bpp / 8;
+ uint8_t* dest_scan = (uint8_t*)pNewBitmap->GetScanline(row - rect.top);
+ FXSYS_memcpy(dest_scan, src_scan, copy_len);
+ }
+ }
+ return pNewBitmap;
+}
+void CFX_DIBSource::BuildPalette() {
+ if (m_pPalette) {
+ return;
+ }
+ if (GetBPP() == 1) {
+ m_pPalette = FX_Alloc(FX_DWORD, 2);
+ if (IsCmykImage()) {
+ m_pPalette[0] = 0xff;
+ m_pPalette[1] = 0;
+ } else {
+ m_pPalette[0] = 0xff000000;
+ m_pPalette[1] = 0xffffffff;
+ }
+ } else if (GetBPP() == 8) {
+ m_pPalette = FX_Alloc(FX_DWORD, 256);
+ if (IsCmykImage()) {
+ for (int i = 0; i < 256; i++) {
+ m_pPalette[i] = 0xff - i;
+ }
+ } else {
+ for (int i = 0; i < 256; i++) {
+ m_pPalette[i] = 0xff000000 | (i * 0x10101);
+ }
+ }
+ }
+}
+FX_BOOL CFX_DIBSource::BuildAlphaMask() {
+ if (m_pAlphaMask) {
+ return TRUE;
+ }
+ m_pAlphaMask = new CFX_DIBitmap;
+ if (!m_pAlphaMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {
+ delete m_pAlphaMask;
+ m_pAlphaMask = NULL;
+ return FALSE;
+ }
+ FXSYS_memset(m_pAlphaMask->GetBuffer(), 0xff,
+ m_pAlphaMask->GetHeight() * m_pAlphaMask->GetPitch());
+ return TRUE;
+}
+FX_DWORD CFX_DIBSource::GetPaletteEntry(int index) const {
+ ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask());
+ if (m_pPalette) {
+ return m_pPalette[index];
+ }
+ if (IsCmykImage()) {
+ if (GetBPP() == 1) {
+ return index ? 0 : 0xff;
+ }
+ return 0xff - index;
+ }
+ if (GetBPP() == 1) {
+ return index ? 0xffffffff : 0xff000000;
+ }
+ return index * 0x10101 | 0xff000000;
+}
+void CFX_DIBSource::SetPaletteEntry(int index, FX_DWORD color) {
+ ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask());
+ if (!m_pPalette) {
+ BuildPalette();
+ }
+ m_pPalette[index] = color;
+}
+int CFX_DIBSource::FindPalette(FX_DWORD color) const {
+ ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask());
+ if (!m_pPalette) {
+ if (IsCmykImage()) {
+ if (GetBPP() == 1) {
+ return ((uint8_t)color == 0xff) ? 0 : 1;
+ }
+ return 0xff - (uint8_t)color;
+ }
+ if (GetBPP() == 1) {
+ return ((uint8_t)color == 0xff) ? 1 : 0;
+ }
+ return (uint8_t)color;
+ }
+ int palsize = (1 << GetBPP());
+ for (int i = 0; i < palsize; i++)
+ if (m_pPalette[i] == color) {
+ return i;
+ }
+ return -1;
+}
+void CFX_DIBitmap::Clear(FX_DWORD color) {
+ if (!m_pBuffer) {
+ return;
+ }
+ switch (GetFormat()) {
+ case FXDIB_1bppMask:
+ FXSYS_memset(m_pBuffer, (color & 0xff000000) ? 0xff : 0,
+ m_Pitch * m_Height);
+ break;
+ case FXDIB_1bppRgb: {
+ int index = FindPalette(color);
+ FXSYS_memset(m_pBuffer, index ? 0xff : 0, m_Pitch * m_Height);
+ break;
+ }
+ case FXDIB_8bppMask:
+ FXSYS_memset(m_pBuffer, color >> 24, m_Pitch * m_Height);
+ break;
+ case FXDIB_8bppRgb: {
+ int index = FindPalette(color);
+ FXSYS_memset(m_pBuffer, index, m_Pitch * m_Height);
+ break;
+ }
+ case FXDIB_Rgb:
+ case FXDIB_Rgba: {
+ int a, r, g, b;
+ ArgbDecode(color, a, r, g, b);
+ if (r == g && g == b) {
+ FXSYS_memset(m_pBuffer, r, m_Pitch * m_Height);
+ } else {
+ int byte_pos = 0;
+ for (int col = 0; col < m_Width; col++) {
+ m_pBuffer[byte_pos++] = b;
+ m_pBuffer[byte_pos++] = g;
+ m_pBuffer[byte_pos++] = r;
+ }
+ for (int row = 1; row < m_Height; row++) {
+ FXSYS_memcpy(m_pBuffer + row * m_Pitch, m_pBuffer, m_Pitch);
+ }
+ }
+ break;
+ }
+ case FXDIB_Rgb32:
+ case FXDIB_Argb: {
+ color = IsCmykImage() ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
+ for (int i = 0; i < m_Width; i++) {
+ ((FX_DWORD*)m_pBuffer)[i] = color;
+ }
+ for (int row = 1; row < m_Height; row++) {
+ FXSYS_memcpy(m_pBuffer + row * m_Pitch, m_pBuffer, m_Pitch);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+void CFX_DIBSource::GetOverlapRect(int& dest_left,
+ int& dest_top,
+ int& width,
+ int& height,
+ int src_width,
+ int src_height,
+ int& src_left,
+ int& src_top,
+ const CFX_ClipRgn* pClipRgn) {
+ if (width == 0 || height == 0) {
+ return;
+ }
+ ASSERT(width > 0 && height > 0);
+ if (dest_left > m_Width || dest_top > m_Height) {
+ width = 0;
+ height = 0;
+ return;
+ }
+ int x_offset = dest_left - src_left;
+ int y_offset = dest_top - src_top;
+ FX_RECT src_rect(src_left, src_top, src_left + width, src_top + height);
+ FX_RECT src_bound(0, 0, src_width, src_height);
+ src_rect.Intersect(src_bound);
+ FX_RECT dest_rect(src_rect.left + x_offset, src_rect.top + y_offset,
+ src_rect.right + x_offset, src_rect.bottom + y_offset);
+ FX_RECT dest_bound(0, 0, m_Width, m_Height);
+ dest_rect.Intersect(dest_bound);
+ if (pClipRgn) {
+ dest_rect.Intersect(pClipRgn->GetBox());
+ }
+ dest_left = dest_rect.left;
+ dest_top = dest_rect.top;
+ src_left = dest_left - x_offset;
+ src_top = dest_top - y_offset;
+ width = dest_rect.right - dest_rect.left;
+ height = dest_rect.bottom - dest_rect.top;
+}
+FX_BOOL CFX_DIBitmap::TransferBitmap(int dest_left,
+ int dest_top,
+ int width,
+ int height,
+ const CFX_DIBSource* pSrcBitmap,
+ int src_left,
+ int src_top,
+ void* pIccTransform) {
+ if (!m_pBuffer) {
+ return FALSE;
+ }
+ GetOverlapRect(dest_left, dest_top, width, height, pSrcBitmap->GetWidth(),
+ pSrcBitmap->GetHeight(), src_left, src_top, NULL);
+ if (width == 0 || height == 0) {
+ return TRUE;
+ }
+ FXDIB_Format dest_format = GetFormat();
+ FXDIB_Format src_format = pSrcBitmap->GetFormat();
+ if (dest_format == src_format && !pIccTransform) {
+ if (GetBPP() == 1) {
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan = m_pBuffer + (dest_top + row) * m_Pitch;
+ const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
+ for (int col = 0; col < width; col++) {
+ if (src_scan[(src_left + col) / 8] &
+ (1 << (7 - (src_left + col) % 8))) {
+ dest_scan[(dest_left + col) / 8] |= 1
+ << (7 - (dest_left + col) % 8);
+ } else {
+ dest_scan[(dest_left + col) / 8] &=
+ ~(1 << (7 - (dest_left + col) % 8));
+ }
+ }
+ }
+ } else {
+ int Bpp = GetBPP() / 8;
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_scan =
+ m_pBuffer + (dest_top + row) * m_Pitch + dest_left * Bpp;
+ const uint8_t* src_scan =
+ pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp;
+ FXSYS_memcpy(dest_scan, src_scan, width * Bpp);
+ }
+ }
+ } else {
+ if (m_pPalette) {
+ return FALSE;
+ }
+ if (m_bpp == 8) {
+ dest_format = FXDIB_8bppMask;
+ }
+ uint8_t* dest_buf =
+ m_pBuffer + dest_top * m_Pitch + dest_left * GetBPP() / 8;
+ FX_DWORD* d_plt = NULL;
+ if (!ConvertBuffer(dest_format, dest_buf, m_Pitch, width, height,
+ pSrcBitmap, src_left, src_top, d_plt, pIccTransform)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+FX_BOOL CFX_DIBitmap::TransferMask(int dest_left,
+ int dest_top,
+ int width,
+ int height,
+ const CFX_DIBSource* pMask,
+ FX_DWORD color,
+ int src_left,
+ int src_top,
+ int alpha_flag,
+ void* pIccTransform) {
+ if (!m_pBuffer) {
+ return FALSE;
+ }
+ ASSERT(HasAlpha() && (m_bpp >= 24));
+ ASSERT(pMask->IsAlphaMask());
+ if (!HasAlpha() || !pMask->IsAlphaMask() || m_bpp < 24) {
+ return FALSE;
+ }
+ GetOverlapRect(dest_left, dest_top, width, height, pMask->GetWidth(),
+ pMask->GetHeight(), src_left, src_top, NULL);
+ if (width == 0 || height == 0) {
+ return TRUE;
+ }
+ int src_bpp = pMask->GetBPP();
+ int alpha;
+ FX_DWORD dst_color;
+ if (alpha_flag >> 8) {
+ alpha = alpha_flag & 0xff;
+ dst_color = FXCMYK_TODIB(color);
+ } else {
+ alpha = FXARGB_A(color);
+ dst_color = FXARGB_TODIB(color);
+ }
+ uint8_t* color_p = (uint8_t*)&dst_color;
+ if (pIccTransform && CFX_GEModule::Get()->GetCodecModule() &&
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) {
+ ICodec_IccModule* pIccModule =
+ CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
+ pIccModule->TranslateScanline(pIccTransform, color_p, color_p, 1);
+ } else {
+ if (alpha_flag >> 8 && !IsCmykImage()) {
+ AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color),
+ FXSYS_GetYValue(color), FXSYS_GetKValue(color),
+ color_p[2], color_p[1], color_p[0]);
+ } else if (!(alpha_flag >> 8) && IsCmykImage()) {
+ return FALSE;
+ }
+ }
+ if (!IsCmykImage()) {
+ color_p[3] = (uint8_t)alpha;
+ }
+ if (GetFormat() == FXDIB_Argb) {
+ for (int row = 0; row < height; row++) {
+ FX_DWORD* dest_pos =
+ (FX_DWORD*)(m_pBuffer + (dest_top + row) * m_Pitch + dest_left * 4);
+ const uint8_t* src_scan = pMask->GetScanline(src_top + row);
+ if (src_bpp == 1) {
+ for (int col = 0; col < width; col++) {
+ int src_bitpos = src_left + col;
+ if (src_scan[src_bitpos / 8] & (1 << (7 - src_bitpos % 8))) {
+ *dest_pos = dst_color;
+ } else {
+ *dest_pos = 0;
+ }
+ dest_pos++;
+ }
+ } else {
+ src_scan += src_left;
+ dst_color = FXARGB_TODIB(dst_color);
+ dst_color &= 0xffffff;
+ for (int col = 0; col < width; col++) {
+ FXARGB_SETDIB(dest_pos++,
+ dst_color | ((alpha * (*src_scan++) / 255) << 24));
+ }
+ }
+ }
+ } else {
+ int comps = m_bpp / 8;
+ for (int row = 0; row < height; row++) {
+ uint8_t* dest_color_pos =
+ m_pBuffer + (dest_top + row) * m_Pitch + dest_left * comps;
+ uint8_t* dest_alpha_pos =
+ (uint8_t*)m_pAlphaMask->GetScanline(dest_top + row) + dest_left;
+ const uint8_t* src_scan = pMask->GetScanline(src_top + row);
+ if (src_bpp == 1) {
+ for (int col = 0; col < width; col++) {
+ int src_bitpos = src_left + col;
+ if (src_scan[src_bitpos / 8] & (1 << (7 - src_bitpos % 8))) {
+ FXSYS_memcpy(dest_color_pos, color_p, comps);
+ *dest_alpha_pos = 0xff;
+ } else {
+ FXSYS_memset(dest_color_pos, 0, comps);
+ *dest_alpha_pos = 0;
+ }
+ dest_color_pos += comps;
+ dest_alpha_pos++;
+ }
+ } else {
+ src_scan += src_left;
+ for (int col = 0; col < width; col++) {
+ FXSYS_memcpy(dest_color_pos, color_p, comps);
+ dest_color_pos += comps;
+ *dest_alpha_pos++ = (alpha * (*src_scan++) / 255);
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+void CFX_DIBSource::CopyPalette(const FX_DWORD* pSrc, FX_DWORD size) {
+ if (!pSrc || GetBPP() > 8) {
+ FX_Free(m_pPalette);
+ m_pPalette = NULL;
+ } else {
+ FX_DWORD pal_size = 1 << GetBPP();
+ if (!m_pPalette) {
+ m_pPalette = FX_Alloc(FX_DWORD, pal_size);
+ }
+ if (pal_size > size) {
+ pal_size = size;
+ }
+ FXSYS_memcpy(m_pPalette, pSrc, pal_size * sizeof(FX_DWORD));
+ }
+}
+void CFX_DIBSource::GetPalette(FX_DWORD* pal, int alpha) const {
+ ASSERT(GetBPP() <= 8 && !IsCmykImage());
+ if (GetBPP() == 1) {
+ pal[0] =
+ ((m_pPalette ? m_pPalette[0] : 0xff000000) & 0xffffff) | (alpha << 24);
+ pal[1] =
+ ((m_pPalette ? m_pPalette[1] : 0xffffffff) & 0xffffff) | (alpha << 24);
+ return;
+ }
+ if (m_pPalette) {
+ for (int i = 0; i < 256; i++) {
+ pal[i] = (m_pPalette[i] & 0x00ffffff) | (alpha << 24);
+ }
+ } else {
+ for (int i = 0; i < 256; i++) {
+ pal[i] = (i * 0x10101) | (alpha << 24);
+ }
+ }
+}
+CFX_DIBitmap* CFX_DIBSource::GetAlphaMask(const FX_RECT* pClip) const {
+ ASSERT(GetFormat() == FXDIB_Argb);
+ FX_RECT rect(0, 0, m_Width, m_Height);
+ if (pClip) {
+ rect.Intersect(*pClip);
+ if (rect.IsEmpty()) {
+ return NULL;
+ }
+ }
+ CFX_DIBitmap* pMask = new CFX_DIBitmap;
+ if (!pMask->Create(rect.Width(), rect.Height(), FXDIB_8bppMask)) {
+ delete pMask;
+ return NULL;
+ }
+ for (int row = rect.top; row < rect.bottom; row++) {
+ const uint8_t* src_scan = GetScanline(row) + rect.left * 4 + 3;
+ uint8_t* dest_scan = (uint8_t*)pMask->GetScanline(row - rect.top);
+ for (int col = rect.left; col < rect.right; col++) {
+ *dest_scan++ = *src_scan;
+ src_scan += 4;
+ }
+ }
+ return pMask;
+}
+FX_BOOL CFX_DIBSource::CopyAlphaMask(const CFX_DIBSource* pAlphaMask,
+ const FX_RECT* pClip) {
+ if (!HasAlpha() || GetFormat() == FXDIB_Argb) {
+ return FALSE;
+ }
+ if (pAlphaMask) {
+ FX_RECT rect(0, 0, pAlphaMask->m_Width, pAlphaMask->m_Height);
+ if (pClip) {
+ rect.Intersect(*pClip);
+ if (rect.IsEmpty() || rect.Width() != m_Width ||
+ rect.Height() != m_Height) {
+ return FALSE;
+ }
+ } else {
+ if (pAlphaMask->m_Width != m_Width || pAlphaMask->m_Height != m_Height) {
+ return FALSE;
+ }
+ }
+ for (int row = 0; row < m_Height; row++)
+ FXSYS_memcpy((void*)m_pAlphaMask->GetScanline(row),
+ pAlphaMask->GetScanline(row + rect.top) + rect.left,
+ m_pAlphaMask->m_Pitch);
+ } else {
+ m_pAlphaMask->Clear(0xff000000);
+ }
+ return TRUE;
+}
+const int g_ChannelOffset[] = {0, 2, 1, 0, 0, 1, 2, 3, 3};
+FX_BOOL CFX_DIBitmap::LoadChannel(FXDIB_Channel destChannel,
+ const CFX_DIBSource* pSrcBitmap,
+ FXDIB_Channel srcChannel) {
+ if (!m_pBuffer) {
+ return FALSE;
+ }
+ CFX_DIBSource* pSrcClone = (CFX_DIBSource*)pSrcBitmap;
+ CFX_DIBitmap* pDst = this;
+ int destOffset, srcOffset;
+ if (srcChannel == FXDIB_Alpha) {
+ if (!pSrcBitmap->HasAlpha() && !pSrcBitmap->IsAlphaMask()) {
+ return FALSE;
+ }
+ if (pSrcBitmap->GetBPP() == 1) {
+ pSrcClone = pSrcBitmap->CloneConvert(FXDIB_8bppMask);
+ if (!pSrcClone) {
+ return FALSE;
+ }
+ }
+ if (pSrcBitmap->GetFormat() == FXDIB_Argb) {
+ srcOffset = 3;
+ } else {
+ srcOffset = 0;
+ }
+ } else {
+ if (pSrcBitmap->IsAlphaMask()) {
+ return FALSE;
+ }
+ if (pSrcBitmap->GetBPP() < 24) {
+ if (pSrcBitmap->IsCmykImage()) {
+ pSrcClone = pSrcBitmap->CloneConvert(
+ (FXDIB_Format)((pSrcBitmap->GetFormat() & 0xff00) | 0x20));
+ } else {
+ pSrcClone = pSrcBitmap->CloneConvert(
+ (FXDIB_Format)((pSrcBitmap->GetFormat() & 0xff00) | 0x18));
+ }
+ if (!pSrcClone) {
+ return FALSE;
+ }
+ }
+ srcOffset = g_ChannelOffset[srcChannel];
+ }
+ if (destChannel == FXDIB_Alpha) {
+ if (IsAlphaMask()) {
+ if (!ConvertFormat(FXDIB_8bppMask)) {
+ if (pSrcClone != pSrcBitmap) {
+ delete pSrcClone;
+ }
+ return FALSE;
+ }
+ destOffset = 0;
+ } else {
+ destOffset = 0;
+ if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) {
+ if (pSrcClone != pSrcBitmap) {
+ delete pSrcClone;
+ }
+ return FALSE;
+ }
+ if (GetFormat() == FXDIB_Argb) {
+ destOffset = 3;
+ }
+ }
+ } else {
+ if (IsAlphaMask()) {
+ if (pSrcClone != pSrcBitmap) {
+ delete pSrcClone;
+ }
+ return FALSE;
+ }
+ if (GetBPP() < 24) {
+ if (HasAlpha()) {
+ if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) {
+ if (pSrcClone != pSrcBitmap) {
+ delete pSrcClone;
+ }
+ return FALSE;
+ }
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+ } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb32)) {
+#else
+ } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb)) {
+#endif
+ if (pSrcClone != pSrcBitmap) {
+ delete pSrcClone;
+ }
+ return FALSE;
+ }
+ }
+ destOffset = g_ChannelOffset[destChannel];
+ }
+ if (srcChannel == FXDIB_Alpha && pSrcClone->m_pAlphaMask) {
+ CFX_DIBitmap* pAlphaMask = pSrcClone->m_pAlphaMask;
+ if (pSrcClone->GetWidth() != m_Width ||
+ pSrcClone->GetHeight() != m_Height) {
+ if (pAlphaMask) {
+ pAlphaMask = pAlphaMask->StretchTo(m_Width, m_Height);
+ if (!pAlphaMask) {
+ if (pSrcClone != pSrcBitmap) {
+ delete pSrcClone;
+ }
+ return FALSE;
+ }
+ }
+ }
+ if (pSrcClone != pSrcBitmap) {
+ pSrcClone->m_pAlphaMask = NULL;
+ delete pSrcClone;
+ }
+ pSrcClone = pAlphaMask;
+ srcOffset = 0;
+ } else if (pSrcClone->GetWidth() != m_Width ||
+ pSrcClone->GetHeight() != m_Height) {
+ CFX_DIBitmap* pSrcMatched = pSrcClone->StretchTo(m_Width, m_Height);
+ if (pSrcClone != pSrcBitmap) {
+ delete pSrcClone;
+ }
+ if (!pSrcMatched) {
+ return FALSE;
+ }
+ pSrcClone = pSrcMatched;
+ }
+ if (destChannel == FXDIB_Alpha && m_pAlphaMask) {
+ pDst = m_pAlphaMask;
+ destOffset = 0;
+ }
+ int srcBytes = pSrcClone->GetBPP() / 8;
+ int destBytes = pDst->GetBPP() / 8;
+ for (int row = 0; row < m_Height; row++) {
+ uint8_t* dest_pos = (uint8_t*)pDst->GetScanline(row) + destOffset;
+ const uint8_t* src_pos = pSrcClone->GetScanline(row) + srcOffset;
+ for (int col = 0; col < m_Width; col++) {
+ *dest_pos = *src_pos;
+ dest_pos += destBytes;
+ src_pos += srcBytes;
+ }
+ }
+ if (pSrcClone != pSrcBitmap && pSrcClone != pSrcBitmap->m_pAlphaMask) {
+ delete pSrcClone;
+ }
+ return TRUE;
+}
+FX_BOOL CFX_DIBitmap::LoadChannel(FXDIB_Channel destChannel, int value) {
+ if (!m_pBuffer) {
+ return FALSE;
+ }
+ int destOffset;
+ if (destChannel == FXDIB_Alpha) {
+ if (IsAlphaMask()) {
+ if (!ConvertFormat(FXDIB_8bppMask)) {
+ return FALSE;
+ }
+ destOffset = 0;
+ } else {
+ destOffset = 0;
+ if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) {
+ return FALSE;
+ }
+ if (GetFormat() == FXDIB_Argb) {
+ destOffset = 3;
+ }
+ }
+ } else {
+ if (IsAlphaMask()) {
+ return FALSE;
+ }
+ if (GetBPP() < 24) {
+ if (HasAlpha()) {
+ if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) {
+ return FALSE;
+ }
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+ } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb)) {
+#else
+ } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb32)) {
+#endif
+ return FALSE;
+ }
+ }
+ destOffset = g_ChannelOffset[destChannel];
+ }
+ int Bpp = GetBPP() / 8;
+ if (Bpp == 1) {
+ FXSYS_memset(m_pBuffer, value, m_Height * m_Pitch);
+ return TRUE;
+ }
+ if (destChannel == FXDIB_Alpha && m_pAlphaMask) {
+ FXSYS_memset(m_pAlphaMask->GetBuffer(), value,
+ m_pAlphaMask->GetHeight() * m_pAlphaMask->GetPitch());
+ return TRUE;
+ }
+ for (int row = 0; row < m_Height; row++) {
+ uint8_t* scan_line = m_pBuffer + row * m_Pitch + destOffset;
+ for (int col = 0; col < m_Width; col++) {
+ *scan_line = value;
+ scan_line += Bpp;
+ }
+ }
+ return TRUE;
+}
+FX_BOOL CFX_DIBitmap::MultiplyAlpha(const CFX_DIBSource* pSrcBitmap) {
+ if (!m_pBuffer) {
+ return FALSE;
+ }
+ ASSERT(pSrcBitmap->IsAlphaMask());
+ if (!pSrcBitmap->IsAlphaMask()) {
+ return FALSE;
+ }
+ if (!IsAlphaMask() && !HasAlpha()) {
+ return LoadChannel(FXDIB_Alpha, pSrcBitmap, FXDIB_Alpha);
+ }
+ CFX_DIBitmap* pSrcClone = (CFX_DIBitmap*)pSrcBitmap;
+ if (pSrcBitmap->GetWidth() != m_Width ||
+ pSrcBitmap->GetHeight() != m_Height) {
+ pSrcClone = pSrcBitmap->StretchTo(m_Width, m_Height);
+ if (!pSrcClone) {
+ return FALSE;
+ }
+ }
+ if (IsAlphaMask()) {
+ if (!ConvertFormat(FXDIB_8bppMask)) {
+ if (pSrcClone != pSrcBitmap) {
+ delete pSrcClone;
+ }
+ return FALSE;
+ }
+ for (int row = 0; row < m_Height; row++) {
+ uint8_t* dest_scan = m_pBuffer + m_Pitch * row;
+ uint8_t* src_scan = pSrcClone->m_pBuffer + pSrcClone->m_Pitch * row;
+ if (pSrcClone->GetBPP() == 1) {
+ for (int col = 0; col < m_Width; col++) {
+ if (!((1 << (7 - col % 8)) & src_scan[col / 8])) {
+ dest_scan[col] = 0;
+ }
+ }
+ } else {
+ for (int col = 0; col < m_Width; col++) {
+ *dest_scan = (*dest_scan) * src_scan[col] / 255;
+ dest_scan++;
+ }
+ }
+ }
+ } else {
+ if (GetFormat() == FXDIB_Argb) {
+ if (pSrcClone->GetBPP() == 1) {
+ if (pSrcClone != pSrcBitmap) {
+ delete pSrcClone;
+ }
+ return FALSE;
+ }
+ for (int row = 0; row < m_Height; row++) {
+ uint8_t* dest_scan = m_pBuffer + m_Pitch * row + 3;
+ uint8_t* src_scan = pSrcClone->m_pBuffer + pSrcClone->m_Pitch * row;
+ for (int col = 0; col < m_Width; col++) {
+ *dest_scan = (*dest_scan) * src_scan[col] / 255;
+ dest_scan += 4;
+ }
+ }
+ } else {
+ m_pAlphaMask->MultiplyAlpha(pSrcClone);
+ }
+ }
+ if (pSrcClone != pSrcBitmap) {
+ delete pSrcClone;
+ }
+ return TRUE;
+}
+FX_BOOL CFX_DIBitmap::GetGrayData(void* pIccTransform) {
+ if (!m_pBuffer) {
+ return FALSE;
+ }
+ switch (GetFormat()) {
+ case FXDIB_1bppRgb: {
+ if (!m_pPalette) {
+ return FALSE;
+ }
+ uint8_t gray[2];
+ for (int i = 0; i < 2; i++) {
+ int r = (uint8_t)(m_pPalette[i] >> 16);
+ int g = (uint8_t)(m_pPalette[i] >> 8);
+ int b = (uint8_t)m_pPalette[i];
+ gray[i] = (uint8_t)FXRGB2GRAY(r, g, b);
+ }
+ CFX_DIBitmap* pMask = new CFX_DIBitmap;
+ if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {
+ delete pMask;
+ return FALSE;
+ }
+ FXSYS_memset(pMask->GetBuffer(), gray[0], pMask->GetPitch() * m_Height);
+ for (int row = 0; row < m_Height; row++) {
+ uint8_t* src_pos = m_pBuffer + row * m_Pitch;
+ uint8_t* dest_pos = (uint8_t*)pMask->GetScanline(row);
+ for (int col = 0; col < m_Width; col++) {
+ if (src_pos[col / 8] & (1 << (7 - col % 8))) {
+ *dest_pos = gray[1];
+ }
+ dest_pos++;
+ }
+ }
+ TakeOver(pMask);
+ delete pMask;
+ break;
+ }
+ case FXDIB_8bppRgb: {
+ if (!m_pPalette) {
+ return FALSE;
+ }
+ uint8_t gray[256];
+ for (int i = 0; i < 256; i++) {
+ int r = (uint8_t)(m_pPalette[i] >> 16);
+ int g = (uint8_t)(m_pPalette[i] >> 8);
+ int b = (uint8_t)m_pPalette[i];
+ gray[i] = (uint8_t)FXRGB2GRAY(r, g, b);
+ }
+ CFX_DIBitmap* pMask = new CFX_DIBitmap;
+ if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {
+ delete pMask;
+ return FALSE;
+ }
+ for (int row = 0; row < m_Height; row++) {
+ uint8_t* dest_pos = pMask->GetBuffer() + row * pMask->GetPitch();
+ uint8_t* src_pos = m_pBuffer + row * m_Pitch;
+ for (int col = 0; col < m_Width; col++) {
+ *dest_pos++ = gray[*src_pos++];
+ }
+ }
+ TakeOver(pMask);
+ delete pMask;
+ break;
+ }
+ case FXDIB_Rgb: {
+ CFX_DIBitmap* pMask = new CFX_DIBitmap;
+ if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {
+ delete pMask;
+ return FALSE;
+ }
+ for (int row = 0; row < m_Height; row++) {
+ uint8_t* src_pos = m_pBuffer + row * m_Pitch;
+ uint8_t* dest_pos = pMask->GetBuffer() + row * pMask->GetPitch();
+ for (int col = 0; col < m_Width; col++) {
+ *dest_pos++ = FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos);
+ src_pos += 3;
+ }
+ }
+ TakeOver(pMask);
+ delete pMask;
+ break;
+ }
+ case FXDIB_Rgb32: {
+ CFX_DIBitmap* pMask = new CFX_DIBitmap;
+ if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {
+ delete pMask;
+ return FALSE;
+ }
+ for (int row = 0; row < m_Height; row++) {
+ uint8_t* src_pos = m_pBuffer + row * m_Pitch;
+ uint8_t* dest_pos = pMask->GetBuffer() + row * pMask->GetPitch();
+ for (int col = 0; col < m_Width; col++) {
+ *dest_pos++ = FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos);
+ src_pos += 4;
+ }
+ }
+ TakeOver(pMask);
+ delete pMask;
+ break;
+ }
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+FX_BOOL CFX_DIBitmap::MultiplyAlpha(int alpha) {
+ if (!m_pBuffer) {
+ return FALSE;
+ }
+ switch (GetFormat()) {
+ case FXDIB_1bppMask:
+ if (!ConvertFormat(FXDIB_8bppMask)) {
+ return FALSE;
+ }
+ MultiplyAlpha(alpha);
+ break;
+ case FXDIB_8bppMask: {
+ for (int row = 0; row < m_Height; row++) {
+ uint8_t* scan_line = m_pBuffer + row * m_Pitch;
+ for (int col = 0; col < m_Width; col++) {
+ scan_line[col] = scan_line[col] * alpha / 255;
+ }
+ }
+ break;
+ }
+ case FXDIB_Argb: {
+ for (int row = 0; row < m_Height; row++) {
+ uint8_t* scan_line = m_pBuffer + row * m_Pitch + 3;
+ for (int col = 0; col < m_Width; col++) {
+ *scan_line = (*scan_line) * alpha / 255;
+ scan_line += 4;
+ }
+ }
+ break;
+ }
+ default:
+ if (HasAlpha()) {
+ m_pAlphaMask->MultiplyAlpha(alpha);
+ } else if (IsCmykImage()) {
+ if (!ConvertFormat((FXDIB_Format)(GetFormat() | 0x0200))) {
+ return FALSE;
+ }
+ m_pAlphaMask->MultiplyAlpha(alpha);
+ } else {
+ if (!ConvertFormat(FXDIB_Argb)) {
+ return FALSE;
+ }
+ MultiplyAlpha(alpha);
+ }
+ break;
+ }
+ return TRUE;
+}
+FX_DWORD CFX_DIBitmap::GetPixel(int x, int y) const {
+ if (!m_pBuffer) {
+ return 0;
+ }
+ uint8_t* pos = m_pBuffer + y * m_Pitch + x * GetBPP() / 8;
+ switch (GetFormat()) {
+ case FXDIB_1bppMask: {
+ if ((*pos) & (1 << (7 - x % 8))) {
+ return 0xff000000;
+ }
+ return 0;
+ }
+ case FXDIB_1bppRgb: {
+ if ((*pos) & (1 << (7 - x % 8))) {
+ return m_pPalette ? m_pPalette[1] : 0xffffffff;
+ }
+ return m_pPalette ? m_pPalette[0] : 0xff000000;
+ }
+ case FXDIB_8bppMask:
+ return (*pos) << 24;
+ case FXDIB_8bppRgb:
+ return m_pPalette ? m_pPalette[*pos] : (0xff000000 | ((*pos) * 0x10101));
+ case FXDIB_Rgb:
+ case FXDIB_Rgba:
+ case FXDIB_Rgb32:
+ return FXARGB_GETDIB(pos) | 0xff000000;
+ case FXDIB_Argb:
+ return FXARGB_GETDIB(pos);
+ default:
+ break;
+ }
+ return 0;
+}
+void CFX_DIBitmap::SetPixel(int x, int y, FX_DWORD color) {
+ if (!m_pBuffer) {
+ return;
+ }
+ if (x < 0 || x >= m_Width || y < 0 || y >= m_Height) {
+ return;
+ }
+ uint8_t* pos = m_pBuffer + y * m_Pitch + x * GetBPP() / 8;
+ switch (GetFormat()) {
+ case FXDIB_1bppMask:
+ if (color >> 24) {
+ *pos |= 1 << (7 - x % 8);
+ } else {
+ *pos &= ~(1 << (7 - x % 8));
+ }
+ break;
+ case FXDIB_1bppRgb:
+ if (m_pPalette) {
+ if (color == m_pPalette[1]) {
+ *pos |= 1 << (7 - x % 8);
+ } else {
+ *pos &= ~(1 << (7 - x % 8));
+ }
+ } else {
+ if (color == 0xffffffff) {
+ *pos |= 1 << (7 - x % 8);
+ } else {
+ *pos &= ~(1 << (7 - x % 8));
+ }
+ }
+ break;
+ case FXDIB_8bppMask:
+ *pos = (uint8_t)(color >> 24);
+ break;
+ case FXDIB_8bppRgb: {
+ if (m_pPalette) {
+ for (int i = 0; i < 256; i++) {
+ if (m_pPalette[i] == color) {
+ *pos = (uint8_t)i;
+ return;
+ }
+ }
+ *pos = 0;
+ } else {
+ *pos = FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color));
+ }
+ break;
+ }
+ case FXDIB_Rgb:
+ case FXDIB_Rgb32: {
+ int alpha = FXARGB_A(color);
+ pos[0] = (FXARGB_B(color) * alpha + pos[0] * (255 - alpha)) / 255;
+ pos[1] = (FXARGB_G(color) * alpha + pos[1] * (255 - alpha)) / 255;
+ pos[2] = (FXARGB_R(color) * alpha + pos[2] * (255 - alpha)) / 255;
+ break;
+ }
+ case FXDIB_Rgba: {
+ pos[0] = FXARGB_B(color);
+ pos[1] = FXARGB_G(color);
+ pos[2] = FXARGB_R(color);
+ break;
+ }
+ case FXDIB_Argb:
+ FXARGB_SETDIB(pos, color);
+ break;
+ default:
+ break;
+ }
+}
+void CFX_DIBitmap::DownSampleScanline(int line,
+ uint8_t* dest_scan,
+ int dest_bpp,
+ int dest_width,
+ FX_BOOL bFlipX,
+ int clip_left,
+ int clip_width) const {
+ if (!m_pBuffer) {
+ return;
+ }
+ int src_Bpp = m_bpp / 8;
+ uint8_t* scanline = m_pBuffer + line * m_Pitch;
+ if (src_Bpp == 0) {
+ for (int i = 0; i < clip_width; i++) {
+ FX_DWORD dest_x = clip_left + i;
+ FX_DWORD src_x = dest_x * m_Width / dest_width;
+ if (bFlipX) {
+ src_x = m_Width - src_x - 1;
+ }
+ src_x %= m_Width;
+ dest_scan[i] = (scanline[src_x / 8] & (1 << (7 - src_x % 8))) ? 255 : 0;
+ }
+ } else if (src_Bpp == 1) {
+ for (int i = 0; i < clip_width; i++) {
+ FX_DWORD dest_x = clip_left + i;
+ FX_DWORD src_x = dest_x * m_Width / dest_width;
+ if (bFlipX) {
+ src_x = m_Width - src_x - 1;
+ }
+ src_x %= m_Width;
+ int dest_pos = i;
+ if (m_pPalette) {
+ if (!IsCmykImage()) {
+ dest_pos *= 3;
+ FX_ARGB argb = m_pPalette[scanline[src_x]];
+ dest_scan[dest_pos] = FXARGB_B(argb);
+ dest_scan[dest_pos + 1] = FXARGB_G(argb);
+ dest_scan[dest_pos + 2] = FXARGB_R(argb);
+ } else {
+ dest_pos *= 4;
+ FX_CMYK cmyk = m_pPalette[scanline[src_x]];
+ dest_scan[dest_pos] = FXSYS_GetCValue(cmyk);
+ dest_scan[dest_pos + 1] = FXSYS_GetMValue(cmyk);
+ dest_scan[dest_pos + 2] = FXSYS_GetYValue(cmyk);
+ dest_scan[dest_pos + 3] = FXSYS_GetKValue(cmyk);
+ }
+ } else {
+ dest_scan[dest_pos] = scanline[src_x];
+ }
+ }
+ } else {
+ for (int i = 0; i < clip_width; i++) {
+ FX_DWORD dest_x = clip_left + i;
+ FX_DWORD src_x =
+ bFlipX ? (m_Width - dest_x * m_Width / dest_width - 1) * src_Bpp
+ : (dest_x * m_Width / dest_width) * src_Bpp;
+ src_x %= m_Width * src_Bpp;
+ int dest_pos = i * src_Bpp;
+ for (int b = 0; b < src_Bpp; b++) {
+ dest_scan[dest_pos + b] = scanline[src_x + b];
+ }
+ }
+ }
+}
+FX_BOOL CFX_DIBitmap::ConvertColorScale(FX_DWORD forecolor,
+ FX_DWORD backcolor) {
+ ASSERT(!IsAlphaMask());
+ if (!m_pBuffer || IsAlphaMask()) {
+ return FALSE;
+ }
+ int fc, fm, fy, fk, bc, bm, by, bk;
+ int fr, fg, fb, br, bg, bb;
+ FX_BOOL isCmykImage = IsCmykImage();
+ if (isCmykImage) {
+ fc = FXSYS_GetCValue(forecolor);
+ fm = FXSYS_GetMValue(forecolor);
+ fy = FXSYS_GetYValue(forecolor);
+ fk = FXSYS_GetKValue(forecolor);
+ bc = FXSYS_GetCValue(backcolor);
+ bm = FXSYS_GetMValue(backcolor);
+ by = FXSYS_GetYValue(backcolor);
+ bk = FXSYS_GetKValue(backcolor);
+ } else {
+ fr = FXSYS_GetRValue(forecolor);
+ fg = FXSYS_GetGValue(forecolor);
+ fb = FXSYS_GetBValue(forecolor);
+ br = FXSYS_GetRValue(backcolor);
+ bg = FXSYS_GetGValue(backcolor);
+ bb = FXSYS_GetBValue(backcolor);
+ }
+ if (m_bpp <= 8) {
+ if (isCmykImage) {
+ if (forecolor == 0xff && backcolor == 0 && !m_pPalette) {
+ return TRUE;
+ }
+ } else if (forecolor == 0 && backcolor == 0xffffff && !m_pPalette) {
+ return TRUE;
+ }
+ if (!m_pPalette) {
+ BuildPalette();
+ }
+ int size = 1 << m_bpp;
+ if (isCmykImage) {
+ for (int i = 0; i < size; i++) {
+ uint8_t b, g, r;
+ AdobeCMYK_to_sRGB1(FXSYS_GetCValue(m_pPalette[i]),
+ FXSYS_GetMValue(m_pPalette[i]),
+ FXSYS_GetYValue(m_pPalette[i]),
+ FXSYS_GetKValue(m_pPalette[i]), r, g, b);
+ int gray = 255 - FXRGB2GRAY(r, g, b);
+ m_pPalette[i] = CmykEncode(
+ bc + (fc - bc) * gray / 255, bm + (fm - bm) * gray / 255,
+ by + (fy - by) * gray / 255, bk + (fk - bk) * gray / 255);
+ }
+ } else {
+ for (int i = 0; i < size; i++) {
+ int gray = FXRGB2GRAY(FXARGB_R(m_pPalette[i]), FXARGB_G(m_pPalette[i]),
+ FXARGB_B(m_pPalette[i]));
+ m_pPalette[i] = FXARGB_MAKE(0xff, br + (fr - br) * gray / 255,
+ bg + (fg - bg) * gray / 255,
+ bb + (fb - bb) * gray / 255);
+ }
+ }
+ return TRUE;
+ }
+ if (isCmykImage) {
+ if (forecolor == 0xff && backcolor == 0x00) {
+ for (int row = 0; row < m_Height; row++) {
+ uint8_t* scanline = m_pBuffer + row * m_Pitch;
+ for (int col = 0; col < m_Width; col++) {
+ uint8_t b, g, r;
+ AdobeCMYK_to_sRGB1(scanline[0], scanline[1], scanline[2], scanline[3],
+ r, g, b);
+ *scanline++ = 0;
+ *scanline++ = 0;
+ *scanline++ = 0;
+ *scanline++ = 255 - FXRGB2GRAY(r, g, b);
+ }
+ }
+ return TRUE;
+ }
+ } else if (forecolor == 0 && backcolor == 0xffffff) {
+ for (int row = 0; row < m_Height; row++) {
+ uint8_t* scanline = m_pBuffer + row * m_Pitch;
+ int gap = m_bpp / 8 - 2;
+ for (int col = 0; col < m_Width; col++) {
+ int gray = FXRGB2GRAY(scanline[2], scanline[1], scanline[0]);
+ *scanline++ = gray;
+ *scanline++ = gray;
+ *scanline = gray;
+ scanline += gap;
+ }
+ }
+ return TRUE;
+ }
+ if (isCmykImage) {
+ for (int row = 0; row < m_Height; row++) {
+ uint8_t* scanline = m_pBuffer + row * m_Pitch;
+ for (int col = 0; col < m_Width; col++) {
+ uint8_t b, g, r;
+ AdobeCMYK_to_sRGB1(scanline[0], scanline[1], scanline[2], scanline[3],
+ r, g, b);
+ int gray = 255 - FXRGB2GRAY(r, g, b);
+ *scanline++ = bc + (fc - bc) * gray / 255;
+ *scanline++ = bm + (fm - bm) * gray / 255;
+ *scanline++ = by + (fy - by) * gray / 255;
+ *scanline++ = bk + (fk - bk) * gray / 255;
+ }
+ }
+ } else {
+ for (int row = 0; row < m_Height; row++) {
+ uint8_t* scanline = m_pBuffer + row * m_Pitch;
+ int gap = m_bpp / 8 - 2;
+ for (int col = 0; col < m_Width; col++) {
+ int gray = FXRGB2GRAY(scanline[2], scanline[1], scanline[0]);
+ *scanline++ = bb + (fb - bb) * gray / 255;
+ *scanline++ = bg + (fg - bg) * gray / 255;
+ *scanline = br + (fr - br) * gray / 255;
+ scanline += gap;
+ }
+ }
+ }
+ return TRUE;
+}
+FX_BOOL CFX_DIBitmap::DitherFS(const FX_DWORD* pPalette,
+ int pal_size,
+ const FX_RECT* pRect) {
+ if (!m_pBuffer) {
+ return FALSE;
+ }
+ if (m_bpp != 8 && m_pPalette && m_AlphaFlag != 0) {
+ return FALSE;
+ }
+ if (m_Width < 4 && m_Height < 4) {
+ return FALSE;
+ }
+ FX_RECT rect(0, 0, m_Width, m_Height);
+ if (pRect) {
+ rect.Intersect(*pRect);
+ }
+ uint8_t translate[256];
+ for (int i = 0; i < 256; i++) {
+ int err2 = 65536;
+ for (int j = 0; j < pal_size; j++) {
+ uint8_t entry = (uint8_t)pPalette[j];
+ int err = (int)entry - i;
+ if (err * err < err2) {
+ err2 = err * err;
+ translate[i] = entry;
+ }
+ }
+ }
+ for (int row = rect.top; row < rect.bottom; row++) {
+ uint8_t* scan = m_pBuffer + row * m_Pitch;
+ uint8_t* next_scan = m_pBuffer + (row + 1) * m_Pitch;
+ for (int col = rect.left; col < rect.right; col++) {
+ int src_pixel = scan[col];
+ int dest_pixel = translate[src_pixel];
+ scan[col] = (uint8_t)dest_pixel;
+ int error = -dest_pixel + src_pixel;
+ if (col < rect.right - 1) {
+ int src = scan[col + 1];
+ src += error * 7 / 16;
+ if (src > 255) {
+ scan[col + 1] = 255;
+ } else if (src < 0) {
+ scan[col + 1] = 0;
+ } else {
+ scan[col + 1] = src;
+ }
+ }
+ if (col < rect.right - 1 && row < rect.bottom - 1) {
+ int src = next_scan[col + 1];
+ src += error * 1 / 16;
+ if (src > 255) {
+ next_scan[col + 1] = 255;
+ } else if (src < 0) {
+ next_scan[col + 1] = 0;
+ } else {
+ next_scan[col + 1] = src;
+ }
+ }
+ if (row < rect.bottom - 1) {
+ int src = next_scan[col];
+ src += error * 5 / 16;
+ if (src > 255) {
+ next_scan[col] = 255;
+ } else if (src < 0) {
+ next_scan[col] = 0;
+ } else {
+ next_scan[col] = src;
+ }
+ }
+ if (col > rect.left && row < rect.bottom - 1) {
+ int src = next_scan[col - 1];
+ src += error * 3 / 16;
+ if (src > 255) {
+ next_scan[col - 1] = 255;
+ } else if (src < 0) {
+ next_scan[col - 1] = 0;
+ } else {
+ next_scan[col - 1] = src;
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+CFX_DIBitmap* CFX_DIBSource::FlipImage(FX_BOOL bXFlip, FX_BOOL bYFlip) const {
+ CFX_DIBitmap* pFlipped = new CFX_DIBitmap;
+ if (!pFlipped->Create(m_Width, m_Height, GetFormat())) {
+ delete pFlipped;
+ return NULL;
+ }
+ pFlipped->CopyPalette(m_pPalette);
+ uint8_t* pDestBuffer = pFlipped->GetBuffer();
+ int Bpp = m_bpp / 8;
+ for (int row = 0; row < m_Height; row++) {
+ const uint8_t* src_scan = GetScanline(row);
+ uint8_t* dest_scan =
+ pDestBuffer + m_Pitch * (bYFlip ? (m_Height - row - 1) : row);
+ if (!bXFlip) {
+ FXSYS_memcpy(dest_scan, src_scan, m_Pitch);
+ continue;
+ }
+ if (m_bpp == 1) {
+ FXSYS_memset(dest_scan, 0, m_Pitch);
+ for (int col = 0; col < m_Width; col++)
+ if (src_scan[col / 8] & (1 << (7 - col % 8))) {
+ int dest_col = m_Width - col - 1;
+ dest_scan[dest_col / 8] |= (1 << (7 - dest_col % 8));
+ }
+ } else {
+ dest_scan += (m_Width - 1) * Bpp;
+ if (Bpp == 1) {
+ for (int col = 0; col < m_Width; col++) {
+ *dest_scan = *src_scan;
+ dest_scan--;
+ src_scan++;
+ }
+ } else if (Bpp == 3) {
+ for (int col = 0; col < m_Width; col++) {
+ dest_scan[0] = src_scan[0];
+ dest_scan[1] = src_scan[1];
+ dest_scan[2] = src_scan[2];
+ dest_scan -= 3;
+ src_scan += 3;
+ }
+ } else {
+ ASSERT(Bpp == 4);
+ for (int col = 0; col < m_Width; col++) {
+ *(FX_DWORD*)dest_scan = *(FX_DWORD*)src_scan;
+ dest_scan -= 4;
+ src_scan += 4;
+ }
+ }
+ }
+ }
+ if (m_pAlphaMask) {
+ pDestBuffer = pFlipped->m_pAlphaMask->GetBuffer();
+ FX_DWORD dest_pitch = pFlipped->m_pAlphaMask->GetPitch();
+ for (int row = 0; row < m_Height; row++) {
+ const uint8_t* src_scan = m_pAlphaMask->GetScanline(row);
+ uint8_t* dest_scan =
+ pDestBuffer + dest_pitch * (bYFlip ? (m_Height - row - 1) : row);
+ if (!bXFlip) {
+ FXSYS_memcpy(dest_scan, src_scan, dest_pitch);
+ continue;
+ }
+ dest_scan += (m_Width - 1);
+ for (int col = 0; col < m_Width; col++) {
+ *dest_scan = *src_scan;
+ dest_scan--;
+ src_scan++;
+ }
+ }
+ }
+ return pFlipped;
+}
+CFX_DIBExtractor::CFX_DIBExtractor(const CFX_DIBSource* pSrc) {
+ m_pBitmap = NULL;
+ if (pSrc->GetBuffer()) {
+ m_pBitmap = new CFX_DIBitmap;
+ if (!m_pBitmap->Create(pSrc->GetWidth(), pSrc->GetHeight(),
+ pSrc->GetFormat(), pSrc->GetBuffer())) {
+ delete m_pBitmap;
+ m_pBitmap = NULL;
+ return;
+ }
+ m_pBitmap->CopyPalette(pSrc->GetPalette());
+ m_pBitmap->CopyAlphaMask(pSrc->m_pAlphaMask);
+ } else {
+ m_pBitmap = pSrc->Clone();
+ }
+}
+CFX_DIBExtractor::~CFX_DIBExtractor() {
+ delete m_pBitmap;
+}
+CFX_FilteredDIB::CFX_FilteredDIB() {
+ m_pScanline = NULL;
+ m_pSrc = NULL;
+}
+CFX_FilteredDIB::~CFX_FilteredDIB() {
+ if (m_bAutoDropSrc) {
+ delete m_pSrc;
+ }
+ FX_Free(m_pScanline);
+}
+void CFX_FilteredDIB::LoadSrc(const CFX_DIBSource* pSrc, FX_BOOL bAutoDropSrc) {
+ m_pSrc = pSrc;
+ m_bAutoDropSrc = bAutoDropSrc;
+ m_Width = pSrc->GetWidth();
+ m_Height = pSrc->GetHeight();
+ FXDIB_Format format = GetDestFormat();
+ m_bpp = (uint8_t)format;
+ m_AlphaFlag = (uint8_t)(format >> 8);
+ m_Pitch = (m_Width * (format & 0xff) + 31) / 32 * 4;
+ m_pPalette = GetDestPalette();
+ m_pScanline = FX_Alloc(uint8_t, m_Pitch);
+}
+const uint8_t* CFX_FilteredDIB::GetScanline(int line) const {
+ TranslateScanline(m_pScanline, m_pSrc->GetScanline(line));
+ return m_pScanline;
+}
+void CFX_FilteredDIB::DownSampleScanline(int line,
+ uint8_t* dest_scan,
+ int dest_bpp,
+ int dest_width,
+ FX_BOOL bFlipX,
+ int clip_left,
+ int clip_width) const {
+ m_pSrc->DownSampleScanline(line, dest_scan, dest_bpp, dest_width, bFlipX,
+ clip_left, clip_width);
+ TranslateDownSamples(dest_scan, dest_scan, clip_width, dest_bpp);
+}
+CFX_ImageRenderer::CFX_ImageRenderer() {
+ m_Status = 0;
+ m_pTransformer = NULL;
+ m_bRgbByteOrder = FALSE;
+ m_BlendType = FXDIB_BLEND_NORMAL;
+}
+CFX_ImageRenderer::~CFX_ImageRenderer() {
+ delete m_pTransformer;
+}
+FX_BOOL CFX_ImageRenderer::Start(CFX_DIBitmap* pDevice,
+ const CFX_ClipRgn* pClipRgn,
+ const CFX_DIBSource* pSource,
+ int bitmap_alpha,
+ FX_DWORD mask_color,
+ const CFX_Matrix* pMatrix,
+ FX_DWORD dib_flags,
+ FX_BOOL bRgbByteOrder,
+ int alpha_flag,
+ void* pIccTransform,
+ int blend_type) {
+ m_Matrix = *pMatrix;
+ CFX_FloatRect image_rect_f = m_Matrix.GetUnitRect();
+ FX_RECT image_rect = image_rect_f.GetOutterRect();
+ m_ClipBox = pClipRgn ? pClipRgn->GetBox() : FX_RECT(0, 0, pDevice->GetWidth(),
+ pDevice->GetHeight());
+ m_ClipBox.Intersect(image_rect);
+ if (m_ClipBox.IsEmpty()) {
+ return FALSE;
+ }
+ m_pDevice = pDevice;
+ m_pClipRgn = pClipRgn;
+ m_MaskColor = mask_color;
+ m_BitmapAlpha = bitmap_alpha;
+ m_Matrix = *pMatrix;
+ m_Flags = dib_flags;
+ m_AlphaFlag = alpha_flag;
+ 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 &&
+ FXSYS_fabs(m_Matrix.d) < FXSYS_fabs(m_Matrix.c) / 20 &&
+ FXSYS_fabs(m_Matrix.a) < 0.5f && FXSYS_fabs(m_Matrix.d) < 0.5f) {
+ int dest_width = image_rect.Width();
+ int dest_height = image_rect.Height();
+ FX_RECT bitmap_clip = m_ClipBox;
+ bitmap_clip.Offset(-image_rect.left, -image_rect.top);
+ bitmap_clip = FXDIB_SwapClipBox(bitmap_clip, dest_width, dest_height,
+ m_Matrix.c > 0, m_Matrix.b < 0);
+ 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)) {
+ return FALSE;
+ }
+ m_Status = 1;
+ return TRUE;
+ }
+ m_Status = 2;
+ m_pTransformer = new CFX_ImageTransformer;
+ m_pTransformer->Start(pSource, &m_Matrix, dib_flags, &m_ClipBox);
+ return TRUE;
+ }
+ int dest_width = image_rect.Width();
+ if (m_Matrix.a < 0) {
+ dest_width = -dest_width;
+ }
+ int dest_height = image_rect.Height();
+ if (m_Matrix.d > 0) {
+ dest_height = -dest_height;
+ }
+ 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;
+}
+FX_BOOL CFX_ImageRenderer::Continue(IFX_Pause* pPause) {
+ if (m_Status == 1) {
+ return m_Stretcher.Continue(pPause);
+ }
+ if (m_Status == 2) {
+ if (m_pTransformer->Continue(pPause)) {
+ return TRUE;
+ }
+ CFX_DIBitmap* pBitmap = m_pTransformer->m_Storer.Detach();
+ if (!pBitmap) {
+ return FALSE;
+ }
+ if (!pBitmap->GetBuffer()) {
+ delete pBitmap;
+ return FALSE;
+ }
+ if (pBitmap->IsAlphaMask()) {
+ if (m_BitmapAlpha != 255) {
+ if (m_AlphaFlag >> 8) {
+ m_AlphaFlag =
+ (((uint8_t)((m_AlphaFlag & 0xff) * m_BitmapAlpha / 255)) |
+ ((m_AlphaFlag >> 8) << 8));
+ } else {
+ m_MaskColor = FXARGB_MUL_ALPHA(m_MaskColor, m_BitmapAlpha);
+ }
+ }
+ m_pDevice->CompositeMask(m_pTransformer->m_ResultLeft,
+ m_pTransformer->m_ResultTop, pBitmap->GetWidth(),
+ pBitmap->GetHeight(), pBitmap, m_MaskColor, 0, 0,
+ m_BlendType, m_pClipRgn, m_bRgbByteOrder,
+ m_AlphaFlag, m_pIccTransform);
+ } else {
+ if (m_BitmapAlpha != 255) {
+ pBitmap->MultiplyAlpha(m_BitmapAlpha);
+ }
+ m_pDevice->CompositeBitmap(
+ m_pTransformer->m_ResultLeft, m_pTransformer->m_ResultTop,
+ pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap, 0, 0, m_BlendType,
+ m_pClipRgn, m_bRgbByteOrder, m_pIccTransform);
+ }
+ delete pBitmap;
+ return FALSE;
+ }
+ return FALSE;
+}
+CFX_BitmapStorer::CFX_BitmapStorer() {
+ m_pBitmap = NULL;
+}
+CFX_BitmapStorer::~CFX_BitmapStorer() {
+ delete m_pBitmap;
+}
+CFX_DIBitmap* CFX_BitmapStorer::Detach() {
+ CFX_DIBitmap* pBitmap = m_pBitmap;
+ m_pBitmap = NULL;
+ return pBitmap;
+}
+void CFX_BitmapStorer::Replace(CFX_DIBitmap* pBitmap) {
+ delete m_pBitmap;
+ m_pBitmap = pBitmap;
+}
+void CFX_BitmapStorer::ComposeScanline(int line,
+ const uint8_t* scanline,
+ const uint8_t* scan_extra_alpha) {
+ uint8_t* dest_buf = (uint8_t*)m_pBitmap->GetScanline(line);
+ uint8_t* dest_alpha_buf =
+ m_pBitmap->m_pAlphaMask
+ ? (uint8_t*)m_pBitmap->m_pAlphaMask->GetScanline(line)
+ : NULL;
+ if (dest_buf) {
+ FXSYS_memcpy(dest_buf, scanline, m_pBitmap->GetPitch());
+ }
+ if (dest_alpha_buf) {
+ FXSYS_memcpy(dest_alpha_buf, scan_extra_alpha,
+ m_pBitmap->m_pAlphaMask->GetPitch());
+ }
+}
+FX_BOOL CFX_BitmapStorer::SetInfo(int width,
+ int height,
+ FXDIB_Format src_format,
+ FX_DWORD* pSrcPalette) {
+ m_pBitmap = new CFX_DIBitmap;
+ if (!m_pBitmap->Create(width, height, src_format)) {
+ delete m_pBitmap;
+ m_pBitmap = NULL;
+ return FALSE;
+ }
+ if (pSrcPalette) {
+ m_pBitmap->CopyPalette(pSrcPalette);
+ }
+ return TRUE;
+}
diff --git a/core/fxge/dib/fx_dib_transform.cpp b/core/fxge/dib/fx_dib_transform.cpp
new file mode 100644
index 0000000000..dc6fb93c75
--- /dev/null
+++ b/core/fxge/dib/fx_dib_transform.cpp
@@ -0,0 +1,948 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxge/dib/dib_int.h"
+
+#include "core/include/fxge/fx_dib.h"
+
+namespace {
+
+uint8_t bilinear_interpol(const uint8_t* buf,
+ int row_offset_l,
+ int row_offset_r,
+ int src_col_l,
+ int src_col_r,
+ int res_x,
+ int res_y,
+ int bpp,
+ int c_offset) {
+ int i_resx = 255 - res_x;
+ int col_bpp_l = src_col_l * bpp;
+ int col_bpp_r = src_col_r * bpp;
+ const uint8_t* buf_u = buf + row_offset_l + c_offset;
+ const uint8_t* buf_d = buf + row_offset_r + c_offset;
+ const uint8_t* src_pos0 = buf_u + col_bpp_l;
+ const uint8_t* src_pos1 = buf_u + col_bpp_r;
+ const uint8_t* src_pos2 = buf_d + col_bpp_l;
+ const uint8_t* src_pos3 = buf_d + col_bpp_r;
+ uint8_t r_pos_0 = (*src_pos0 * i_resx + *src_pos1 * res_x) >> 8;
+ uint8_t r_pos_1 = (*src_pos2 * i_resx + *src_pos3 * res_x) >> 8;
+ return (r_pos_0 * (255 - res_y) + r_pos_1 * res_y) >> 8;
+}
+
+uint8_t bicubic_interpol(const uint8_t* buf,
+ int pitch,
+ int pos_pixel[],
+ int u_w[],
+ int v_w[],
+ int res_x,
+ int res_y,
+ int bpp,
+ int c_offset) {
+ int s_result = 0;
+ for (int i = 0; i < 4; i++) {
+ int a_result = 0;
+ for (int j = 0; j < 4; j++) {
+ a_result += u_w[j] * (*(uint8_t*)(buf + pos_pixel[i + 4] * pitch +
+ pos_pixel[j] * bpp + c_offset));
+ }
+ s_result += a_result * v_w[i];
+ }
+ s_result >>= 16;
+ return (uint8_t)(s_result < 0 ? 0 : s_result > 255 ? 255 : s_result);
+}
+
+void bicubic_get_pos_weight(int pos_pixel[],
+ int u_w[],
+ int v_w[],
+ int src_col_l,
+ int src_row_l,
+ int res_x,
+ int res_y,
+ int stretch_width,
+ int stretch_height) {
+ pos_pixel[0] = src_col_l - 1;
+ pos_pixel[1] = src_col_l;
+ pos_pixel[2] = src_col_l + 1;
+ pos_pixel[3] = src_col_l + 2;
+ pos_pixel[4] = src_row_l - 1;
+ pos_pixel[5] = src_row_l;
+ pos_pixel[6] = src_row_l + 1;
+ pos_pixel[7] = src_row_l + 2;
+ for (int i = 0; i < 4; i++) {
+ if (pos_pixel[i] < 0) {
+ pos_pixel[i] = 0;
+ }
+ if (pos_pixel[i] >= stretch_width) {
+ pos_pixel[i] = stretch_width - 1;
+ }
+ if (pos_pixel[i + 4] < 0) {
+ pos_pixel[i + 4] = 0;
+ }
+ if (pos_pixel[i + 4] >= stretch_height) {
+ pos_pixel[i + 4] = stretch_height - 1;
+ }
+ }
+ u_w[0] = SDP_Table[256 + res_x];
+ u_w[1] = SDP_Table[res_x];
+ u_w[2] = SDP_Table[256 - res_x];
+ u_w[3] = SDP_Table[512 - res_x];
+ v_w[0] = SDP_Table[256 + res_y];
+ v_w[1] = SDP_Table[res_y];
+ v_w[2] = SDP_Table[256 - res_y];
+ v_w[3] = SDP_Table[512 - res_y];
+}
+
+FXDIB_Format GetTransformedFormat(const CFX_DIBSource* pDrc) {
+ FXDIB_Format format = pDrc->GetFormat();
+ if (pDrc->IsAlphaMask()) {
+ format = FXDIB_8bppMask;
+ } else if (format >= 1025) {
+ format = FXDIB_Cmyka;
+ } else if (format <= 32 || format == FXDIB_Argb) {
+ format = FXDIB_Argb;
+ } else {
+ format = FXDIB_Rgba;
+ }
+ return format;
+}
+
+} // namespace
+
+const int16_t SDP_Table[513] = {
+ 256, 256, 256, 256, 256, 256, 256, 256, 256, 255, 255, 255, 255, 255, 255,
+ 254, 254, 254, 254, 253, 253, 253, 252, 252, 252, 251, 251, 251, 250, 250,
+ 249, 249, 249, 248, 248, 247, 247, 246, 246, 245, 244, 244, 243, 243, 242,
+ 242, 241, 240, 240, 239, 238, 238, 237, 236, 236, 235, 234, 233, 233, 232,
+ 231, 230, 230, 229, 228, 227, 226, 226, 225, 224, 223, 222, 221, 220, 219,
+ 218, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205,
+ 204, 203, 202, 201, 200, 199, 198, 196, 195, 194, 193, 192, 191, 190, 189,
+ 188, 186, 185, 184, 183, 182, 181, 179, 178, 177, 176, 175, 173, 172, 171,
+ 170, 169, 167, 166, 165, 164, 162, 161, 160, 159, 157, 156, 155, 154, 152,
+ 151, 150, 149, 147, 146, 145, 143, 142, 141, 140, 138, 137, 136, 134, 133,
+ 132, 130, 129, 128, 126, 125, 124, 122, 121, 120, 119, 117, 116, 115, 113,
+ 112, 111, 109, 108, 107, 105, 104, 103, 101, 100, 99, 97, 96, 95, 93,
+ 92, 91, 89, 88, 87, 85, 84, 83, 81, 80, 79, 77, 76, 75, 73,
+ 72, 71, 69, 68, 67, 66, 64, 63, 62, 60, 59, 58, 57, 55, 54,
+ 53, 52, 50, 49, 48, 47, 45, 44, 43, 42, 40, 39, 38, 37, 36,
+ 34, 33, 32, 31, 30, 28, 27, 26, 25, 24, 23, 21, 20, 19, 18,
+ 17, 16, 15, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
+ 1, 0, 0, -1, -2, -3, -4, -5, -6, -7, -7, -8, -9, -10, -11,
+ -12, -12, -13, -14, -15, -15, -16, -17, -17, -18, -19, -19, -20, -21, -21,
+ -22, -22, -23, -24, -24, -25, -25, -26, -26, -27, -27, -27, -28, -28, -29,
+ -29, -30, -30, -30, -31, -31, -31, -32, -32, -32, -33, -33, -33, -33, -34,
+ -34, -34, -34, -35, -35, -35, -35, -35, -36, -36, -36, -36, -36, -36, -36,
+ -36, -36, -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, -37,
+ -37, -37, -37, -37, -37, -37, -37, -37, -36, -36, -36, -36, -36, -36, -36,
+ -36, -36, -35, -35, -35, -35, -35, -35, -34, -34, -34, -34, -34, -33, -33,
+ -33, -33, -33, -32, -32, -32, -32, -31, -31, -31, -31, -30, -30, -30, -30,
+ -29, -29, -29, -29, -28, -28, -28, -27, -27, -27, -27, -26, -26, -26, -25,
+ -25, -25, -24, -24, -24, -23, -23, -23, -22, -22, -22, -22, -21, -21, -21,
+ -20, -20, -20, -19, -19, -19, -18, -18, -18, -17, -17, -17, -16, -16, -16,
+ -15, -15, -15, -14, -14, -14, -13, -13, -13, -12, -12, -12, -11, -11, -11,
+ -10, -10, -10, -9, -9, -9, -9, -8, -8, -8, -7, -7, -7, -7, -6,
+ -6, -6, -6, -5, -5, -5, -5, -4, -4, -4, -4, -3, -3, -3, -3,
+ -3, -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, -1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,
+};
+
+class CFX_BilinearMatrix : public CPDF_FixedMatrix {
+ public:
+ CFX_BilinearMatrix(const CFX_Matrix& src, int bits)
+ : CPDF_FixedMatrix(src, bits) {}
+ inline void Transform(int x,
+ int y,
+ int& x1,
+ int& y1,
+ int& res_x,
+ int& res_y) {
+ x1 = a * x + c * y + e + base / 2;
+ y1 = b * x + d * y + f + base / 2;
+ res_x = x1 % base;
+ res_y = y1 % base;
+ if (res_x < 0 && res_x > -base) {
+ res_x = base + res_x;
+ }
+ if (res_y < 0 && res_x > -base) {
+ res_y = base + res_y;
+ }
+ x1 /= base;
+ y1 /= base;
+ }
+};
+CFX_DIBitmap* CFX_DIBSource::SwapXY(FX_BOOL bXFlip,
+ FX_BOOL bYFlip,
+ const FX_RECT* pDestClip) const {
+ FX_RECT dest_clip(0, 0, m_Height, m_Width);
+ if (pDestClip) {
+ dest_clip.Intersect(*pDestClip);
+ }
+ if (dest_clip.IsEmpty()) {
+ return NULL;
+ }
+ CFX_DIBitmap* pTransBitmap = new CFX_DIBitmap;
+ int result_height = dest_clip.Height(), result_width = dest_clip.Width();
+ if (!pTransBitmap->Create(result_width, result_height, GetFormat())) {
+ delete pTransBitmap;
+ return NULL;
+ }
+ pTransBitmap->CopyPalette(m_pPalette);
+ int dest_pitch = pTransBitmap->GetPitch();
+ uint8_t* dest_buf = pTransBitmap->GetBuffer();
+ int row_start = bXFlip ? m_Height - dest_clip.right : dest_clip.left;
+ int row_end = bXFlip ? m_Height - dest_clip.left : dest_clip.right;
+ int col_start = bYFlip ? m_Width - dest_clip.bottom : dest_clip.top;
+ int col_end = bYFlip ? m_Width - dest_clip.top : dest_clip.bottom;
+ if (GetBPP() == 1) {
+ FXSYS_memset(dest_buf, 0xff, dest_pitch * result_height);
+ for (int row = row_start; row < row_end; row++) {
+ const uint8_t* src_scan = GetScanline(row);
+ int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) -
+ dest_clip.left;
+ uint8_t* dest_scan = dest_buf;
+ if (bYFlip) {
+ dest_scan += (result_height - 1) * dest_pitch;
+ }
+ int dest_step = bYFlip ? -dest_pitch : dest_pitch;
+ for (int col = col_start; col < col_end; col++) {
+ if (!(src_scan[col / 8] & (1 << (7 - col % 8)))) {
+ dest_scan[dest_col / 8] &= ~(1 << (7 - dest_col % 8));
+ }
+ dest_scan += dest_step;
+ }
+ }
+ } else {
+ int nBytes = GetBPP() / 8;
+ int dest_step = bYFlip ? -dest_pitch : dest_pitch;
+ if (nBytes == 3) {
+ dest_step -= 2;
+ }
+ for (int row = row_start; row < row_end; row++) {
+ int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) -
+ dest_clip.left;
+ uint8_t* dest_scan = dest_buf + dest_col * nBytes;
+ if (bYFlip) {
+ dest_scan += (result_height - 1) * dest_pitch;
+ }
+ if (nBytes == 4) {
+ FX_DWORD* src_scan = (FX_DWORD*)GetScanline(row) + col_start;
+ for (int col = col_start; col < col_end; col++) {
+ *(FX_DWORD*)dest_scan = *src_scan++;
+ dest_scan += dest_step;
+ }
+ } else {
+ const uint8_t* src_scan = GetScanline(row) + col_start * nBytes;
+ if (nBytes == 1) {
+ for (int col = col_start; col < col_end; col++) {
+ *dest_scan = *src_scan++;
+ dest_scan += dest_step;
+ }
+ } else {
+ for (int col = col_start; col < col_end; col++) {
+ *dest_scan++ = *src_scan++;
+ *dest_scan++ = *src_scan++;
+ *dest_scan = *src_scan++;
+ dest_scan += dest_step;
+ }
+ }
+ }
+ }
+ }
+ if (m_pAlphaMask) {
+ dest_pitch = pTransBitmap->m_pAlphaMask->GetPitch();
+ dest_buf = pTransBitmap->m_pAlphaMask->GetBuffer();
+ int dest_step = bYFlip ? -dest_pitch : dest_pitch;
+ for (int row = row_start; row < row_end; row++) {
+ int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) -
+ dest_clip.left;
+ uint8_t* dest_scan = dest_buf + dest_col;
+ if (bYFlip) {
+ dest_scan += (result_height - 1) * dest_pitch;
+ }
+ const uint8_t* src_scan = m_pAlphaMask->GetScanline(row) + col_start;
+ for (int col = col_start; col < col_end; col++) {
+ *dest_scan = *src_scan++;
+ dest_scan += dest_step;
+ }
+ }
+ }
+ return pTransBitmap;
+}
+#define FIX16_005 0.05f
+FX_RECT FXDIB_SwapClipBox(FX_RECT& clip,
+ int width,
+ int height,
+ FX_BOOL bFlipX,
+ FX_BOOL bFlipY) {
+ FX_RECT rect;
+ if (bFlipY) {
+ rect.left = height - clip.top;
+ rect.right = height - clip.bottom;
+ } else {
+ rect.left = clip.top;
+ rect.right = clip.bottom;
+ }
+ if (bFlipX) {
+ rect.top = width - clip.left;
+ rect.bottom = width - clip.right;
+ } else {
+ rect.top = clip.left;
+ rect.bottom = clip.right;
+ }
+ rect.Normalize();
+ return rect;
+}
+CFX_DIBitmap* CFX_DIBSource::TransformTo(const CFX_Matrix* pDestMatrix,
+ int& result_left,
+ int& result_top,
+ FX_DWORD flags,
+ const FX_RECT* pDestClip) const {
+ CFX_ImageTransformer transformer;
+ transformer.Start(this, pDestMatrix, flags, pDestClip);
+ transformer.Continue(NULL);
+ result_left = transformer.m_ResultLeft;
+ result_top = transformer.m_ResultTop;
+ CFX_DIBitmap* pTransformed = transformer.m_Storer.Detach();
+ return pTransformed;
+}
+CFX_DIBitmap* CFX_DIBSource::StretchTo(int dest_width,
+ int dest_height,
+ FX_DWORD flags,
+ const FX_RECT* pClip) const {
+ FX_RECT clip_rect(0, 0, FXSYS_abs(dest_width), FXSYS_abs(dest_height));
+ if (pClip) {
+ clip_rect.Intersect(*pClip);
+ }
+ if (clip_rect.IsEmpty()) {
+ return NULL;
+ }
+ 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);
+ }
+ 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,
+ const FX_RECT* pDestClip) {
+ m_pMatrix = (CFX_Matrix*)pDestMatrix;
+ CFX_FloatRect unit_rect = pDestMatrix->GetUnitRect();
+ FX_RECT result_rect = unit_rect.GetClosestRect();
+ FX_RECT result_clip = result_rect;
+ if (pDestClip) {
+ result_clip.Intersect(*pDestClip);
+ }
+ if (result_clip.IsEmpty()) {
+ return FALSE;
+ }
+ m_ResultLeft = result_clip.left;
+ m_ResultTop = result_clip.top;
+ m_ResultWidth = result_clip.Width();
+ m_ResultHeight = result_clip.Height();
+ m_Flags = flags;
+ if (FXSYS_fabs(pDestMatrix->a) < FXSYS_fabs(pDestMatrix->b) / 20 &&
+ FXSYS_fabs(pDestMatrix->d) < FXSYS_fabs(pDestMatrix->c) / 20 &&
+ FXSYS_fabs(pDestMatrix->a) < 0.5f && FXSYS_fabs(pDestMatrix->d) < 0.5f) {
+ int dest_width = result_rect.Width();
+ int dest_height = result_rect.Height();
+ 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_Status = 1;
+ return TRUE;
+ }
+ if (FXSYS_fabs(pDestMatrix->b) < FIX16_005 &&
+ FXSYS_fabs(pDestMatrix->c) < FIX16_005) {
+ int dest_width = pDestMatrix->a > 0 ? (int)FXSYS_ceil(pDestMatrix->a)
+ : (int)FXSYS_floor(pDestMatrix->a);
+ 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_Status = 2;
+ return TRUE;
+ }
+ int stretch_width =
+ (int)FXSYS_ceil(FXSYS_sqrt2(pDestMatrix->a, pDestMatrix->b));
+ int stretch_height =
+ (int)FXSYS_ceil(FXSYS_sqrt2(pDestMatrix->c, pDestMatrix->d));
+ CFX_Matrix stretch2dest(1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
+ (FX_FLOAT)(stretch_height));
+ stretch2dest.Concat(
+ pDestMatrix->a / stretch_width, pDestMatrix->b / stretch_width,
+ pDestMatrix->c / stretch_height, pDestMatrix->d / stretch_height,
+ pDestMatrix->e, pDestMatrix->f);
+ m_dest2stretch.SetReverse(stretch2dest);
+ CFX_FloatRect clip_rect_f(result_clip);
+ 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_Status = 3;
+ return TRUE;
+}
+
+FX_BOOL CFX_ImageTransformer::Continue(IFX_Pause* pPause) {
+ if (m_Status == 1) {
+ 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) {
+ return FALSE;
+ }
+ if (m_Stretcher.Continue(pPause)) {
+ return TRUE;
+ }
+ int stretch_width = m_StretchClip.Width();
+ int stretch_height = m_StretchClip.Height();
+ 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) {
+ 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;
+ return FALSE;
+ }
+ pTransformed->Clear(0);
+ 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);
+ result2stretch.TranslateI(-m_StretchClip.left, -m_StretchClip.top);
+ if (!stretch_buf_mask && pTransformed->m_pAlphaMask) {
+ pTransformed->m_pAlphaMask->Clear(0xff000000);
+ } else if (pTransformed->m_pAlphaMask) {
+ int stretch_pitch_mask = m_Storer.GetBitmap()->m_pAlphaMask->GetPitch();
+ if (!(m_Flags & FXDIB_DOWNSAMPLE) && !(m_Flags & FXDIB_BICUBIC_INTERPOL)) {
+ CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
+ for (int row = 0; row < m_ResultHeight; row++) {
+ uint8_t* dest_pos_mask =
+ (uint8_t*)pTransformed->m_pAlphaMask->GetScanline(row);
+ for (int col = 0; col < m_ResultWidth; col++) {
+ int src_col_l, src_row_l, res_x, res_y;
+ result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
+ res_y);
+ if (src_col_l >= 0 && src_col_l <= stretch_width && src_row_l >= 0 &&
+ src_row_l <= stretch_height) {
+ if (src_col_l == stretch_width) {
+ src_col_l--;
+ }
+ if (src_row_l == stretch_height) {
+ src_row_l--;
+ }
+ int src_col_r = src_col_l + 1;
+ int src_row_r = src_row_l + 1;
+ if (src_col_r == stretch_width) {
+ src_col_r--;
+ }
+ if (src_row_r == stretch_height) {
+ src_row_r--;
+ }
+ int row_offset_l = src_row_l * stretch_pitch_mask;
+ int row_offset_r = src_row_r * stretch_pitch_mask;
+ *dest_pos_mask =
+ bilinear_interpol(stretch_buf_mask, row_offset_l, row_offset_r,
+ src_col_l, src_col_r, res_x, res_y, 1, 0);
+ }
+ dest_pos_mask++;
+ }
+ }
+ } else if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+ CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
+ for (int row = 0; row < m_ResultHeight; row++) {
+ uint8_t* dest_pos_mask =
+ (uint8_t*)pTransformed->m_pAlphaMask->GetScanline(row);
+ for (int col = 0; col < m_ResultWidth; col++) {
+ int src_col_l, src_row_l, res_x, res_y;
+ result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
+ res_y);
+ if (src_col_l >= 0 && src_col_l <= stretch_width && src_row_l >= 0 &&
+ src_row_l <= stretch_height) {
+ int pos_pixel[8];
+ int u_w[4], v_w[4];
+ if (src_col_l == stretch_width) {
+ src_col_l--;
+ }
+ if (src_row_l == stretch_height) {
+ src_row_l--;
+ }
+ bicubic_get_pos_weight(pos_pixel, u_w, v_w, src_col_l, src_row_l,
+ res_x, res_y, stretch_width, stretch_height);
+ *dest_pos_mask =
+ bicubic_interpol(stretch_buf_mask, stretch_pitch_mask,
+ pos_pixel, u_w, v_w, res_x, res_y, 1, 0);
+ }
+ dest_pos_mask++;
+ }
+ }
+ } else {
+ CPDF_FixedMatrix result2stretch_fix(result2stretch, 8);
+ for (int row = 0; row < m_ResultHeight; row++) {
+ uint8_t* dest_pos_mask =
+ (uint8_t*)pTransformed->m_pAlphaMask->GetScanline(row);
+ for (int col = 0; col < m_ResultWidth; col++) {
+ int src_col, src_row;
+ result2stretch_fix.Transform(col, row, src_col, src_row);
+ if (src_col >= 0 && src_col <= stretch_width && src_row >= 0 &&
+ src_row <= stretch_height) {
+ if (src_col == stretch_width) {
+ src_col--;
+ }
+ if (src_row == stretch_height) {
+ src_row--;
+ }
+ *dest_pos_mask =
+ stretch_buf_mask[src_row * stretch_pitch_mask + src_col];
+ }
+ dest_pos_mask++;
+ }
+ }
+ }
+ }
+ if (m_Storer.GetBitmap()->IsAlphaMask()) {
+ if (!(m_Flags & FXDIB_DOWNSAMPLE) && !(m_Flags & FXDIB_BICUBIC_INTERPOL)) {
+ CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
+ for (int row = 0; row < m_ResultHeight; row++) {
+ uint8_t* dest_scan = (uint8_t*)pTransformed->GetScanline(row);
+ for (int col = 0; col < m_ResultWidth; col++) {
+ int src_col_l, src_row_l, res_x, res_y;
+ result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
+ res_y);
+ if (src_col_l >= 0 && src_col_l <= stretch_width && src_row_l >= 0 &&
+ src_row_l <= stretch_height) {
+ if (src_col_l == stretch_width) {
+ src_col_l--;
+ }
+ if (src_row_l == stretch_height) {
+ src_row_l--;
+ }
+ int src_col_r = src_col_l + 1;
+ int src_row_r = src_row_l + 1;
+ if (src_col_r == stretch_width) {
+ src_col_r--;
+ }
+ if (src_row_r == stretch_height) {
+ src_row_r--;
+ }
+ int row_offset_l = src_row_l * stretch_pitch;
+ int row_offset_r = src_row_r * stretch_pitch;
+ *dest_scan =
+ bilinear_interpol(stretch_buf, row_offset_l, row_offset_r,
+ src_col_l, src_col_r, res_x, res_y, 1, 0);
+ }
+ dest_scan++;
+ }
+ }
+ } else if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+ CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
+ for (int row = 0; row < m_ResultHeight; row++) {
+ uint8_t* dest_scan = (uint8_t*)pTransformed->GetScanline(row);
+ for (int col = 0; col < m_ResultWidth; col++) {
+ int src_col_l, src_row_l, res_x, res_y;
+ result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
+ res_y);
+ if (src_col_l >= 0 && src_col_l <= stretch_width && src_row_l >= 0 &&
+ src_row_l <= stretch_height) {
+ int pos_pixel[8];
+ int u_w[4], v_w[4];
+ if (src_col_l == stretch_width) {
+ src_col_l--;
+ }
+ if (src_row_l == stretch_height) {
+ src_row_l--;
+ }
+ bicubic_get_pos_weight(pos_pixel, u_w, v_w, src_col_l, src_row_l,
+ res_x, res_y, stretch_width, stretch_height);
+ *dest_scan = bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel,
+ u_w, v_w, res_x, res_y, 1, 0);
+ }
+ dest_scan++;
+ }
+ }
+ } else {
+ CPDF_FixedMatrix result2stretch_fix(result2stretch, 8);
+ for (int row = 0; row < m_ResultHeight; row++) {
+ uint8_t* dest_scan = (uint8_t*)pTransformed->GetScanline(row);
+ for (int col = 0; col < m_ResultWidth; col++) {
+ int src_col, src_row;
+ result2stretch_fix.Transform(col, row, src_col, src_row);
+ if (src_col >= 0 && src_col <= stretch_width && src_row >= 0 &&
+ src_row <= stretch_height) {
+ if (src_col == stretch_width) {
+ src_col--;
+ }
+ if (src_row == stretch_height) {
+ src_row--;
+ }
+ const uint8_t* src_pixel =
+ stretch_buf + stretch_pitch * src_row + src_col;
+ *dest_scan = *src_pixel;
+ }
+ dest_scan++;
+ }
+ }
+ }
+ } else {
+ int Bpp = m_Storer.GetBitmap()->GetBPP() / 8;
+ int destBpp = pTransformed->GetBPP() / 8;
+ if (Bpp == 1) {
+ FX_DWORD argb[256];
+ FX_ARGB* pPal = m_Storer.GetBitmap()->GetPalette();
+ if (pPal) {
+ for (int i = 0; i < 256; i++) {
+ argb[i] = pPal[i];
+ }
+ } else {
+ if (m_Storer.GetBitmap()->IsCmykImage()) {
+ for (int i = 0; i < 256; i++) {
+ argb[i] = 255 - i;
+ }
+ } else {
+ for (int i = 0; i < 256; i++) {
+ argb[i] = 0xff000000 | (i * 0x010101);
+ }
+ }
+ }
+ if (!(m_Flags & FXDIB_DOWNSAMPLE) &&
+ !(m_Flags & FXDIB_BICUBIC_INTERPOL)) {
+ CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
+ for (int row = 0; row < m_ResultHeight; row++) {
+ uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
+ for (int col = 0; col < m_ResultWidth; col++) {
+ int src_col_l, src_row_l, res_x, res_y;
+ result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
+ res_y);
+ if (src_col_l >= 0 && src_col_l <= stretch_width &&
+ src_row_l >= 0 && src_row_l <= stretch_height) {
+ if (src_col_l == stretch_width) {
+ src_col_l--;
+ }
+ if (src_row_l == stretch_height) {
+ src_row_l--;
+ }
+ int src_col_r = src_col_l + 1;
+ int src_row_r = src_row_l + 1;
+ if (src_col_r == stretch_width) {
+ src_col_r--;
+ }
+ if (src_row_r == stretch_height) {
+ src_row_r--;
+ }
+ int row_offset_l = src_row_l * stretch_pitch;
+ int row_offset_r = src_row_r * stretch_pitch;
+ FX_DWORD r_bgra_cmyk = argb[bilinear_interpol(
+ stretch_buf, row_offset_l, row_offset_r, src_col_l, src_col_r,
+ res_x, res_y, 1, 0)];
+ if (transformF == FXDIB_Rgba) {
+ dest_pos[0] = (uint8_t)(r_bgra_cmyk >> 24);
+ dest_pos[1] = (uint8_t)(r_bgra_cmyk >> 16);
+ dest_pos[2] = (uint8_t)(r_bgra_cmyk >> 8);
+ } else {
+ *(FX_DWORD*)dest_pos = r_bgra_cmyk;
+ }
+ }
+ dest_pos += destBpp;
+ }
+ }
+ } else if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+ CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
+ for (int row = 0; row < m_ResultHeight; row++) {
+ uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
+ for (int col = 0; col < m_ResultWidth; col++) {
+ int src_col_l, src_row_l, res_x, res_y;
+ result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
+ res_y);
+ if (src_col_l >= 0 && src_col_l <= stretch_width &&
+ src_row_l >= 0 && src_row_l <= stretch_height) {
+ int pos_pixel[8];
+ int u_w[4], v_w[4];
+ if (src_col_l == stretch_width) {
+ src_col_l--;
+ }
+ if (src_row_l == stretch_height) {
+ src_row_l--;
+ }
+ bicubic_get_pos_weight(pos_pixel, u_w, v_w, src_col_l, src_row_l,
+ res_x, res_y, stretch_width,
+ stretch_height);
+ FX_DWORD r_bgra_cmyk =
+ argb[bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel,
+ u_w, v_w, res_x, res_y, 1, 0)];
+ if (transformF == FXDIB_Rgba) {
+ dest_pos[0] = (uint8_t)(r_bgra_cmyk >> 24);
+ dest_pos[1] = (uint8_t)(r_bgra_cmyk >> 16);
+ dest_pos[2] = (uint8_t)(r_bgra_cmyk >> 8);
+ } else {
+ *(FX_DWORD*)dest_pos = r_bgra_cmyk;
+ }
+ }
+ dest_pos += destBpp;
+ }
+ }
+ } else {
+ CPDF_FixedMatrix result2stretch_fix(result2stretch, 8);
+ for (int row = 0; row < m_ResultHeight; row++) {
+ uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
+ for (int col = 0; col < m_ResultWidth; col++) {
+ int src_col, src_row;
+ result2stretch_fix.Transform(col, row, src_col, src_row);
+ if (src_col >= 0 && src_col <= stretch_width && src_row >= 0 &&
+ src_row <= stretch_height) {
+ if (src_col == stretch_width) {
+ src_col--;
+ }
+ if (src_row == stretch_height) {
+ src_row--;
+ }
+ FX_DWORD r_bgra_cmyk =
+ argb[stretch_buf[src_row * stretch_pitch + src_col]];
+ if (transformF == FXDIB_Rgba) {
+ dest_pos[0] = (uint8_t)(r_bgra_cmyk >> 24);
+ dest_pos[1] = (uint8_t)(r_bgra_cmyk >> 16);
+ dest_pos[2] = (uint8_t)(r_bgra_cmyk >> 8);
+ } else {
+ *(FX_DWORD*)dest_pos = r_bgra_cmyk;
+ }
+ }
+ dest_pos += destBpp;
+ }
+ }
+ }
+ } else {
+ FX_BOOL bHasAlpha = m_Storer.GetBitmap()->HasAlpha();
+ int destBpp = pTransformed->GetBPP() / 8;
+ if (!(m_Flags & FXDIB_DOWNSAMPLE) &&
+ !(m_Flags & FXDIB_BICUBIC_INTERPOL)) {
+ CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
+ for (int row = 0; row < m_ResultHeight; row++) {
+ uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
+ for (int col = 0; col < m_ResultWidth; col++) {
+ int src_col_l, src_row_l, res_x, res_y, r_pos_k_r = 0;
+ result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
+ res_y);
+ if (src_col_l >= 0 && src_col_l <= stretch_width &&
+ src_row_l >= 0 && src_row_l <= stretch_height) {
+ if (src_col_l == stretch_width) {
+ src_col_l--;
+ }
+ if (src_row_l == stretch_height) {
+ src_row_l--;
+ }
+ int src_col_r = src_col_l + 1;
+ int src_row_r = src_row_l + 1;
+ if (src_col_r == stretch_width) {
+ src_col_r--;
+ }
+ if (src_row_r == stretch_height) {
+ src_row_r--;
+ }
+ int row_offset_l = src_row_l * stretch_pitch;
+ int row_offset_r = src_row_r * stretch_pitch;
+ uint8_t r_pos_red_y_r =
+ bilinear_interpol(stretch_buf, row_offset_l, row_offset_r,
+ src_col_l, src_col_r, res_x, res_y, Bpp, 2);
+ uint8_t r_pos_green_m_r =
+ bilinear_interpol(stretch_buf, row_offset_l, row_offset_r,
+ src_col_l, src_col_r, res_x, res_y, Bpp, 1);
+ uint8_t r_pos_blue_c_r =
+ bilinear_interpol(stretch_buf, row_offset_l, row_offset_r,
+ src_col_l, src_col_r, res_x, res_y, Bpp, 0);
+ if (bHasAlpha) {
+ if (transformF != FXDIB_Argb) {
+ if (transformF == FXDIB_Rgba) {
+ dest_pos[0] = r_pos_blue_c_r;
+ dest_pos[1] = r_pos_green_m_r;
+ dest_pos[2] = r_pos_red_y_r;
+ } else {
+ r_pos_k_r = bilinear_interpol(
+ stretch_buf, row_offset_l, row_offset_r, src_col_l,
+ src_col_r, res_x, res_y, Bpp, 3);
+ *(FX_DWORD*)dest_pos =
+ FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r,
+ r_pos_red_y_r, r_pos_k_r));
+ }
+ } else {
+ uint8_t r_pos_a_r = bilinear_interpol(
+ stretch_buf, row_offset_l, row_offset_r, src_col_l,
+ src_col_r, res_x, res_y, Bpp, 3);
+ *(FX_DWORD*)dest_pos = FXARGB_TODIB(
+ FXARGB_MAKE(r_pos_a_r, r_pos_red_y_r, r_pos_green_m_r,
+ r_pos_blue_c_r));
+ }
+ } else {
+ r_pos_k_r = 0xff;
+ if (transformF == FXDIB_Cmyka) {
+ r_pos_k_r = bilinear_interpol(
+ stretch_buf, row_offset_l, row_offset_r, src_col_l,
+ src_col_r, res_x, res_y, Bpp, 3);
+ *(FX_DWORD*)dest_pos =
+ FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r,
+ r_pos_red_y_r, r_pos_k_r));
+ } else {
+ *(FX_DWORD*)dest_pos = FXARGB_TODIB(
+ FXARGB_MAKE(r_pos_k_r, r_pos_red_y_r, r_pos_green_m_r,
+ r_pos_blue_c_r));
+ }
+ }
+ }
+ dest_pos += destBpp;
+ }
+ }
+ } else if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
+ CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
+ for (int row = 0; row < m_ResultHeight; row++) {
+ uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
+ for (int col = 0; col < m_ResultWidth; col++) {
+ int src_col_l, src_row_l, res_x, res_y, r_pos_k_r = 0;
+ result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
+ res_y);
+ if (src_col_l >= 0 && src_col_l <= stretch_width &&
+ src_row_l >= 0 && src_row_l <= stretch_height) {
+ int pos_pixel[8];
+ int u_w[4], v_w[4];
+ if (src_col_l == stretch_width) {
+ src_col_l--;
+ }
+ if (src_row_l == stretch_height) {
+ src_row_l--;
+ }
+ bicubic_get_pos_weight(pos_pixel, u_w, v_w, src_col_l, src_row_l,
+ res_x, res_y, stretch_width,
+ stretch_height);
+ uint8_t r_pos_red_y_r =
+ bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel, u_w,
+ v_w, res_x, res_y, Bpp, 2);
+ uint8_t r_pos_green_m_r =
+ bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel, u_w,
+ v_w, res_x, res_y, Bpp, 1);
+ uint8_t r_pos_blue_c_r =
+ bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel, u_w,
+ v_w, res_x, res_y, Bpp, 0);
+ if (bHasAlpha) {
+ if (transformF != FXDIB_Argb) {
+ if (transformF == FXDIB_Rgba) {
+ dest_pos[0] = r_pos_blue_c_r;
+ dest_pos[1] = r_pos_green_m_r;
+ dest_pos[2] = r_pos_red_y_r;
+ } else {
+ r_pos_k_r =
+ bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel,
+ u_w, v_w, res_x, res_y, Bpp, 3);
+ *(FX_DWORD*)dest_pos =
+ FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r,
+ r_pos_red_y_r, r_pos_k_r));
+ }
+ } else {
+ uint8_t r_pos_a_r =
+ bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel,
+ u_w, v_w, res_x, res_y, Bpp, 3);
+ *(FX_DWORD*)dest_pos = FXARGB_TODIB(
+ FXARGB_MAKE(r_pos_a_r, r_pos_red_y_r, r_pos_green_m_r,
+ r_pos_blue_c_r));
+ }
+ } else {
+ r_pos_k_r = 0xff;
+ if (transformF == FXDIB_Cmyka) {
+ r_pos_k_r =
+ bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel,
+ u_w, v_w, res_x, res_y, Bpp, 3);
+ *(FX_DWORD*)dest_pos =
+ FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r,
+ r_pos_red_y_r, r_pos_k_r));
+ } else {
+ *(FX_DWORD*)dest_pos = FXARGB_TODIB(
+ FXARGB_MAKE(r_pos_k_r, r_pos_red_y_r, r_pos_green_m_r,
+ r_pos_blue_c_r));
+ }
+ }
+ }
+ dest_pos += destBpp;
+ }
+ }
+ } else {
+ CPDF_FixedMatrix result2stretch_fix(result2stretch, 8);
+ for (int row = 0; row < m_ResultHeight; row++) {
+ uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
+ for (int col = 0; col < m_ResultWidth; col++) {
+ int src_col, src_row;
+ result2stretch_fix.Transform(col, row, src_col, src_row);
+ if (src_col >= 0 && src_col <= stretch_width && src_row >= 0 &&
+ src_row <= stretch_height) {
+ if (src_col == stretch_width) {
+ src_col--;
+ }
+ if (src_row == stretch_height) {
+ src_row--;
+ }
+ const uint8_t* src_pos =
+ stretch_buf + src_row * stretch_pitch + src_col * Bpp;
+ if (bHasAlpha) {
+ if (transformF != FXDIB_Argb) {
+ if (transformF == FXDIB_Rgba) {
+ dest_pos[0] = src_pos[0];
+ dest_pos[1] = src_pos[1];
+ dest_pos[2] = src_pos[2];
+ } else {
+ *(FX_DWORD*)dest_pos = FXCMYK_TODIB(CmykEncode(
+ src_pos[0], src_pos[1], src_pos[2], src_pos[3]));
+ }
+ } else {
+ *(FX_DWORD*)dest_pos = FXARGB_TODIB(FXARGB_MAKE(
+ src_pos[3], src_pos[2], src_pos[1], src_pos[0]));
+ }
+ } else {
+ if (transformF == FXDIB_Cmyka) {
+ *(FX_DWORD*)dest_pos = FXCMYK_TODIB(CmykEncode(
+ src_pos[0], src_pos[1], src_pos[2], src_pos[3]));
+ } else {
+ *(FX_DWORD*)dest_pos = FXARGB_TODIB(
+ FXARGB_MAKE(0xff, src_pos[2], src_pos[1], src_pos[0]));
+ }
+ }
+ }
+ dest_pos += destBpp;
+ }
+ }
+ }
+ }
+ }
+ m_Storer.Replace(pTransformed);
+ return FALSE;
+}