/* 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 2 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "glk/window_graphics.h" #include "glk/conf.h" #include "glk/glk.h" #include "glk/screen.h" namespace Glk { GraphicsWindow::GraphicsWindow(Windows *windows, uint rock) : Window(windows, rock), _w(0), _h(0), _dirty(false), _surface(nullptr) { _type = wintype_Graphics; _bgnd = _bgColor; } GraphicsWindow::~GraphicsWindow() { delete _surface; } void GraphicsWindow::rearrange(const Rect &box) { int newwid, newhgt; int bothwid, bothhgt; Graphics::ManagedSurface *newSurface; _bbox = box; newwid = box.width(); newhgt = box.height(); if (newwid <= 0 || newhgt <= 0) { _w = 0; _h = 0; delete _surface; _surface = nullptr; return; } bothwid = _w; if (newwid < bothwid) bothwid = newwid; bothhgt = _h; if (newhgt < bothhgt) bothhgt = newhgt; // Create it Graphics::PixelFormat pixelFormat = g_system->getScreenFormat(); newSurface = new Graphics::ManagedSurface(newwid, newhgt, pixelFormat); newSurface->clear(_bgnd); // If the new surface is equal or bigger than the old one, copy it over if (_surface && bothwid && bothhgt) newSurface->blitFrom(*_surface); delete _surface; _surface = newSurface; _w = newwid; _h = newhgt; touch(); } void GraphicsWindow::touch() { _dirty = true; _windows->repaint(_bbox); } void GraphicsWindow::redraw() { Screen &screen = *g_vm->_screen; Window::redraw(); if (_dirty || Windows::_forceRedraw) { _dirty = 0; if (_surface) screen.blitFrom(*_surface, Point(_bbox.left, _bbox.top)); } } uint GraphicsWindow::drawPicture(uint image, int xpos, int ypos, int scale, uint imagewidth, uint imageheight) { Picture *pic = g_vm->_pictures->load(image); uint hyperlink = _attr.hyper; if (!pic) return false; if (!_imageLoaded) { g_vm->_pictures->increment(); _imageLoaded = true; } if (!scale) { imagewidth = pic->w; imageheight = pic->h; } drawPicture(pic, xpos, ypos, imagewidth, imageheight, hyperlink); touch(); return true; } void GraphicsWindow::eraseRect(bool whole, const Rect &box) { int x0 = box.left, y0 = box.top, x1 = box.right, y1 = box.bottom; int hx0, hx1, hy0, hy1; if (whole) { x0 = 0; y0 = 0; x1 = _w; y1 = _h; } if (x0 < 0) x0 = 0; if (y0 < 0) y0 = 0; if (x1 < 0) x1 = 0; if (y1 < 0) y1 = 0; if ((uint)x0 >= _w) x0 = _w; if ((uint)y0 >= _h) y0 = _h; if ((uint)x1 >= _w) x1 = _w; if ((uint)y1 >= _h) y1 = _h; hx0 = _bbox.left + x0; hx1 = _bbox.left + x1; hy0 = _bbox.top + y0; hy1 = _bbox.top + y1; // zero out hyperlinks for these coordinates g_vm->_selection->putHyperlink(0, hx0, hy0, hx1, hy1); _surface->fillRect(Rect(x0, y0, x1, y1), _bgnd); touch(); } void GraphicsWindow::fillRect(uint color, const Rect &box) { int x0 = box.left, y0 = box.top, x1 = box.right, y1 = box.bottom; int hx0, hx1, hy0, hy1; if (x0 < 0) x0 = 0; if (y0 < 0) y0 = 0; if (x1 < 0) x1 = 0; if (y1 < 0) y1 = 0; if ((uint)x0 > _w) x0 = _w; if ((uint)y0 > _h) y0 = _h; if ((uint)x1 > _w) x1 = _w; if ((uint)y1 > _h) y1 = _h; hx0 = _bbox.left + x0; hx1 = _bbox.left + x1; hy0 = _bbox.top + y0; hy1 = _bbox.top + y1; // zero out hyperlinks for these coordinates g_vm->_selection->putHyperlink(0, hx0, hy0, hx1, hy1); _surface->fillRect(Rect(x0, y0, x1, y1), color); touch(); } void GraphicsWindow::drawPicture(Picture *src, int x0, int y0, int width, int height, uint linkval) { int dx1, dy1, x1, y1, sx0, sy0, sx1, sy1; int hx0, hx1, hy0, hy1; int w, h; if (width != src->w || height != src->h) { src = g_vm->_pictures->scale(src, width, height); if (!src) return; } sx0 = 0; sy0 = 0; sx1 = src->w; sy1 = src->h; dx1 = _w; dy1 = _h; x1 = x0 + src->w; y1 = y0 + src->h; if (x1 <= 0 || x0 >= dx1) return; if (y1 <= 0 || y0 >= dy1) return; if (x0 < 0) { sx0 -= x0; x0 = 0; } if (y0 < 0) { sy0 -= y0; y0 = 0; } if (x1 > dx1) { sx1 += dx1 - x1; x1 = dx1; } if (y1 > dy1) { sy1 += dy1 - y1; y1 = dy1; } hx0 = _bbox.left + x0; hx1 = _bbox.left + x1; hy0 = _bbox.top + y0; hy1 = _bbox.top + y1; // zero out or set hyperlink for these coordinates g_vm->_selection->putHyperlink(linkval, hx0, hy0, hx1, hy1); w = sx1 - sx0; h = sy1 - sy0; _surface->transBlitFrom(*src, Rect(sx0, sy0, sx0 + w, sy0 + h), Point(x0, y0), src->getTransparentColor()); } void GraphicsWindow::getSize(uint *width, uint *height) const { *width = _bbox.width(); *height = _bbox.height(); } void GraphicsWindow::setBackgroundColor(uint color) { _bgnd = color; } void GraphicsWindow::click(const Point &newPos) { Point diff = newPos - Point(_bbox.left, _bbox.top); if (_mouseRequest) { g_vm->_events->store(evtype_MouseInput, this, diff.x, diff.y); _mouseRequest = false; if (g_conf->_safeClicks) g_vm->_events->_forceClick = true; } if (_hyperRequest) { uint linkval = g_vm->_selection->getHyperlink(newPos); if (linkval) { g_vm->_events->store(evtype_Hyperlink, this, linkval, 0); _hyperRequest = false; if (g_conf->_safeClicks) g_vm->_events->_forceClick = 1; } } } } // End of namespace Glk