218 lines
5.1 KiB
C++
218 lines
5.1 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 "m4/graphics/gr_buff.h"
|
|
#include "m4/graphics/gr_pal.h"
|
|
#include "m4/gui/gui_vmng_core.h"
|
|
#include "m4/core/errors.h"
|
|
#include "m4/mem/memman.h"
|
|
|
|
namespace M4 {
|
|
|
|
GrBuff::GrBuff(int32 _w, int32 _h) {
|
|
w = _w;
|
|
h = _h;
|
|
x_off = y_off = 0;
|
|
pitch = _w;
|
|
height = _h;
|
|
alloc_pixmap();
|
|
}
|
|
|
|
GrBuff::GrBuff(int32 _w, int32 _h, int32 _x_off, int32 _y_off, int32 _pitch, int32 _height) {
|
|
w = _w;
|
|
h = _h;
|
|
x_off = _x_off;
|
|
y_off = _y_off;
|
|
pitch = _pitch;
|
|
height = _height;
|
|
alloc_pixmap();
|
|
}
|
|
|
|
GrBuff::~GrBuff() {
|
|
if (pixmap)
|
|
DisposeHandle(pixmap);
|
|
}
|
|
|
|
void GrBuff::lock() {
|
|
if (!pixmap)
|
|
return;
|
|
|
|
HLock(pixmap);
|
|
}
|
|
|
|
void GrBuff::release() {
|
|
if (pixmap)
|
|
HUnLock(pixmap);
|
|
}
|
|
|
|
void GrBuff::alloc_pixmap() {
|
|
pixmap = NewHandle(pitch * height, "pixmap");
|
|
HLock(pixmap);
|
|
memset(*pixmap, __BLACK, pitch * height);
|
|
HUnLock(pixmap);
|
|
}
|
|
|
|
uint8 *GrBuff::get_pixmap() {
|
|
if (pixmap) {
|
|
lock();
|
|
return (uint8 *)*pixmap;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Buffer *GrBuff::get_buffer() {
|
|
if (pixmap) {
|
|
lock();
|
|
dummy.data = (uint8 *)*pixmap;
|
|
dummy.w = w;
|
|
dummy.h = h;
|
|
dummy.encoding = 0;
|
|
dummy.stride = pitch;
|
|
|
|
return &dummy;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void GrBuff::refresh_video(int32 scrnX, int32 scrnY, int32 x1, int32 y1, int32 x2, int32 y2) {
|
|
vmng_refresh_video(scrnX, scrnY, x1, y1, x2, y2, get_buffer());
|
|
}
|
|
|
|
int32 gr_buffer_free(Buffer *buf) {
|
|
buf->w = buf->h = buf->stride = 0;
|
|
|
|
if (buf->data != nullptr) {
|
|
mem_free((char *)buf->data);
|
|
buf->data = nullptr;
|
|
return true;
|
|
}
|
|
|
|
error_show(FL, 'BUF!');
|
|
return false;
|
|
}
|
|
|
|
byte *gr_buffer_pointer(Buffer *buf, int32 x, int32 y) {
|
|
if (!buf || !buf->data || y < 0 || x < 0) {
|
|
error_show(FL, 'BUF!', "buffer_pointer x,y = %d,%d", x, y);
|
|
return nullptr;
|
|
}
|
|
|
|
return (byte *)(buf->data + x + (y * buf->stride));
|
|
}
|
|
|
|
const byte *gr_buffer_pointer(const Buffer *buf, int32 x, int32 y) {
|
|
if (!buf || !buf->data || y < 0 || x < 0) {
|
|
error_show(FL, 'BUF!', "buffer_pointer x,y = %d,%d", x, y);
|
|
return nullptr;
|
|
}
|
|
|
|
return (byte *)(buf->data + x + (y * buf->stride));
|
|
}
|
|
|
|
int32 gr_buffer_init(Buffer *buf, const char *name, int32 w, int32 h) {
|
|
if (buf->data)
|
|
error_show(FL, 'BUFR', "buffer_init %s", name);
|
|
|
|
buf->w = w;
|
|
buf->h = h;
|
|
buf->stride = w;
|
|
|
|
buf->data = (uint8 *)mem_alloc(buf->stride * h, name);
|
|
if (buf->data == nullptr)
|
|
error_show(FL, 'OOM!', "buffer: %s - w:%d h:%d bytes:%d", name, buf->stride, h, buf->stride * h);
|
|
|
|
memset(buf->data, 0, buf->stride * h);
|
|
|
|
return (true);
|
|
}
|
|
|
|
bool gr_buffer_rect_copy_2(const Buffer *from, Buffer *to, int32 sx, int32 sy,
|
|
int32 dx, int32 dy, int32 w, int32 h) {
|
|
// stupid check for no data
|
|
if (!from || !to || !from->data || !to->data)
|
|
error_show(FL, 'BUF!', "buff_rect_copy2");
|
|
|
|
// CKB: if height is greater than source height, truncate!
|
|
if (h > from->h)
|
|
h = from->h;
|
|
|
|
// if source x,y or dest x,y won't touch dest or source buffers, we're done
|
|
if ((sx > from->w) || (sy > from->h) || (dx > to->w) || (dy > to->h))
|
|
return true;
|
|
|
|
// if dest request intersects dest buffer, clip dest request
|
|
if ((dx + w) > to->w)
|
|
w = to->w - dx;
|
|
if ((dy + h) > to->h)
|
|
h = to->h - dy;
|
|
|
|
// if our dest request is too small, we're done
|
|
if ((w < 1) || (h < 1))
|
|
return true;
|
|
|
|
// initialize pointers
|
|
const byte *src = gr_buffer_pointer(from, sx, sy);
|
|
byte *dest = gr_buffer_pointer(to, dx, dy);
|
|
|
|
// get stride
|
|
int32 sIncr = from->stride;
|
|
int32 dIncr = to->stride;
|
|
|
|
// copy one to d'other
|
|
for (int i = 0; i < h; i++, dest += dIncr, src += sIncr)
|
|
memmove(dest, src, w);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool gr_buffer_rect_copy(Buffer *from, Buffer *to, int32 x, int32 y, int32 w, int32 h) {
|
|
return (gr_buffer_rect_copy_2(from, to, x, y, x, y, w, h));
|
|
}
|
|
|
|
int32 gr_buffer_rect_fill(Buffer *target, int32 x1, int32 y1, int32 w, int32 h) {
|
|
const byte color = gr_color_get_current();
|
|
|
|
// if no data, bad.
|
|
if (!target || !target->data)
|
|
error_show(FL, 'BUF!', "buffer_rect_fill");
|
|
|
|
// if nothing to fill, we're done
|
|
if ((w < 1) || (h < 1) || (x1 > target->w) || (y1 > target->h))
|
|
return true;
|
|
|
|
// clip if rectangles too big
|
|
if ((x1 + w) > target->w)
|
|
w = target->w - x1;
|
|
if ((y1 + h) > target->h)
|
|
h = target->h - y1;
|
|
|
|
if ((w < 1) || (h < 1))
|
|
return true;
|
|
|
|
uint8 *start = target->data + y1 * target->stride + x1;
|
|
for (int32 i = 0; i < h; i++, start += target->stride)
|
|
memset(start, color, w);
|
|
|
|
return true;
|
|
}
|
|
|
|
} // namespace M4
|