aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/gfx/gfx_pixmap_scale.cpp
diff options
context:
space:
mode:
authorEugene Sandulenko2009-02-15 11:39:07 +0000
committerEugene Sandulenko2009-02-15 11:39:07 +0000
commite241843bec22600ab4ef98e7a085e82aac73fc93 (patch)
tree61a793884d3462e1feb80e80f202d8816d0c8ec4 /engines/sci/gfx/gfx_pixmap_scale.cpp
parente9f742806362a84ffdb176a7414318dd2ab4df89 (diff)
downloadscummvm-rg350-e241843bec22600ab4ef98e7a085e82aac73fc93.tar.gz
scummvm-rg350-e241843bec22600ab4ef98e7a085e82aac73fc93.tar.bz2
scummvm-rg350-e241843bec22600ab4ef98e7a085e82aac73fc93.zip
- Remove some unneeded files
- Mass rename .c to .cpp svn-id: r38227
Diffstat (limited to 'engines/sci/gfx/gfx_pixmap_scale.cpp')
-rw-r--r--engines/sci/gfx/gfx_pixmap_scale.cpp497
1 files changed, 497 insertions, 0 deletions
diff --git a/engines/sci/gfx/gfx_pixmap_scale.cpp b/engines/sci/gfx/gfx_pixmap_scale.cpp
new file mode 100644
index 0000000000..0edd0365c8
--- /dev/null
+++ b/engines/sci/gfx/gfx_pixmap_scale.cpp
@@ -0,0 +1,497 @@
+/* Required defines:
+** FUNCNAME: Function name
+** SIZETYPE: Type used for each pixel
+** EXTRA_BYTE_OFFSET: Extra source byte offset for copying (used on big-endian machines in 24 bit mode)
+*/
+
+/* set optimisations for Win32: */
+/* g on: enable global optimizations */
+/* t on: use fast code */
+/* y on: suppress creation of frame pointers on stack */
+/* s off: disable minimize size code */
+#ifdef _WIN32
+# include <memory.h>
+# ifndef SATISFY_PURIFY
+# pragma optimize( "s", off )
+# pragma optimize( "gty", on )
+# pragma intrinsic( memcpy, memset )
+# endif
+#endif
+
+#include "sci/include/sci_memory.h"
+
+#define EXTEND_COLOR(x) (unsigned) ((((unsigned) x) << 24) | (((unsigned) x) << 16) | (((unsigned) x) << 8) | ((unsigned) x))
+#define PALETTE_MODE mode->palette
+
+void
+FUNCNAME(gfx_mode_t *mode, gfx_pixmap_t *pxm, int scale)
+{
+ SIZETYPE result_colors[GFX_PIC_COLORS];
+ SIZETYPE alpha_color = 0xffffffff & mode->alpha_mask;
+ SIZETYPE alpha_ormask = 0;
+ int xfact = (scale)? mode->xfact: 1;
+ int yfact = (scale)? mode->yfact: 1;
+ int widthc, heightc; /* Width duplication counter */
+ int line_width = xfact * pxm->index_xl;
+ int bytespp = mode->bytespp;
+ int x, y;
+ int i;
+ byte byte_transparent = (mode->flags & GFX_MODE_FLAG_REVERSE_ALPHA)? 0 : 255;
+ byte byte_opaque = (mode->flags & GFX_MODE_FLAG_REVERSE_ALPHA)? 255 : 0;
+ byte *src = pxm->index_data;
+ byte *dest = pxm->data;
+ byte *alpha_dest = pxm->alpha_map;
+ int using_alpha = pxm->color_key != GFX_PIXMAP_COLOR_KEY_NONE;
+ int separate_alpha_map = (!mode->alpha_mask) && using_alpha;
+
+ if (mode->flags & GFX_MODE_FLAG_REVERSE_ALPHA) {
+ alpha_ormask = alpha_color;
+ alpha_color = 0;
+ }
+
+ assert(bytespp == COPY_BYTES);
+
+ if (separate_alpha_map && !alpha_dest)
+ alpha_dest = pxm->alpha_map = (byte*)sci_malloc(pxm->index_xl * xfact * pxm->index_yl * yfact);
+
+ /* Calculate all colors */
+ for (i = 0; i < pxm->colors_nr; i++) {
+ int col;
+
+ if (PALETTE_MODE)
+ col = pxm->colors[i].global_index;
+ else {
+ col = mode->red_mask & ((EXTEND_COLOR(pxm->colors[i].r)) >> mode->red_shift);
+ col |= mode->green_mask & ((EXTEND_COLOR(pxm->colors[i].g)) >> mode->green_shift);
+ col |= mode->blue_mask & ((EXTEND_COLOR(pxm->colors[i].b)) >> mode->blue_shift);
+ col |= alpha_ormask;
+ }
+ result_colors[i] = col;
+ }
+
+ if (!separate_alpha_map && pxm->color_key != GFX_PIXMAP_COLOR_KEY_NONE)
+ result_colors[pxm->color_key] = alpha_color;
+
+ src = pxm->index_data; /* Workaround for gcc 4.2.3 bug on EMT64 */
+ for (y = 0; y < pxm->index_yl; y++) {
+ byte *prev_dest = dest;
+ byte *prev_alpha_dest = alpha_dest;
+
+ for (x = 0; x < pxm->index_xl; x++) {
+ int isalpha;
+ SIZETYPE col = result_colors[isalpha = *src++] << (EXTRA_BYTE_OFFSET * 8);
+ isalpha = (isalpha == pxm->color_key) && using_alpha;
+
+ /* O(n) loops. There is an O(ln(n)) algorithm for this, but its slower for small n (which we're optimizing for here).
+ ** And, anyway, most of the time is spent in memcpy() anyway. */
+
+ for (widthc = 0; widthc < xfact; widthc++) {
+ memcpy(dest, &col, COPY_BYTES);
+ dest += COPY_BYTES;
+ }
+
+ if (separate_alpha_map) { /* Set separate alpha map */
+ memset(alpha_dest, (isalpha)? byte_transparent : byte_opaque, xfact);
+ alpha_dest += xfact;
+ }
+ }
+
+ /* Copies each line. O(n) iterations; again, this could be optimized to O(ln(n)) for very high resolutions,
+ ** but that wouldn't really help that much, as the same amount of data still would have to be transferred.
+ */
+ for (heightc = 1; heightc < yfact; heightc++) {
+ memcpy(dest, prev_dest, line_width * bytespp);
+ dest += line_width * bytespp;
+ if (separate_alpha_map) {
+ memcpy(alpha_dest, prev_alpha_dest, line_width);
+ alpha_dest += line_width;
+ }
+ }
+ }
+}
+
+
+
+
+/* linear filter: Macros (in reverse order) */
+
+#define X_CALC_INTENSITY_NORMAL (ctexel[i] << 16) + ((linecolor[i])*(256-column_valuator)) + ((othercolumn[i]*column_valuator))*(256-line_valuator)
+#define X_CALC_INTENSITY_CENTER (ctexel[i] << 16) + ((linecolor[i])*(256-column_valuator))
+
+#define WRITE_XPART(X_CALC_INTENSITY, DO_X_STEP) \
+ for (subx = 0; subx < ((DO_X_STEP)? (xfact >> 1) : 1); subx++) { \
+ unsigned int intensity; \
+ wrcolor = 0; \
+ for (i = 0; i < 3; i++) { \
+ intensity = X_CALC_INTENSITY; \
+ wrcolor |= (intensity >> shifts[i]) & masks[i]; \
+ } \
+ i = 3; \
+ intensity = X_CALC_INTENSITY; \
+ if (inverse_alpha) \
+ intensity = ~intensity; \
+ wrcolor |= (intensity >> shifts[i]) & masks[i]; \
+ if (separate_alpha_map) \
+ *alpha_wrpos++ = intensity >> 24; \
+ wrcolor <<= (EXTRA_BYTE_OFFSET * 8); \
+ memcpy(wrpos, &wrcolor, COPY_BYTES); \
+ wrpos += COPY_BYTES; \
+ if (DO_X_STEP) \
+ column_valuator -= column_step; \
+ } \
+ if (DO_X_STEP) \
+ column_step = -column_step
+/* End of macro definition */
+
+
+#define Y_CALC_INTENSITY_CENTER 0
+#define Y_CALC_INTENSITY_NORMAL otherline[i]*line_valuator
+
+#define WRITE_YPART(DO_Y_STEP, LINE_COLOR) \
+ for (suby = 0; suby < ((DO_Y_STEP)? yfact >> 1 : 1); suby++) { \
+ int column_valuator = column_step? 128 - (column_step >> 1) : 256; \
+ int linecolor[4]; \
+ int othercolumn[4]; \
+ int i; \
+ SIZETYPE wrcolor; \
+ wrpos = sublinepos; \
+ alpha_wrpos = alpha_sublinepos; \
+ for (i = 0; i < 4; i++) \
+ linecolor[i] = LINE_COLOR; \
+ /*-- left half --*/ \
+ MAKE_PIXEL((x == 0), othercolumn, ctexel, src[-1]); \
+ WRITE_XPART(X_CALC_INTENSITY_NORMAL, 1); \
+ column_valuator -= column_step; \
+ /*-- center --*/ \
+ if (xfact & 1) { \
+ WRITE_XPART(X_CALC_INTENSITY_CENTER, 0); \
+ } \
+ /*-- right half --*/ \
+ MAKE_PIXEL((x+1 == pxm->index_xl), othercolumn, ctexel, src[+1]); \
+ WRITE_XPART(X_CALC_INTENSITY_NORMAL, 1); \
+ if (DO_Y_STEP) \
+ line_valuator -= line_step; \
+ sublinepos += pxm->xl * bytespp; \
+ alpha_sublinepos += pxm->xl; \
+ } \
+ if (DO_Y_STEP) \
+ line_step = -line_step
+/* End of macro definition */
+
+
+
+
+void
+FUNCNAME_LINEAR(gfx_mode_t *mode, gfx_pixmap_t *pxm, int scale)
+{
+ int xfact = mode->xfact;
+ int yfact = mode->yfact;
+ int line_step = (yfact < 2)? 0 : 256 / (yfact & ~1);
+ int column_step = (xfact < 2)? 0 : 256 / (xfact & ~1);
+ int bytespp = mode->bytespp;
+ byte *src = pxm->index_data;
+ byte *dest = pxm->data;
+ byte *alpha_dest = pxm->alpha_map;
+ int using_alpha = pxm->color_key != GFX_PIXMAP_COLOR_KEY_NONE;
+ int separate_alpha_map = (!mode->alpha_mask) && using_alpha;
+ unsigned int masks[4], shifts[4], zero[3];
+ int x,y;
+ byte inverse_alpha = mode->flags & GFX_MODE_FLAG_REVERSE_ALPHA;
+
+ zero[0] = 255;
+ zero[1] = zero[2] = 0;
+
+ if (separate_alpha_map) {
+ masks[3] = 0;
+ shifts[3] = 24;
+ }
+
+ assert(bytespp == COPY_BYTES);
+ assert(!PALETTE_MODE);
+
+ masks[0] = mode->red_mask;
+ masks[1] = mode->green_mask;
+ masks[2] = mode->blue_mask;
+ masks[3] = mode->alpha_mask;
+ shifts[0] = mode->red_shift;
+ shifts[1] = mode->green_shift;
+ shifts[2] = mode->blue_shift;
+ shifts[3] = mode->alpha_shift;
+
+ if (separate_alpha_map && !alpha_dest)
+ alpha_dest = pxm->alpha_map = (byte*)sci_malloc(pxm->index_xl * xfact * pxm->index_yl * yfact);
+
+ for (y = 0; y < pxm->index_yl; y++) {
+ byte *linepos = dest;
+ byte *alpha_linepos = alpha_dest;
+
+ for (x = 0; x < pxm->index_xl; x++) {
+ int otherline[4]; /* the above line or the line below */
+ int ctexel[4]; /* Current texel */
+ int subx, suby;
+ int line_valuator = line_step? 128 - (line_step >> 1) : 256;
+ byte *wrpos, *alpha_wrpos;
+ byte *sublinepos = linepos;
+ byte *alpha_sublinepos = alpha_linepos;
+
+ ctexel[0] = ctexel[1] = ctexel[2] = ctexel[3] = 0;
+
+#define MAKE_PIXEL(cond, rec, other, nr) \
+ if ((cond) || (using_alpha && nr == pxm->color_key)) { \
+ rec[0] = other[0] - ctexel[0]; \
+ rec[1] = other[1] - ctexel[1]; \
+ rec[2] = other[2] - ctexel[2]; \
+ rec[3] = 0xffff - ctexel[3]; \
+ } else { \
+ rec[0] = (EXTEND_COLOR(pxm->colors[nr].r) >> 16) - ctexel[0]; \
+ rec[1] = (EXTEND_COLOR(pxm->colors[nr].g) >> 16) - ctexel[1]; \
+ rec[2] = (EXTEND_COLOR(pxm->colors[nr].b) >> 16) - ctexel[2]; \
+ rec[3] = 0 - ctexel[3]; \
+ }
+
+ MAKE_PIXEL(0, ctexel, zero, *src);
+
+ /*-- Upper half --*/
+ MAKE_PIXEL((y == 0), otherline, ctexel, src[-pxm->index_xl]);
+ WRITE_YPART(1, Y_CALC_INTENSITY_NORMAL);
+
+ if (yfact & 1) {
+ WRITE_YPART(0, Y_CALC_INTENSITY_CENTER);
+ }
+
+ /*-- Lower half --*/
+ line_valuator -= line_step;
+ MAKE_PIXEL((y+1 == pxm->index_yl), otherline, ctexel, src[pxm->index_xl]);
+ WRITE_YPART(1, Y_CALC_INTENSITY_NORMAL);
+
+ src++;
+ linepos += xfact * bytespp;
+ alpha_linepos += xfact;
+ }
+
+ dest += pxm->xl * yfact * bytespp;
+ alpha_dest += pxm->xl * yfact;
+ }
+}
+
+
+
+/*----------------------*/
+/*** Trilinear filter ***/
+/*----------------------*/
+
+
+#ifndef GFX_GET_PIXEL_DELTA
+#define GFX_GET_PIXEL_DELTA
+static inline void
+gfx_get_pixel_delta(unsigned int *color, int *delta, unsigned int *pixel0, unsigned int *pixel1)
+{
+ int j;
+ int transp0 = pixel0[3] == 0xffffff;
+ int transp1 = pixel1[3] == 0xffffff;
+
+ if (transp0 && !transp1) { /* Transparent -> Opaque */
+ memset(delta, 0, sizeof(int) * 3);
+ delta[3] = ((pixel1[3] >> 8) - (pixel0[3] >> 8));
+ memcpy(color, pixel1, sizeof(int) * 3);
+ color[3] = 0xffffff;
+ } else if (!transp0 && transp1) { /* Opaque -> Transparent */
+ memset(delta, 0, sizeof(int) * 3);
+ delta[3] = ((pixel1[3] >> 8) - (pixel0[3] >> 8));
+ memcpy(color, pixel0, sizeof(int) * 4);
+ } else if (transp0 && transp1) { /* Transparent */
+ delta[3] = 0;
+ color[3] = 0xffffff;
+ } else { /* Opaque */
+ memcpy(color, pixel0, sizeof(int) * 4);
+ for (j = 0; j < 4; j++)
+ delta[j] = ((pixel1[j] >> 8) - (pixel0[j] >> 8));
+ }
+}
+
+
+static inline void
+gfx_apply_delta(unsigned int *color, int *delta, int factor)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ color[i] += delta[i] * factor;
+}
+#endif
+
+#define MAKE_PIXEL_TRILINEAR(cond, rec, nr) \
+ if (!(cond) || (using_alpha && nr == pxm->color_key)) { \
+ rec[0] = 0; \
+ rec[1] = 0; \
+ rec[2] = 0; \
+ rec[3] = 0xffffff; \
+ } else { \
+ rec[0] = (EXTEND_COLOR(pxm->colors[nr].r) >> 8); \
+ rec[1] = (EXTEND_COLOR(pxm->colors[nr].g) >> 8); \
+ rec[2] = (EXTEND_COLOR(pxm->colors[nr].b) >> 8); \
+ rec[3] = 0; \
+ }
+
+#define REVERSE_ALPHA(foo) ((inverse_alpha)? ~(foo) : (foo))
+
+void
+FUNCNAME_TRILINEAR(gfx_mode_t *mode, gfx_pixmap_t *pxm, int scale)
+{
+ int xfact = mode->xfact;
+ int yfact = mode->yfact;
+ int line_step = (yfact < 2)? 0 : 256 / yfact;
+ int column_step = (xfact < 2)? 0 : 256 / xfact;
+ int bytespp = mode->bytespp;
+ byte *src = pxm->index_data;
+ byte *dest = pxm->data;
+ byte *alpha_dest = pxm->alpha_map;
+ int using_alpha = pxm->color_key != GFX_PIXMAP_COLOR_KEY_NONE;
+ int separate_alpha_map = (!mode->alpha_mask) && using_alpha;
+ unsigned int masks[4], shifts[4];
+ unsigned int pixels[4][4];
+ /* 0 1
+ ** 2 3 */
+ int x,y;
+ byte inverse_alpha = mode->flags & GFX_MODE_FLAG_REVERSE_ALPHA;
+
+ if (separate_alpha_map) {
+ masks[3] = 0;
+ shifts[3] = 24;
+ }
+
+ assert(bytespp == COPY_BYTES);
+ assert(!PALETTE_MODE);
+
+ masks[0] = mode->red_mask;
+ masks[1] = mode->green_mask;
+ masks[2] = mode->blue_mask;
+ masks[3] = mode->alpha_mask;
+ shifts[0] = mode->red_shift;
+ shifts[1] = mode->green_shift;
+ shifts[2] = mode->blue_shift;
+ shifts[3] = mode->alpha_shift;
+
+ if (!(pxm->index_xl && pxm->index_yl))
+ return; /* Duh. */
+
+ if (separate_alpha_map && !alpha_dest)
+ alpha_dest = pxm->alpha_map = (byte*)sci_malloc(pxm->index_xl * xfact * pxm->index_yl * yfact);
+
+ src -= pxm->index_xl + 1;
+
+ for (y = 0; y <= pxm->index_yl; y++) {
+ byte *y_dest_backup = dest;
+ byte *y_alpha_dest_backup = alpha_dest;
+ int y_valuator = (y > 0)? 0 : 128;
+ int yc_count;
+
+
+ if (y == 0)
+ yc_count = yfact >> 1;
+ else if (y == pxm->index_yl)
+ yc_count = (yfact + 1) >> 1;
+ else
+ yc_count = yfact;
+
+ if (yfact & 1)
+ y_valuator += line_step >> 1;
+
+ for (x = 0; x <= pxm->index_xl; x++) {
+ byte *x_dest_backup = dest;
+ byte *x_alpha_dest_backup = alpha_dest;
+ int x_valuator = (x > 0)? 0 : 128;
+ int xc_count;
+ unsigned int leftcolor[4], rightcolor[4];
+ int leftdelta[4], rightdelta[4];
+ int xc, yc;
+
+ if (x == 0)
+ xc_count = xfact >> 1;
+ else if (x == pxm->index_xl)
+ xc_count = (xfact + 1) >> 1;
+ else
+ xc_count = xfact;
+
+ if (xfact & 1)
+ x_valuator += column_step >> 1;
+
+ MAKE_PIXEL_TRILINEAR((y && x), pixels[0], *src);
+ MAKE_PIXEL_TRILINEAR((y && (x < pxm->index_xl)), pixels[1], src[1]);
+ MAKE_PIXEL_TRILINEAR(((y < pxm->index_yl) && x), pixels[2], src[pxm->index_xl]);
+ MAKE_PIXEL_TRILINEAR(((y < pxm->index_yl) && (x < pxm->index_xl)),
+ pixels[3], src[pxm->index_xl + 1]);
+
+ /* OptimizeMe */
+
+ gfx_get_pixel_delta(leftcolor, leftdelta, pixels[0], pixels[2]);
+ gfx_get_pixel_delta(rightcolor, rightdelta, pixels[1], pixels[3]);
+ gfx_apply_delta(leftcolor, leftdelta, y_valuator);
+ gfx_apply_delta(rightcolor, rightdelta, y_valuator);
+
+ for (yc = 0; yc < yc_count; yc++) {
+ unsigned int color[4];
+ int delta[4];
+ byte *yc_dest_backup = dest;
+ byte *yc_alpha_dest_backup = alpha_dest;
+
+ gfx_get_pixel_delta(color, delta, leftcolor, rightcolor);
+
+ gfx_apply_delta(color, delta, x_valuator);
+
+ for (xc = 0; xc < xc_count; xc++) {
+ SIZETYPE wrcolor;
+ int i;
+ wrcolor = 0;
+
+ for (i = 0; i < 3; i++)
+ wrcolor |= ((color[i] << 8) >> shifts[i]) & masks[i];
+
+ if (separate_alpha_map) {
+ *alpha_dest++ = REVERSE_ALPHA(color[3] >> 16);
+ } else
+ wrcolor |= REVERSE_ALPHA((color[3] << 8) >> shifts[3]) & masks[3];
+
+ wrcolor <<= (EXTRA_BYTE_OFFSET * 8);
+
+ memcpy(dest, &wrcolor, COPY_BYTES);
+ dest += COPY_BYTES;
+ gfx_apply_delta(color, delta, column_step);
+ }
+ gfx_apply_delta(leftcolor, leftdelta, line_step);
+ gfx_apply_delta(rightcolor, rightdelta, line_step);
+
+ dest = yc_dest_backup + pxm->index_xl * xfact * COPY_BYTES;
+ alpha_dest = yc_alpha_dest_backup + pxm->index_xl * xfact;
+ }
+
+ dest = x_dest_backup + xc_count * COPY_BYTES;
+ alpha_dest = x_alpha_dest_backup + xc_count;
+
+ if (x < pxm->index_xl)
+ src++;
+ }
+ dest = y_dest_backup + pxm->index_xl * xfact * yc_count * COPY_BYTES;
+ alpha_dest = y_alpha_dest_backup + pxm->index_xl * xfact * yc_count;
+ }
+}
+
+#undef REVERSE_ALPHA
+#undef WRITE_YPART
+#undef Y_CALC_INTENSITY_CENTER
+#undef Y_CALC_INTENSITY_NORMAL
+#undef WRITE_XPART
+#undef X_CALC_INTENSITY_CENTER
+#undef X_CALC_INTENSITY_NORMAL
+#undef MAKE_PIXEL_TRILINEAR
+#undef MAKE_PIXEL
+#undef FUNCNAME
+#undef FUNCNAME_LINEAR
+#undef FUNCNAME_TRILINEAR
+#undef SIZETYPE
+#undef EXTEND_COLOR
+
+/* reset to original optimisations for Win32: */
+/* (does not reset intrinsics) */
+#ifdef _WIN32
+# pragma optimize( "", on )
+#endif