913 lines
23 KiB
C++
913 lines
23 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "common/textconsole.h"
|
|
#include "graphics/managed_surface.h"
|
|
|
|
#include "qdengine/qdengine.h"
|
|
#include "qdengine/qd_fwd.h"
|
|
#include "qdengine/system/graphics/gr_dispatcher.h"
|
|
#include "qdengine/system/graphics/rle_compress.h"
|
|
|
|
|
|
namespace QDEngine {
|
|
|
|
void grDispatcher::putSpr_rle(int x, int y, int sx, int sy, const class RLEBuffer *p, int mode, bool alpha_flag) {
|
|
debugC(4, kDebugGraphics, "grDispatcher::putSpr_rle([%d, %d], [%d, %d], mode: %d, alpha: %d", x, y, sx, sy, mode, alpha_flag);
|
|
|
|
int px = 0;
|
|
int py = 0;
|
|
|
|
int psx = sx;
|
|
int psy = sy;
|
|
|
|
if (!clip_rectangle(x, y, px, py, psx, psy)) return;
|
|
int dx = -2;
|
|
int dy = -1;
|
|
|
|
if (mode & GR_FLIP_HORIZONTAL) {
|
|
x += (psx - 1);
|
|
px = sx - px - psx;
|
|
} else
|
|
dx = 2;
|
|
|
|
if (_pixel_format == GR_RGBA8888)
|
|
dx *= 2;
|
|
|
|
psx += px;
|
|
|
|
if (mode & GR_FLIP_VERTICAL) {
|
|
y += psy - 1;
|
|
py = sy - py - psy;
|
|
} else
|
|
dy = 1;
|
|
|
|
for (int i = 0; i < psy; i++) {
|
|
byte *scr_buf = reinterpret_cast<byte *>(_screenBuf->getBasePtr(x, y));
|
|
|
|
const int8 *rle_header = p->header_ptr(py + i);
|
|
const uint32 *rle_data = p->data_ptr(py + i);
|
|
|
|
int j = 0;
|
|
int8 count = 0;
|
|
while (j < px) {
|
|
count = *rle_header++;
|
|
if (count > 0) {
|
|
if (count + j <= px) {
|
|
j += count;
|
|
rle_data++;
|
|
count = 0;
|
|
} else {
|
|
count -= px - j;
|
|
j = px;
|
|
}
|
|
} else {
|
|
if (j - count <= px) {
|
|
j -= count;
|
|
rle_data -= count;
|
|
count = 0;
|
|
} else {
|
|
count += px - j;
|
|
rle_data += px - j;
|
|
j = px;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!alpha_flag) {
|
|
while (j < psx) {
|
|
if (count > 0) {
|
|
while (count && j < psx) {
|
|
if (*rle_data) {
|
|
const byte *rle_buf = (const byte *)rle_data;
|
|
uint32 cl = make_rgb(rle_buf[2], rle_buf[1], rle_buf[0]);
|
|
setPixelFast(scr_buf, cl);
|
|
}
|
|
scr_buf += dx;
|
|
count--;
|
|
j++;
|
|
}
|
|
rle_data++;
|
|
} else {
|
|
if (count < 0) {
|
|
count = -count;
|
|
while (count && j < psx) {
|
|
if (*rle_data) {
|
|
const byte *rle_buf = (const byte *)rle_data;
|
|
uint32 cl = make_rgb(rle_buf[2], rle_buf[1], rle_buf[0]);
|
|
setPixelFast(scr_buf, cl);
|
|
}
|
|
scr_buf += dx;
|
|
rle_data++;
|
|
count--;
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
count = *rle_header++;
|
|
}
|
|
} else {
|
|
while (j < psx) {
|
|
if (count > 0) {
|
|
while (count && j < psx) {
|
|
const byte *rle_buf = (const byte *)rle_data;
|
|
uint32 a = rle_buf[3];
|
|
if (_pixel_format == GR_RGB565) {
|
|
*(uint16 *)scr_buf = alpha_blend_565(make_rgb565u(rle_buf[2], rle_buf[1], rle_buf[0]), *(uint16 *)scr_buf, a);
|
|
} else {
|
|
if (a != 255) {
|
|
scr_buf[1] = rle_buf[0] + ((a * scr_buf[1]) >> 8);
|
|
scr_buf[2] = rle_buf[1] + ((a * scr_buf[2]) >> 8);
|
|
scr_buf[3] = rle_buf[2] + ((a * scr_buf[3]) >> 8);
|
|
}
|
|
}
|
|
scr_buf += dx;
|
|
count--;
|
|
j++;
|
|
}
|
|
rle_data++;
|
|
} else {
|
|
if (count < 0) {
|
|
count = -count;
|
|
while (count && j < psx) {
|
|
const byte *rle_buf = (const byte *)rle_data;
|
|
uint32 a = rle_buf[3];
|
|
if (_pixel_format == GR_RGB565) {
|
|
*(uint16 *)scr_buf = alpha_blend_565(make_rgb565u(rle_buf[2], rle_buf[1], rle_buf[0]), *(uint16 *)scr_buf, a);
|
|
} else {
|
|
if (a != 255) {
|
|
scr_buf[1] = rle_buf[0] + ((a * scr_buf[1]) >> 8);
|
|
scr_buf[2] = rle_buf[1] + ((a * scr_buf[2]) >> 8);
|
|
scr_buf[3] = rle_buf[2] + ((a * scr_buf[3]) >> 8);
|
|
}
|
|
}
|
|
scr_buf += dx;
|
|
rle_data++;
|
|
count--;
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
count = *rle_header++;
|
|
}
|
|
}
|
|
y += dy;
|
|
}
|
|
}
|
|
|
|
void grDispatcher::putSpr_rle(int x, int y, int sx, int sy, const class RLEBuffer *p, int mode, float scale, bool alpha_flag) {
|
|
debugC(4, kDebugGraphics, "grDispatcher::putSpr_rle([%d, %d], [%d, %d], mode: %d, scale: %f, alpha: %d", x, y, sx, sy, mode, scale, alpha_flag);
|
|
|
|
int sx_dest = round(float(sx) * scale);
|
|
int sy_dest = round(float(sy) * scale);
|
|
|
|
if (sx_dest <= 0 || sy_dest <= 0) return;
|
|
|
|
int dx = (sx << 16) / sx_dest;
|
|
int dy = (sy << 16) / sy_dest;
|
|
int fx = (1 << 15);
|
|
int fy = (1 << 15);
|
|
|
|
int x0 = 0;
|
|
int x1 = sx_dest - 1;
|
|
int ix = 1;
|
|
|
|
int y0 = 0;
|
|
int y1 = sy_dest - 1;
|
|
int iy = 1;
|
|
|
|
if (mode & GR_FLIP_VERTICAL) {
|
|
y0 = sy_dest - 1,
|
|
y1 = 0;
|
|
iy = -1;
|
|
}
|
|
|
|
if (mode & GR_FLIP_HORIZONTAL) {
|
|
x0 = sx_dest - 1,
|
|
x1 = 0;
|
|
ix = -1;
|
|
}
|
|
if (!alpha_flag) {
|
|
const byte *line_src = RLEBuffer::get_buffer(0);
|
|
for (int i = y0; i != y1; i += iy) {
|
|
p->decode_line(fy >> 16);
|
|
|
|
fy += dy;
|
|
fx = (1 << 15);
|
|
|
|
for (int j = x0; j != x1; j += ix) {
|
|
if (clipCheck(x + j, y + i)) {
|
|
const byte *src_data = line_src + (fx >> 16) * 3;
|
|
if (src_data[0] || src_data[1] || src_data[2])
|
|
setPixelFast(x + j, y + i, make_rgb(src_data[2], src_data[1], src_data[0]));
|
|
}
|
|
fx += dx;
|
|
}
|
|
}
|
|
} else {
|
|
const byte *line_src = RLEBuffer::get_buffer(0);
|
|
for (int i = y0; i != y1; i += iy) {
|
|
p->decode_line(fy >> 16);
|
|
|
|
fy += dy;
|
|
fx = (1 << 15);
|
|
|
|
for (int j = x0; j != x1; j += ix) {
|
|
if (clipCheck(x + j, y + i)) {
|
|
const byte *src_data = line_src + ((fx >> 16) << 2);
|
|
|
|
uint32 a = src_data[3];
|
|
if (a != 255) {
|
|
if (_pixel_format == GR_RGB565) {
|
|
uint32 cl = make_rgb565u(src_data[2], src_data[1], src_data[0]);
|
|
|
|
if (a) {
|
|
uint16 scl;
|
|
getPixel(x + j, y + i, scl);
|
|
|
|
setPixelFast(x + j, y + i, alpha_blend_565(cl, scl, a));
|
|
} else
|
|
setPixelFast(x + j, y + i, cl);
|
|
} else {
|
|
byte sr, sg, sb;
|
|
getPixel(x + j, y + i, sr, sg, sb);
|
|
|
|
uint32 r = src_data[2] + ((a * sr) >> 8);
|
|
uint32 g = src_data[1] + ((a * sg) >> 8);
|
|
uint32 b = src_data[0] + ((a * sb) >> 8);
|
|
|
|
setPixelFast(x + j, y + i, r, g, b);
|
|
}
|
|
}
|
|
}
|
|
fx += dx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void grDispatcher::putSprMask_rle(int x, int y, int sx, int sy, const RLEBuffer *p, uint32 mask_color, int mask_alpha, int mode, bool alpha_flag) {
|
|
debugC(4, kDebugGraphics, "grDispatcher::putSprMask_rle([%d, %d], [%d, %d], ...)", x, y, sx, sy);
|
|
|
|
int px = 0;
|
|
int py = 0;
|
|
|
|
int psx = sx;
|
|
int psy = sy;
|
|
|
|
if (!clip_rectangle(x, y, px, py, psx, psy)) return;
|
|
|
|
int dx = -2;
|
|
int dy = -1;
|
|
|
|
if (mode & GR_FLIP_HORIZONTAL) {
|
|
x += (psx - 1);
|
|
px = sx - px - psx;
|
|
} else
|
|
dx = 2;
|
|
|
|
if (_pixel_format == GR_RGBA8888)
|
|
dx *= 2;
|
|
|
|
psx += px;
|
|
|
|
if (mode & GR_FLIP_VERTICAL) {
|
|
y += psy - 1;
|
|
py = sy - py - psy;
|
|
} else
|
|
dy = 1;
|
|
|
|
for (int i = 0; i < psy; i++) {
|
|
byte *scr_buf = reinterpret_cast<byte *>(_screenBuf->getBasePtr(x, y));
|
|
|
|
const int8 *rle_header = p->header_ptr(py + i);
|
|
const uint32 *rle_data = p->data_ptr(py + i);
|
|
|
|
int j = 0;
|
|
int8 count = 0;
|
|
while (j < px) {
|
|
count = *rle_header++;
|
|
if (count > 0) {
|
|
if (count + j <= px) {
|
|
j += count;
|
|
rle_data++;
|
|
count = 0;
|
|
} else {
|
|
count -= px - j;
|
|
j = px;
|
|
}
|
|
} else {
|
|
if (j - count <= px) {
|
|
j -= count;
|
|
rle_data -= count;
|
|
count = 0;
|
|
} else {
|
|
count += px - j;
|
|
rle_data += px - j;
|
|
j = px;
|
|
}
|
|
}
|
|
}
|
|
byte mr, mg, mb;
|
|
if (_pixel_format == GR_RGB565)
|
|
split_rgb565u(mask_color, mr, mg, mb);
|
|
else
|
|
split_rgb888(mask_color, mr, mg, mb);
|
|
|
|
if (!alpha_flag) {
|
|
mr = (mr * (255 - mask_alpha)) >> 8;
|
|
mg = (mg * (255 - mask_alpha)) >> 8;
|
|
mb = (mb * (255 - mask_alpha)) >> 8;
|
|
|
|
uint32 cl = make_rgb(mr, mg, mb);
|
|
|
|
while (j < psx) {
|
|
if (count > 0) {
|
|
while (count && j < psx) {
|
|
if (*rle_data) {
|
|
if (_pixel_format == GR_RGB565) {
|
|
setPixelFast(scr_buf, cl);
|
|
} else {
|
|
scr_buf[3] = mr + ((mask_alpha * scr_buf[3]) >> 8);
|
|
scr_buf[2] = mg + ((mask_alpha * scr_buf[2]) >> 8);
|
|
scr_buf[1] = mb + ((mask_alpha * scr_buf[1]) >> 8);
|
|
}
|
|
}
|
|
scr_buf += dx;
|
|
count--;
|
|
j++;
|
|
}
|
|
rle_data++;
|
|
} else {
|
|
if (count < 0) {
|
|
count = -count;
|
|
while (count && j < psx) {
|
|
if (*rle_data) {
|
|
if (_pixel_format == GR_RGB565) {
|
|
setPixelFast(scr_buf, cl);
|
|
} else {
|
|
scr_buf[3] = mr + ((mask_alpha * scr_buf[3]) >> 8);
|
|
scr_buf[2] = mg + ((mask_alpha * scr_buf[2]) >> 8);
|
|
scr_buf[1] = mb + ((mask_alpha * scr_buf[1]) >> 8);
|
|
}
|
|
}
|
|
scr_buf += dx;
|
|
rle_data++;
|
|
count--;
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
count = *rle_header++;
|
|
}
|
|
} else {
|
|
while (j < psx) {
|
|
if (count > 0) {
|
|
while (count && j < psx) {
|
|
const byte *rle_buf = (const byte *)rle_data;
|
|
uint32 a = rle_buf[3];
|
|
|
|
if (a != 255) {
|
|
a = mask_alpha + ((a * (255 - mask_alpha)) >> 8);
|
|
|
|
uint32 r = (mr * (255 - a)) >> 8;
|
|
uint32 g = (mg * (255 - a)) >> 8;
|
|
uint32 b = (mb * (255 - a)) >> 8;
|
|
|
|
if (_pixel_format == GR_RGB565) {
|
|
uint16 cl = make_rgb565u(r, g, b);
|
|
*(uint16 *)scr_buf = alpha_blend_565(cl, *(uint16 *)scr_buf, a);
|
|
} else {
|
|
scr_buf[1] = b + ((a * scr_buf[1]) >> 8);
|
|
scr_buf[2] = g + ((a * scr_buf[2]) >> 8);
|
|
scr_buf[3] = r + ((a * scr_buf[3]) >> 8);
|
|
}
|
|
}
|
|
|
|
scr_buf += dx;
|
|
count--;
|
|
j++;
|
|
}
|
|
rle_data++;
|
|
} else {
|
|
if (count < 0) {
|
|
count = -count;
|
|
while (count && j < psx) {
|
|
const byte *rle_buf = (const byte *)rle_data;
|
|
uint32 a = rle_buf[3];
|
|
|
|
if (a != 255) {
|
|
a = mask_alpha + ((a * (255 - mask_alpha)) >> 8);
|
|
|
|
uint32 r = (mr * (255 - a)) >> 8;
|
|
uint32 g = (mg * (255 - a)) >> 8;
|
|
uint32 b = (mb * (255 - a)) >> 8;
|
|
|
|
if (_pixel_format == GR_RGB565) {
|
|
uint16 cl = make_rgb565u(r, g, b);
|
|
*(uint16 *)scr_buf = alpha_blend_565(cl, *(uint16 *)scr_buf, a);
|
|
} else {
|
|
scr_buf[1] = b + ((a * scr_buf[1]) >> 8);
|
|
scr_buf[2] = g + ((a * scr_buf[2]) >> 8);
|
|
scr_buf[3] = r + ((a * scr_buf[3]) >> 8);
|
|
}
|
|
}
|
|
|
|
scr_buf += dx;
|
|
rle_data++;
|
|
count--;
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
count = *rle_header++;
|
|
}
|
|
}
|
|
y += dy;
|
|
}
|
|
}
|
|
|
|
void grDispatcher::putSprMask_rle(int x, int y, int sx, int sy, const RLEBuffer *p, uint32 mask_color, int mask_alpha, int mode, float scale, bool alpha_flag) {
|
|
debugC(4, kDebugGraphics, "grDispatcher::putSprMask_rle([%d, %d], [%d, %d], mask: %d, alpha: %d, mode: %d, scale: %f, alpha_flag: %d)", x, y, sx, sy, mask_color, mask_alpha, mode, scale, alpha_flag);
|
|
|
|
int sx_dest = round(float(sx) * scale);
|
|
int sy_dest = round(float(sy) * scale);
|
|
|
|
if (sx_dest <= 0 || sy_dest <= 0) return;
|
|
|
|
int dx = (sx << 16) / sx_dest;
|
|
int dy = (sy << 16) / sy_dest;
|
|
int fx = (1 << 15);
|
|
int fy = (1 << 15);
|
|
|
|
int x0 = 0;
|
|
int x1 = sx_dest - 1;
|
|
int ix = 1;
|
|
|
|
int y0 = 0;
|
|
int y1 = sy_dest - 1;
|
|
int iy = 1;
|
|
|
|
if (mode & GR_FLIP_VERTICAL) {
|
|
y0 = sy_dest - 1,
|
|
y1 = 0;
|
|
iy = -1;
|
|
}
|
|
|
|
if (mode & GR_FLIP_HORIZONTAL) {
|
|
x0 = sx_dest - 1,
|
|
x1 = 0;
|
|
ix = -1;
|
|
}
|
|
if (!alpha_flag) {
|
|
byte mr, mg, mb;
|
|
if (_pixel_format == GR_RGB565)
|
|
split_rgb565u(mask_color, mr, mg, mb);
|
|
else
|
|
split_rgb888(mask_color, mr, mg, mb);
|
|
|
|
mr = (mr * (255 - mask_alpha)) >> 8;
|
|
mg = (mg * (255 - mask_alpha)) >> 8;
|
|
mb = (mb * (255 - mask_alpha)) >> 8;
|
|
|
|
uint32 mcl = make_rgb(mr, mg, mb);
|
|
|
|
const byte *line_src = RLEBuffer::get_buffer(0);
|
|
|
|
for (int i = y0; i != y1; i += iy) {
|
|
p->decode_line(fy >> 16);
|
|
|
|
fy += dy;
|
|
fx = (1 << 15);
|
|
|
|
for (int j = x0; j != x1; j += ix) {
|
|
if (clipCheck(x + j, y + i)) {
|
|
const byte *src_buf = line_src + ((fx >> 16) << 2);
|
|
if (src_buf[0] || src_buf[1] || src_buf[2]) {
|
|
if (_pixel_format == GR_RGB565) {
|
|
uint16 scl;
|
|
getPixel(x + j, y + i, scl);
|
|
setPixelFast(x + j, y + i, alpha_blend_565(mcl, scl, mask_alpha));
|
|
} else {
|
|
byte sr, sg, sb;
|
|
getPixel(x + j, y + i, sr, sg, sb);
|
|
|
|
uint32 r = mr + ((mask_alpha * sr) >> 8);
|
|
uint32 g = mg + ((mask_alpha * sg) >> 8);
|
|
uint32 b = mb + ((mask_alpha * sb) >> 8);
|
|
|
|
setPixelFast(x + j, y + i, r, g, b);
|
|
}
|
|
}
|
|
}
|
|
fx += dx;
|
|
}
|
|
}
|
|
} else {
|
|
const byte *line_src = RLEBuffer::get_buffer(0);
|
|
byte mr, mg, mb;
|
|
if (_pixel_format == GR_RGB565)
|
|
split_rgb565u(mask_color, mr, mg, mb);
|
|
else
|
|
split_rgb888(mask_color, mr, mg, mb);
|
|
|
|
for (int i = y0; i != y1; i += iy) {
|
|
p->decode_line(fy >> 16);
|
|
|
|
fy += dy;
|
|
fx = (1 << 15);
|
|
|
|
for (int j = x0; j != x1; j += ix) {
|
|
if (clipCheck(x + j, y + i)) {
|
|
const byte *src_buf = line_src + ((fx >> 16) << 2);
|
|
uint32 a = src_buf[3];
|
|
if (a != 255) {
|
|
a = mask_alpha + ((a * (255 - mask_alpha)) >> 8);
|
|
|
|
uint32 r = (mr * (255 - a)) >> 8;
|
|
uint32 g = (mg * (255 - a)) >> 8;
|
|
uint32 b = (mb * (255 - a)) >> 8;
|
|
|
|
if (_pixel_format == GR_RGB565) {
|
|
uint16 scl;
|
|
getPixel(x + j, y + i, scl);
|
|
|
|
uint16 cl = make_rgb565u(r, g, b);
|
|
setPixelFast(x + j, y + i, alpha_blend_565(cl, scl, a));
|
|
} else {
|
|
byte sr, sg, sb;
|
|
getPixel(x + j, y + i, sr, sg, sb);
|
|
|
|
r = r + ((a * sr) >> 8);
|
|
g = g + ((a * sg) >> 8);
|
|
b = b + ((a * sb) >> 8);
|
|
|
|
setPixelFast(x + j, y + i, r, g, b);
|
|
}
|
|
}
|
|
}
|
|
fx += dx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void grDispatcher::putSpr_rle_rot(const Vect2i &pos, const Vect2i &size, const RLEBuffer *data, bool has_alpha, int mode, float angle) {
|
|
debugC(4, kDebugGraphics, "grDispatcher::putSpr_rle_rot([%d, %d], [%d, %d], alpha: %d, mode: %d, angle: %f", pos.x, pos.y, size.x, size.y, has_alpha, mode, angle);
|
|
|
|
byte *buf = (byte *)temp_buffer(size.x * size.y * 4);
|
|
|
|
byte *buf_ptr = buf;
|
|
for (int i = 0; i < size.y; i++) {
|
|
data->decode_line(i, buf_ptr);
|
|
buf_ptr += size.x * 4;
|
|
}
|
|
|
|
if (!has_alpha) {
|
|
uint32 *p = (uint32 *)buf;
|
|
buf_ptr = buf + 3;
|
|
for (int i = 0; i < size.y; i++) {
|
|
for (int j = 0; j < size.x; j++) {
|
|
if (!*p++)
|
|
*buf_ptr = 255;
|
|
|
|
buf_ptr += 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
putSpr_rot(pos, size, buf, true, mode, angle);
|
|
}
|
|
|
|
void grDispatcher::putSpr_rle_rot(const Vect2i &pos, const Vect2i &size, const RLEBuffer *data, bool has_alpha, int mode, float angle, const Vect2f &scale) {
|
|
debugC(4, kDebugGraphics, "grDispatcher::putSpr_rle_rot([%d, %d], [%d, %d], alpha: %d, mode: %d, angle: %f, scale: [%f, %f]", pos.x, pos.y, size.x, size.y, has_alpha, mode, angle, scale.x, scale.y);
|
|
|
|
byte *buf = (byte *)temp_buffer(size.x * size.y * 4);
|
|
|
|
byte *buf_ptr = buf;
|
|
for (int i = 0; i < size.y; i++) {
|
|
data->decode_line(i, buf_ptr);
|
|
buf_ptr += size.x * 4;
|
|
}
|
|
|
|
if (!has_alpha) {
|
|
uint32 *p = (uint32 *)buf;
|
|
buf_ptr = buf + 3;
|
|
for (int i = 0; i < size.y; i++) {
|
|
for (int j = 0; j < size.x; j++) {
|
|
if (!*p++)
|
|
*buf_ptr = 255;
|
|
|
|
buf_ptr += 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
putSpr_rot(pos, size, buf, true, mode, angle, scale);
|
|
}
|
|
|
|
void grDispatcher::putSprMask_rle_rot(const Vect2i &pos, const Vect2i &size, const RLEBuffer *data, bool has_alpha, uint32 mask_color, int mask_alpha, int mode, float angle) {
|
|
debugC(4, kDebugGraphics, "grDispatcher::putSpr_rle_rot([%d, %d], [%d, %d], alpha: %d, mask: %d, mask_alpha: %d, mode: %d, angle: %f", pos.x, pos.y, size.x, size.y, has_alpha, mask_color, mask_alpha, mode, angle);
|
|
|
|
byte *buf = (byte *)temp_buffer(size.x * size.y * 4);
|
|
|
|
byte *buf_ptr = buf;
|
|
for (int i = 0; i < size.y; i++) {
|
|
data->decode_line(i, buf_ptr);
|
|
buf_ptr += size.x * 4;
|
|
}
|
|
|
|
if (!has_alpha) {
|
|
uint32 *p = (uint32 *)buf;
|
|
buf_ptr = buf + 3;
|
|
for (int i = 0; i < size.y; i++) {
|
|
for (int j = 0; j < size.x; j++) {
|
|
if (!*p++)
|
|
*buf_ptr = 255;
|
|
|
|
buf_ptr += 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
putSprMask_rot(pos, size, buf, true, mask_color, mask_alpha, mode, angle);
|
|
}
|
|
|
|
void grDispatcher::putSprMask_rle_rot(const Vect2i &pos, const Vect2i &size, const RLEBuffer *data, bool has_alpha, uint32 mask_color, int mask_alpha, int mode, float angle, const Vect2f &scale) {
|
|
debugC(4, kDebugGraphics, "grDispatcher::putSpr_rle_rot([%d, %d], [%d, %d], alpha: %d, mask: %d, mask_alpha: %d, mode: %d, angle: %f, scale: [%f, %f]", pos.x, pos.y, size.x, size.y, has_alpha, mask_color, mask_alpha, mode, angle, scale.x, scale.y);
|
|
|
|
byte *buf = (byte *)temp_buffer(size.x * size.y * 4);
|
|
|
|
byte *buf_ptr = buf;
|
|
for (int i = 0; i < size.y; i++) {
|
|
data->decode_line(i, buf_ptr);
|
|
buf_ptr += size.x * 4;
|
|
}
|
|
|
|
if (!has_alpha) {
|
|
uint32 *p = (uint32 *)buf;
|
|
buf_ptr = buf + 3;
|
|
for (int i = 0; i < size.y; i++) {
|
|
for (int j = 0; j < size.x; j++) {
|
|
if (!*p++)
|
|
*buf_ptr = 255;
|
|
|
|
buf_ptr += 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
putSprMask_rot(pos, size, buf, true, mask_color, mask_alpha, mode, angle, scale);
|
|
}
|
|
|
|
inline bool rle_alpha_b(uint32 pixel) {
|
|
return (reinterpret_cast<byte *>(&pixel)[3] < 200);
|
|
}
|
|
inline bool rle_alpha_b16(uint16 pixel) {
|
|
return pixel < 200;
|
|
}
|
|
|
|
void grDispatcher::drawSprContour(int x, int y, int sx, int sy, const class RLEBuffer *p, int contour_color, int mode, bool alpha_flag) {
|
|
debugC(4, kDebugGraphics, "grDispatcher::drawSprContour([%d, %d], [%d, %d], contour_color: %d, mode: %d, alpha_flag: %d)", x, y, sx, sy, contour_color, mode, alpha_flag);
|
|
|
|
int px = 0;
|
|
int py = 0;
|
|
|
|
int psx = sx;
|
|
int psy = sy;
|
|
|
|
if (!clip_rectangle(x, y, px, py, psx, psy)) return;
|
|
int dx = -1;
|
|
int dy = -1;
|
|
|
|
if (mode & GR_FLIP_HORIZONTAL) {
|
|
x += (psx - 1) * 2;
|
|
px = sx - px - psx;
|
|
} else
|
|
dx = 1;
|
|
|
|
if (mode & GR_FLIP_VERTICAL) {
|
|
y += psy - 1;
|
|
py = sy - py - psy;
|
|
} else
|
|
dy = 1;
|
|
|
|
const uint16 *data0 = reinterpret_cast<const uint16 *>(RLEBuffer::get_buffer(0));
|
|
const uint16 *data1 = reinterpret_cast<const uint16 *>(RLEBuffer::get_buffer(1));
|
|
|
|
px <<= 1;
|
|
psx <<= 1;
|
|
|
|
warning("STUB: grDispatcher::drawSprContour");
|
|
for (int i = 0; i < psy; i++) {
|
|
uint16 *scr_buf = (uint16 *)_screenBuf->getBasePtr(x, y);
|
|
uint16 *scr_buf_prev = (i) ? (uint16 *)_screenBuf->getBasePtr(x, y - dy) : scr_buf;
|
|
p->decode_line(py + i, i & 1);
|
|
|
|
const uint16 *data_ptr = (i & 1) ? data1 + px : data0 + px;
|
|
const uint16 *data_ptr_prev = (i & 1) ? data0 + px : data1 + px;
|
|
|
|
if (!alpha_flag) {
|
|
uint32 pixel = 0;
|
|
for (int j = 0; j < psx; j += 2) {
|
|
pixel = data_ptr[j];
|
|
|
|
if (!pixel && j && data_ptr[j - 2]) {
|
|
*(scr_buf - dx) = contour_color;
|
|
}
|
|
if ((pixel && (!j || !data_ptr[j - 2]))) {
|
|
*scr_buf = contour_color;
|
|
} else {
|
|
if (pixel && (!i || !data_ptr_prev[j])) {
|
|
*scr_buf = contour_color;
|
|
}
|
|
}
|
|
if (!pixel && i && data_ptr_prev[j]) {
|
|
*scr_buf_prev = contour_color;
|
|
}
|
|
|
|
scr_buf += dx;
|
|
scr_buf_prev += dx;
|
|
}
|
|
if (pixel) *(scr_buf - dx) = contour_color;
|
|
} else {
|
|
bool pixel = false;
|
|
for (int j = 0; j < psx; j += 2) {
|
|
pixel = rle_alpha_b16(data_ptr[j + 1]);
|
|
|
|
if (!pixel && j && rle_alpha_b16(data_ptr[j - 1])) {
|
|
*(scr_buf - dx) = contour_color;
|
|
}
|
|
if ((pixel && (!j || !rle_alpha_b16(data_ptr[j - 1])))) {
|
|
*scr_buf = contour_color;
|
|
} else {
|
|
if (pixel && (!i || !rle_alpha_b16(data_ptr_prev[j + 1]))) {
|
|
*scr_buf = contour_color;
|
|
}
|
|
}
|
|
if (!pixel && i && rle_alpha_b16(data_ptr_prev[j + 1])) {
|
|
*scr_buf_prev = contour_color;
|
|
}
|
|
|
|
scr_buf += dx;
|
|
scr_buf_prev += dx;
|
|
}
|
|
if (pixel) *(scr_buf - dx) = contour_color;
|
|
}
|
|
|
|
y += dy;
|
|
}
|
|
uint16 *scr_buf_prev = (uint16 *)_screenBuf->getBasePtr(x, y - dy);
|
|
const uint16 *data_ptr_prev = (psy & 1) ? data0 + px : data1 + px;
|
|
if (!alpha_flag) {
|
|
for (int j = 0; j < psx; j += 2) {
|
|
if (data_ptr_prev[j])
|
|
*scr_buf_prev = contour_color;
|
|
scr_buf_prev += dx;
|
|
}
|
|
} else {
|
|
for (int j = 0; j < psx; j += 2) {
|
|
if (rle_alpha_b16(data_ptr_prev[j + 1]))
|
|
*scr_buf_prev = contour_color;
|
|
scr_buf_prev += dx;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void grDispatcher::drawSprContour(int x, int y, int sx, int sy, const class RLEBuffer *p, int contour_color, int mode, float scale, bool alpha_flag) {
|
|
debugC(4, kDebugGraphics, "grDispatcher::drawSprContour([%d, %d], [%d, %d], contour_color: %d, mode: %d, scale: %f, alpha_flag: %d)", x, y, sx, sy, contour_color, mode, scale, alpha_flag);
|
|
|
|
int sx_dest = round(float(sx) * scale);
|
|
int sy_dest = round(float(sy) * scale);
|
|
|
|
if (!sx_dest || !sy_dest) return;
|
|
|
|
int dx = (sx << 16) / sx_dest;
|
|
int dy = (sy << 16) / sy_dest;
|
|
int fx = (1 << 15);
|
|
int fy = (1 << 15);
|
|
|
|
int x0 = 0;
|
|
int x1 = sx_dest;
|
|
int ix = 1;
|
|
|
|
int y0 = 0;
|
|
int y1 = sy_dest;
|
|
int iy = 1;
|
|
|
|
if (mode & GR_FLIP_VERTICAL) {
|
|
y0 = sy_dest,
|
|
y1 = 0;
|
|
iy = -1;
|
|
}
|
|
|
|
if (mode & GR_FLIP_HORIZONTAL) {
|
|
x0 = sx_dest,
|
|
x1 = 0;
|
|
ix = -1;
|
|
}
|
|
|
|
if (!alpha_flag) {
|
|
const uint16 *line0 = reinterpret_cast<const uint16 *>(RLEBuffer::get_buffer(0));
|
|
const uint16 *line1 = reinterpret_cast<const uint16 *>(RLEBuffer::get_buffer(1));
|
|
|
|
for (int i = y0; i != y1; i += iy) {
|
|
p->decode_line(fy >> 16, i & 1);
|
|
const uint16 *line_src = (i & 1) ? line1 : line0;
|
|
const uint16 *line_src_prev = (i & 1) ? line0 : line1;
|
|
|
|
fy += dy;
|
|
fx = (1 << 15);
|
|
|
|
uint32 cl = 0;
|
|
for (int j = x0; j != x1; j += ix) {
|
|
if (clipCheck(x + j, y + i)) {
|
|
cl = line_src[(fx >> 16) << 1];
|
|
if (!cl && j != x0 && line_src[((fx - dx) >> 16) << 1])
|
|
setPixel(x + j - ix, y + i, contour_color);
|
|
|
|
if (cl && (j == x0 || !line_src[((fx - dx) >> 16) << 1])) {
|
|
setPixelFast(x + j, y + i, contour_color);
|
|
} else {
|
|
if (cl && (i == y0 || !line_src_prev[(fx >> 16) << 1]))
|
|
setPixelFast(x + j, y + i, contour_color);
|
|
}
|
|
|
|
if (!cl && i != y0 && line_src_prev[(fx >> 16) << 1])
|
|
setPixel(x + j, y + i - iy, contour_color);
|
|
}
|
|
fx += dx;
|
|
}
|
|
if (cl) setPixel(x + x1 - ix, y + i, contour_color);
|
|
}
|
|
fx = (1 << 15);
|
|
for (int j = x0; j != x1; j += ix) {
|
|
const uint16 *line_src_prev = (y1 & 1) ? line0 : line1;
|
|
if (line_src_prev[(fx >> 16) << 1])
|
|
setPixel(x + j, y + y1 - iy, contour_color);
|
|
fx += dx;
|
|
}
|
|
} else {
|
|
const uint16 *line0 = reinterpret_cast<const uint16 *>(RLEBuffer::get_buffer(0));
|
|
const uint16 *line1 = reinterpret_cast<const uint16 *>(RLEBuffer::get_buffer(1));
|
|
|
|
for (int i = y0; i != y1; i += iy) {
|
|
p->decode_line(fy >> 16, i & 1);
|
|
const uint16 *line_src = (i & 1) ? line1 : line0;
|
|
const uint16 *line_src_prev = (i & 1) ? line0 : line1;
|
|
|
|
fy += dy;
|
|
fx = (1 << 15);
|
|
|
|
bool cl = false;
|
|
for (int j = x0; j != x1; j += ix) {
|
|
if (clipCheck(x + j, y + i)) {
|
|
cl = rle_alpha_b16(line_src[((fx >> 16) << 1) + 1]);
|
|
if (!cl && j != x0 && rle_alpha_b16(line_src[(((fx - dx) >> 16) << 1) + 1]))
|
|
setPixel(x + j - ix, y + i, contour_color);
|
|
|
|
if (cl && (j == x0 || !rle_alpha_b16(line_src[(((fx - dx) >> 16) << 1) + 1]))) {
|
|
setPixelFast(x + j, y + i, contour_color);
|
|
} else {
|
|
if (cl && (i == y0 || !rle_alpha_b16(line_src_prev[((fx >> 16) << 1) + 1])))
|
|
setPixelFast(x + j, y + i, contour_color);
|
|
}
|
|
|
|
if (!cl && i != y0 && rle_alpha_b16(line_src_prev[((fx >> 16) << 1) + 1]))
|
|
setPixel(x + j, y + i - iy, contour_color);
|
|
}
|
|
fx += dx;
|
|
}
|
|
if (cl) setPixel(x + x1 - ix, y + i, contour_color);
|
|
}
|
|
fx = (1 << 15);
|
|
for (int j = x0; j != x1; j += ix) {
|
|
const uint16 *line_src_prev = (y1 & 1) ? line0 : line1;
|
|
if (rle_alpha_b16(line_src_prev[((fx >> 16) << 1) + 1]))
|
|
setPixel(x + j, y + y1 - iy, contour_color);
|
|
fx += dx;
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace QDEngine
|