/* 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 . * */ #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(_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(_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(&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(RLEBuffer::get_buffer(0)); const uint16 *data1 = reinterpret_cast(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(RLEBuffer::get_buffer(0)); const uint16 *line1 = reinterpret_cast(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(RLEBuffer::get_buffer(0)); const uint16 *line1 = reinterpret_cast(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