2009-02-17 15:17:01 +00:00
|
|
|
/* 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.
|
|
|
|
*
|
|
|
|
* $URL$
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
*/
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
// Graphical operations, called from the widget state manager
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-13 16:52:41 +00:00
|
|
|
#include "sci/sci.h"
|
2009-02-24 20:39:34 +00:00
|
|
|
#include "sci/gfx/operations.h"
|
2009-03-08 08:15:56 +00:00
|
|
|
#include "sci/gfx/font.h"
|
2009-05-11 13:31:17 +00:00
|
|
|
#include "sci/console.h"
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-21 22:00:24 +00:00
|
|
|
#include "common/system.h"
|
2009-03-07 19:23:32 +00:00
|
|
|
#include "common/events.h"
|
2009-02-21 22:00:24 +00:00
|
|
|
|
2009-02-21 10:23:36 +00:00
|
|
|
namespace Sci {
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
#define PRECISE_PRIORITY_MAP // Duplicate all operations on the local priority map as appropriate
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-22 13:11:43 +00:00
|
|
|
#undef GFXW_DEBUG_DIRTY
|
2009-02-21 08:47:07 +00:00
|
|
|
// Enable to debug stuff relevant for dirty rectsin widget management
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
#ifdef GFXW_DEBUG_DIRTY
|
2009-02-21 14:11:41 +00:00
|
|
|
# define DDIRTY fprintf(stderr, "%s:%5d| ", __FILE__, __LINE__); fprintf
|
2009-02-15 06:10:59 +00:00
|
|
|
#else
|
|
|
|
# define DDIRTY if (0) fprintf
|
|
|
|
#endif
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
// Default color maps
|
2009-02-15 06:10:59 +00:00
|
|
|
#define DEFAULT_COLORS_NR 16
|
2009-02-21 08:47:07 +00:00
|
|
|
|
2009-02-15 22:33:36 +00:00
|
|
|
gfx_pixmap_color_t default_colors[DEFAULT_COLORS_NR] = {{GFX_COLOR_SYSTEM, 0x00, 0x00, 0x00}, {GFX_COLOR_SYSTEM, 0x00, 0x00, 0xaa},
|
|
|
|
{GFX_COLOR_SYSTEM, 0x00, 0xaa, 0x00}, {GFX_COLOR_SYSTEM, 0x00, 0xaa, 0xaa},
|
|
|
|
{GFX_COLOR_SYSTEM, 0xaa, 0x00, 0x00}, {GFX_COLOR_SYSTEM, 0xaa, 0x00, 0xaa},
|
|
|
|
{GFX_COLOR_SYSTEM, 0xaa, 0x55, 0x00}, {GFX_COLOR_SYSTEM, 0xaa, 0xaa, 0xaa},
|
|
|
|
{GFX_COLOR_SYSTEM, 0x55, 0x55, 0x55}, {GFX_COLOR_SYSTEM, 0x55, 0x55, 0xff},
|
|
|
|
{GFX_COLOR_SYSTEM, 0x55, 0xff, 0x55}, {GFX_COLOR_SYSTEM, 0x55, 0xff, 0xff},
|
|
|
|
{GFX_COLOR_SYSTEM, 0xff, 0x55, 0x55}, {GFX_COLOR_SYSTEM, 0xff, 0x55, 0xff},
|
|
|
|
{GFX_COLOR_SYSTEM, 0xff, 0xff, 0x55}, {GFX_COLOR_SYSTEM, 0xff, 0xff, 0xff}
|
2009-02-21 08:47:07 +00:00
|
|
|
}; // "Normal" EGA
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
#define POINTER_VISIBLE_BUT_CLIPPED 2
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
// How to determine whether colors have to be allocated
|
2009-06-06 10:21:48 +00:00
|
|
|
#define PALETTE_MODE state->driver->getMode()->palette
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
//#define GFXOP_DEBUG_DIRTY
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
// Internal operations
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
static void _gfxop_scale_rect(rect_t *rect, gfx_mode_t *mode) {
|
2009-03-18 07:59:46 +00:00
|
|
|
rect->x *= mode->xfact;
|
|
|
|
rect->y *= mode->yfact;
|
|
|
|
rect->width *= mode->xfact;
|
|
|
|
rect->height *= mode->yfact;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
static void _gfxop_scale_point(Common::Point *point, gfx_mode_t *mode) {
|
2009-03-18 07:59:46 +00:00
|
|
|
point->x *= mode->xfact;
|
|
|
|
point->y *= mode->yfact;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
int _gfxop_clip(rect_t *rect, rect_t clipzone) {
|
|
|
|
// Returns 1 if nothing is left */
|
2009-02-15 06:10:59 +00:00
|
|
|
#if 0
|
2009-03-16 00:07:12 +00:00
|
|
|
printf("Clipping (%d, %d) size (%d, %d) by (%d,%d)(%d,%d)\n", rect->x, rect->y, rect->width, rect->height,
|
|
|
|
clipzone.x, clipzone.y, clipzone.width, clipzone.height);
|
2009-02-15 06:10:59 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (rect->x < clipzone.x) {
|
2009-03-16 00:07:12 +00:00
|
|
|
rect->width -= (clipzone.x - rect->x);
|
2009-02-15 06:10:59 +00:00
|
|
|
rect->x = clipzone.x;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rect->y < clipzone.y) {
|
2009-03-16 00:07:12 +00:00
|
|
|
rect->height -= (clipzone.y - rect->y);
|
2009-02-15 06:10:59 +00:00
|
|
|
rect->y = clipzone.y;
|
|
|
|
}
|
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
if (rect->x + rect->width > clipzone.x + clipzone.width)
|
|
|
|
rect->width = (clipzone.x + clipzone.width) - rect->x;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
if (rect->y + rect->height > clipzone.y + clipzone.height)
|
|
|
|
rect->height = (clipzone.y + clipzone.height) - rect->y;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
if (rect->width < 0)
|
|
|
|
rect->width = 0;
|
|
|
|
if (rect->height < 0)
|
|
|
|
rect->height = 0;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
#if 0
|
2009-03-16 00:07:12 +00:00
|
|
|
printf(" => (%d, %d) size (%d, %d)\n", rect->x, rect->y, rect->width, rect->height);
|
2009-02-15 06:10:59 +00:00
|
|
|
#endif
|
2009-03-16 00:07:12 +00:00
|
|
|
return (rect->width <= 0 || rect->height <= 0);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
static int _gfxop_grab_pixmap(GfxState *state, gfx_pixmap_t **pxmp, int x, int y,
|
2009-02-21 08:47:07 +00:00
|
|
|
int xl, int yl, int priority, rect_t *zone) {
|
|
|
|
// Returns 1 if the resulting data size was zero, GFX_OK or an error code otherwise */
|
2009-06-06 10:21:48 +00:00
|
|
|
int xfact = state->driver->getMode()->xfact;
|
|
|
|
int yfact = state->driver->getMode()->yfact;
|
2009-02-15 06:10:59 +00:00
|
|
|
int unscaled_xl = (xl + xfact - 1) / xfact;
|
|
|
|
int unscaled_yl = (yl + yfact - 1) / yfact;
|
|
|
|
*zone = gfx_rect(x, y, xl, yl);
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
if (_gfxop_clip(zone, gfx_rect(0, 0, 320 * state->driver->getMode()->xfact, 200 * state->driver->getMode()->yfact)))
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_ERROR;
|
|
|
|
|
|
|
|
if (!*pxmp)
|
|
|
|
*pxmp = gfx_new_pixmap(unscaled_xl, unscaled_yl, GFX_RESID_NONE, 0, 0);
|
|
|
|
else
|
2009-03-16 00:07:12 +00:00
|
|
|
if (xl * yl > (*pxmp)->width * (*pxmp)->height) {
|
2009-02-15 06:10:59 +00:00
|
|
|
gfx_pixmap_free_data(*pxmp);
|
|
|
|
(*pxmp)->data = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(*pxmp)->data) {
|
2009-03-16 00:07:12 +00:00
|
|
|
(*pxmp)->index_width = unscaled_xl + 1;
|
|
|
|
(*pxmp)->index_height = unscaled_yl + 1;
|
2009-06-06 10:21:48 +00:00
|
|
|
gfx_pixmap_alloc_data(*pxmp, state->driver->getMode());
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
2009-06-06 10:21:48 +00:00
|
|
|
return state->driver->grabPixmap(*zone, *pxmp, priority ? GFX_MASK_PRIORITY : GFX_MASK_VISUAL);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#define DRAW_LOOP(condition) \
|
|
|
|
{ \
|
2009-03-16 00:07:12 +00:00
|
|
|
rect_t drawrect = gfx_rect(pos.x, pos.y, pxm->index_width, pxm->index_height); \
|
2009-02-15 06:10:59 +00:00
|
|
|
int offset, base_offset; \
|
|
|
|
int read_offset, base_read_offset; \
|
|
|
|
int x,y; \
|
|
|
|
\
|
|
|
|
if (!pxm->index_data) { \
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Attempt to draw control color %d on pixmap %d/%d/%d without index data", color, pxm->ID, pxm->loop, pxm->cel); \
|
2009-02-15 06:10:59 +00:00
|
|
|
return; \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
if (_gfxop_clip(&drawrect, gfx_rect(0, 0, 320, 200))) \
|
|
|
|
return; \
|
|
|
|
\
|
|
|
|
offset = base_offset = drawrect.x + drawrect.y * 320; \
|
2009-03-16 00:07:12 +00:00
|
|
|
read_offset = base_read_offset = (drawrect.x - pos.x) + ((drawrect.y - pos.y) * pxm->index_width); \
|
2009-02-15 06:10:59 +00:00
|
|
|
\
|
2009-03-16 00:07:12 +00:00
|
|
|
for (y = 0; y < drawrect.height; y++) { \
|
|
|
|
for (x = 0; x < drawrect.width; x++) \
|
2009-02-15 06:10:59 +00:00
|
|
|
if (pxm->index_data[read_offset++] != pxm->color_key) { \
|
|
|
|
if (condition) \
|
|
|
|
map->index_data[offset++] = color; \
|
|
|
|
else \
|
|
|
|
++offset; \
|
2009-02-21 08:47:07 +00:00
|
|
|
} else \
|
|
|
|
++offset; \
|
2009-02-15 06:10:59 +00:00
|
|
|
\
|
|
|
|
offset = base_offset += 320; \
|
2009-03-16 00:07:12 +00:00
|
|
|
read_offset = base_read_offset += pxm->index_width; \
|
2009-02-15 06:10:59 +00:00
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
static void _gfxop_draw_control(gfx_pixmap_t *map, gfx_pixmap_t *pxm, int color, Common::Point pos)
|
|
|
|
DRAW_LOOP(1) // Always draw
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
#ifdef PRECISE_PRIORITY_MAP
|
2009-02-21 08:47:07 +00:00
|
|
|
static void _gfxop_draw_priority(gfx_pixmap_t *map, gfx_pixmap_t *pxm, int color, Common::Point pos)
|
|
|
|
DRAW_LOOP(map->index_data[offset] < color) // Draw only lower priority
|
2009-02-15 06:10:59 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#undef DRAW_LOOP
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
static int _gfxop_install_pixmap(GfxDriver *driver, gfx_pixmap_t *pxm) {
|
|
|
|
if (!driver->getMode()->palette) return GFX_OK;
|
2009-03-08 20:17:01 +00:00
|
|
|
if (!pxm->palette) return GFX_OK;
|
2009-03-12 23:23:46 +00:00
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
pxm->palette->mergeInto(driver->getMode()->palette);
|
|
|
|
assert(pxm->palette->getParent() == driver->getMode()->palette);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-05-24 12:56:06 +00:00
|
|
|
if (pxm->palette_revision != pxm->palette->getRevision())
|
2009-06-06 10:21:48 +00:00
|
|
|
gfx_xlate_pixmap(pxm, driver->getMode(), GFX_XLATE_FILTER_NONE);
|
2009-05-24 12:56:06 +00:00
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
if (!driver->getMode()->palette->isDirty()) return GFX_OK;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-08 20:17:01 +00:00
|
|
|
// TODO: We probably want to only update the colours used by this pixmap
|
|
|
|
// here. This will require updating the 'dirty' system.
|
2009-06-06 10:40:32 +00:00
|
|
|
byte paletteData[4*256];
|
2009-06-06 10:21:48 +00:00
|
|
|
const uint paletteSize = driver->getMode()->palette->size();
|
2009-05-08 16:00:39 +00:00
|
|
|
for (uint i = 0; i < paletteSize; ++i) {
|
2009-06-06 10:21:48 +00:00
|
|
|
const PaletteEntry& c = (*driver->getMode()->palette)[i];
|
2009-05-08 16:00:39 +00:00
|
|
|
paletteData[4*i+0] = c.r;
|
|
|
|
paletteData[4*i+1] = c.g;
|
|
|
|
paletteData[4*i+2] = c.b;
|
|
|
|
paletteData[4*i+3] = 255;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
2009-03-08 20:17:01 +00:00
|
|
|
|
2009-05-08 16:00:39 +00:00
|
|
|
g_system->setPalette(paletteData, 0, paletteSize);
|
2009-06-06 10:21:48 +00:00
|
|
|
driver->getMode()->palette->markClean();
|
2009-05-24 12:56:06 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
static int _gfxop_draw_pixmap(GfxDriver *driver, gfx_pixmap_t *pxm, int priority, int control,
|
2009-02-22 13:11:43 +00:00
|
|
|
rect_t src, rect_t dest, rect_t clip, int static_buf, gfx_pixmap_t *control_map, gfx_pixmap_t *priority_map) {
|
2009-04-24 10:44:10 +00:00
|
|
|
int err;
|
2009-03-16 00:07:12 +00:00
|
|
|
rect_t clipped_dest = gfx_rect(dest.x, dest.y, dest.width, dest.height);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (control >= 0 || priority >= 0) {
|
2009-06-06 10:21:48 +00:00
|
|
|
Common::Point original_pos = Common::Point(dest.x / driver->getMode()->xfact, dest.y / driver->getMode()->yfact);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (control >= 0)
|
|
|
|
_gfxop_draw_control(control_map, pxm, control, original_pos);
|
|
|
|
|
|
|
|
#ifdef PRECISE_PRIORITY_MAP
|
|
|
|
if (priority >= 0)
|
|
|
|
_gfxop_draw_priority(priority_map, pxm, priority, original_pos);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_gfxop_clip(&clipped_dest, clip))
|
|
|
|
return GFX_OK;
|
|
|
|
|
|
|
|
src.x += clipped_dest.x - dest.x;
|
|
|
|
src.y += clipped_dest.y - dest.y;
|
2009-03-16 00:07:12 +00:00
|
|
|
src.width = clipped_dest.width;
|
|
|
|
src.height = clipped_dest.height;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-04-24 10:44:10 +00:00
|
|
|
err = _gfxop_install_pixmap(driver, pxm);
|
|
|
|
if (err)
|
|
|
|
return err;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
DDIRTY(stderr, "\\-> Drawing to actual %d %d %d %d\n", clipped_dest.x / driver->getMode()->xfact,
|
|
|
|
clipped_dest.y / driver->getMode()->yfact, clipped_dest.width / driver->getMode()->xfact, clipped_dest.height / driver->getMode()->yfact);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
err = driver->drawPixmap(pxm, priority, src, clipped_dest, static_buf ? GFX_BUFFER_STATIC : GFX_BUFFER_BACK);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-04-24 10:44:10 +00:00
|
|
|
if (err) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("driver->draw_pixmap() returned error code");
|
2009-04-24 10:44:10 +00:00
|
|
|
return err;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
2009-02-21 08:47:07 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
static void _gfxop_full_pointer_refresh(GfxState *state) {
|
2009-06-05 18:05:45 +00:00
|
|
|
Common::Point mousePoint = g_system->getEventManager()->getMousePos();
|
2009-06-06 10:21:48 +00:00
|
|
|
state->pointer_pos.x = mousePoint.x / state->driver->getMode()->xfact;
|
|
|
|
state->pointer_pos.y = mousePoint.y / state->driver->getMode()->yfact;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
static int _gfxop_buffer_propagate_box(GfxState *state, rect_t box, gfx_buffer_t buffer);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
gfx_pixmap_t *_gfxr_get_cel(GfxState *state, int nr, int *loop, int *cel, int palette) {
|
2009-03-22 23:11:43 +00:00
|
|
|
gfxr_view_t *view = state->gfxResMan->getView(nr, loop, cel, palette);
|
2009-03-17 23:30:57 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
gfxr_loop_t *indexed_loop;
|
|
|
|
|
|
|
|
if (!view)
|
|
|
|
return NULL;
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
if (*loop >= view->loops_nr || *loop < 0) {
|
2009-06-08 11:42:13 +00:00
|
|
|
warning("[GFX] Attempt to get cel from loop %d/%d inside view %d", *loop, view->loops_nr, nr);
|
2009-02-15 06:10:59 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
indexed_loop = view->loops + *loop;
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
if (*cel >= indexed_loop->cels_nr || *cel < 0) {
|
2009-06-08 11:42:13 +00:00
|
|
|
warning("[GFX] Attempt to get cel %d/%d from view %d/%d", *cel, indexed_loop->cels_nr, nr, *loop);
|
2009-02-15 06:10:59 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
return indexed_loop->cels[*cel]; // Yes, view->cels uses a malloced pointer list.
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
//** Dirty rectangle operations **
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
static int _gfxop_update_box(GfxState *state, rect_t box) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int retval;
|
2009-06-06 10:21:48 +00:00
|
|
|
_gfxop_scale_rect(&box, state->driver->getMode());
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if ((retval = _gfxop_buffer_propagate_box(state, box, GFX_BUFFER_FRONT))) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Error occured while propagating box (%d,%d,%d,%d) to front buffer", box.x, box.y, box.width, box.height);
|
2009-02-15 06:10:59 +00:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:25 +00:00
|
|
|
void gfxdr_add_dirty(DirtyRectList &list, rect_t box, int strategy) {
|
2009-03-16 00:07:12 +00:00
|
|
|
if (box.width < 0) {
|
|
|
|
box.x += box.width;
|
|
|
|
box.width = - box.width;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
if (box.height < 0) {
|
|
|
|
box.y += box.height;
|
|
|
|
box.height = - box.height;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
#ifdef GFXOP_DEBUG_DIRTY
|
2009-02-21 14:11:41 +00:00
|
|
|
fprintf(stderr, "Adding new dirty (%d %d %d %d)\n",
|
|
|
|
GFX_PRINT_RECT(box));
|
2009-02-15 06:10:59 +00:00
|
|
|
#endif
|
|
|
|
if (_gfxop_clip(&box, gfx_rect(0, 0, 320, 200)))
|
2009-04-27 11:12:25 +00:00
|
|
|
return;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
switch (strategy) {
|
|
|
|
|
|
|
|
case GFXOP_DIRTY_FRAMES_ONE:
|
2009-04-27 11:12:25 +00:00
|
|
|
if (!list.empty()) {
|
|
|
|
Common::Rect tmp = toCommonRect(list.front());
|
2009-03-19 19:52:05 +00:00
|
|
|
tmp.extend(toCommonRect(box));
|
2009-04-27 11:12:25 +00:00
|
|
|
list.front() = toSCIRect(tmp);
|
2009-03-16 15:36:09 +00:00
|
|
|
} else {
|
2009-04-27 11:12:25 +00:00
|
|
|
list.push_back(box);
|
2009-03-16 15:36:09 +00:00
|
|
|
}
|
2009-02-15 06:10:59 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GFXOP_DIRTY_FRAMES_CLUSTERS: {
|
2009-04-27 11:12:25 +00:00
|
|
|
DirtyRectList::iterator dirty = list.begin();
|
|
|
|
while (dirty != list.end()) {
|
|
|
|
if (gfx_rects_overlap(*dirty, box)) {
|
2009-03-19 19:52:05 +00:00
|
|
|
Common::Rect tmp = toCommonRect(box);
|
2009-04-27 11:12:25 +00:00
|
|
|
tmp.extend(toCommonRect(*dirty));
|
2009-03-16 15:36:09 +00:00
|
|
|
box = toSCIRect(tmp);
|
|
|
|
|
2009-04-27 11:12:25 +00:00
|
|
|
dirty = list.erase(dirty);
|
2009-02-15 06:10:59 +00:00
|
|
|
} else
|
2009-04-27 11:12:25 +00:00
|
|
|
++dirty;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
2009-04-27 11:12:25 +00:00
|
|
|
list.push_back(box);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-04-27 11:12:25 +00:00
|
|
|
}
|
|
|
|
break;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
default:
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Attempt to use invalid dirty frame mode %d!\nPlease refer to gfx_options.h", strategy);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
static void _gfxop_add_dirty(GfxState *state, rect_t box) {
|
2009-02-15 06:10:59 +00:00
|
|
|
if (state->disable_dirty)
|
|
|
|
return;
|
|
|
|
|
2009-04-01 20:32:45 +00:00
|
|
|
#ifdef CUSTOM_GRAPHICS_OPTIONS
|
2009-04-27 11:12:25 +00:00
|
|
|
gfxdr_add_dirty(state->_dirtyRects, box, state->options->dirty_frames);
|
2009-04-01 20:32:45 +00:00
|
|
|
#else
|
2009-04-27 11:12:25 +00:00
|
|
|
gfxdr_add_dirty(state->_dirtyRects, box, GFXOP_DIRTY_FRAMES_CLUSTERS);
|
2009-04-01 20:32:45 +00:00
|
|
|
#endif
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
static void _gfxop_add_dirty_x(GfxState *state, rect_t box) {
|
2009-02-21 08:47:07 +00:00
|
|
|
// Extends the box size by one before adding (used for lines)
|
2009-03-16 00:07:12 +00:00
|
|
|
if (box.width < 0)
|
|
|
|
box.width--;
|
2009-02-15 06:10:59 +00:00
|
|
|
else
|
2009-03-16 00:07:12 +00:00
|
|
|
box.width++;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
if (box.height < 0)
|
|
|
|
box.height--;
|
2009-02-15 06:10:59 +00:00
|
|
|
else
|
2009-03-16 00:07:12 +00:00
|
|
|
box.height++;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
_gfxop_add_dirty(state, box);
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:25 +00:00
|
|
|
static int _gfxop_clear_dirty_rec(GfxState *state, DirtyRectList &dirtyRects) {
|
|
|
|
int retval = GFX_OK;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-04-27 11:12:25 +00:00
|
|
|
DirtyRectList::iterator dirty = dirtyRects.begin();
|
|
|
|
while (dirty != dirtyRects.end()) {
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-04-27 11:12:25 +00:00
|
|
|
#ifdef GFXOP_DEBUG_DIRTY
|
|
|
|
fprintf(stderr, "\tClearing dirty (%d %d %d %d)\n", GFX_PRINT_RECT(*dirty));
|
|
|
|
#endif
|
|
|
|
if (!state->fullscreen_override)
|
|
|
|
retval |= _gfxop_update_box(state, *dirty);
|
|
|
|
++dirty;
|
|
|
|
}
|
|
|
|
dirtyRects.clear();
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
//** Exported operations **
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
static void init_aux_pixmap(gfx_pixmap_t **pixmap) {
|
2009-02-15 06:10:59 +00:00
|
|
|
*pixmap = gfx_pixmap_alloc_index_data(gfx_new_pixmap(320, 200, GFX_RESID_NONE, 0, 0));
|
2009-03-08 20:17:01 +00:00
|
|
|
// FIXME: don't duplicate this palette for every aux_pixmap
|
|
|
|
(*pixmap)->palette = new Palette(default_colors, DEFAULT_COLORS_NR);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
Merged revisions 42205-42206,42208-42209,42211-42212,42214-42217,42219,42221-42222,42229-42235,42238-42240 via svnmerge from
https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk
........
r42205 | dreammaster | 2009-07-07 17:41:02 +1000 (Tue, 07 Jul 2009) | 1 line
Removed the shooting workaround delay - the overlay number can vary, so it isn't a reliable way of identifying the specific message
........
r42206 | thebluegr | 2009-07-07 17:44:25 +1000 (Tue, 07 Jul 2009) | 4 lines
- Added auto-detection for EGA graphics. As a result of this, GF_SCI1_EGA has been removed and versions SCI_VERSION_01_EGA and SCI_VERSION_01_VGA have been merged into SCI_VERSION_01
- Simplified the checks for EGA and VGA graphics
- Fixed a bug in script_adjust_opcode_formats()
- Simplified the code in GfxResManager::getView() a bit
........
r42208 | strangerke | 2009-07-07 17:51:18 +1000 (Tue, 07 Jul 2009) | 1 line
Add detection of Playtoons 2 En
........
r42209 | thebluegr | 2009-07-07 17:51:26 +1000 (Tue, 07 Jul 2009) | 1 line
Added a SCI1.1 case in the lofss opcode, like in the lofsa opcode (essentially, lofss and lofsa both load an offset, with lofsa loading it in the accumulator and lofss in the stack). lofss is rarely used in SCI1.1 games, which explains why no lofss-related crashes have been observed in SCI1.1
........
r42211 | thebluegr | 2009-07-07 20:28:05 +1000 (Tue, 07 Jul 2009) | 1 line
Added auto-detection for games with older headers for script blocks, and removed game flag GF_SCI0_OLD
........
r42212 | thebluegr | 2009-07-07 21:14:18 +1000 (Tue, 07 Jul 2009) | 1 line
Cleanup: added an enum for the auto-detected features, removed the selectors which are only used for auto-detection from the convenience selector map and placed feature auto-detection in a separate function. Also, now the automatically detected graphics resources are shown in the console.
........
r42214 | strangerke | 2009-07-07 21:58:22 +1000 (Tue, 07 Jul 2009) | 2 lines
- Separate Playtoons gametypes from in GobEngine::initGameParts()
- Add a specific save/load class for Playtoons as some specific files need to be tested
........
r42215 | strangerke | 2009-07-07 22:03:27 +1000 (Tue, 07 Jul 2009) | 3 lines
- Add a new gametype for 'The Land of the Magic Stones'
- Add detection of the french version
- Add a new game feature for 800*600
........
r42216 | thebluegr | 2009-07-07 22:29:55 +1000 (Tue, 07 Jul 2009) | 1 line
Removed the superfluous sci_version_types array (it's essentially the same as the versionNames array)
........
r42217 | strangerke | 2009-07-07 22:51:21 +1000 (Tue, 07 Jul 2009) | 1 line
Change SaveLoad_Playtoons case
........
r42219 | thebluegr | 2009-07-07 23:39:24 +1000 (Tue, 07 Jul 2009) | 1 line
Removed the weird checks for a maximum resource number (the sci_max_resource_nr array), as it doesn't serve any real purpose and leads to strange errors: if a resource is found which is bigger than the maximum number, it will be remapped to an incorrect number from this check. This makes KQ5CD work properly again (resources would be remapped to incorrect resource numbers from this code as a result of not updating this array with the latest SCI version merges).
........
r42221 | lordhoto | 2009-07-08 00:22:23 +1000 (Wed, 08 Jul 2009) | 1 line
Add generic functionallity to draw FM-Towns ROM. (To be used by KYRA and SCI)
........
r42222 | lordhoto | 2009-07-08 00:22:39 +1000 (Wed, 08 Jul 2009) | 1 line
Adapt KYRA to use the new Graphics::FontSJIS code.
........
r42229 | sev | 2009-07-08 03:11:29 +1000 (Wed, 08 Jul 2009) | 2 lines
kFeatures800 -> kFeatures800x600 in order to have more meaningful name
........
r42230 | lordhoto | 2009-07-08 04:10:35 +1000 (Wed, 08 Jul 2009) | 2 lines
- Added support for outlined FM-Towns ROM drawing
- Adapted KYRA to use that
........
r42231 | lordhoto | 2009-07-08 04:17:30 +1000 (Wed, 08 Jul 2009) | 2 lines
- Rename FontSJIS::enableShadow to enableOutline.
- Initialize outline to false by default in FontTowns.
........
r42232 | lordhoto | 2009-07-08 05:00:39 +1000 (Wed, 08 Jul 2009) | 1 line
Change "FM-Towns" to "FM-TOWNS" for consistency.
........
r42233 | lordhoto | 2009-07-08 05:00:51 +1000 (Wed, 08 Jul 2009) | 1 line
Add guards to only include SJIS font code, when KYRA or SCI is enabled.
........
r42234 | lordhoto | 2009-07-08 05:18:32 +1000 (Wed, 08 Jul 2009) | 1 line
Simply compile guard of SJIS code and fix comment.
........
r42235 | lordhoto | 2009-07-08 05:18:53 +1000 (Wed, 08 Jul 2009) | 1 line
Change all uses of FM-Towns/fm-towns to FM-TOWNS.
........
r42238 | thebluegr | 2009-07-08 06:01:15 +1000 (Wed, 08 Jul 2009) | 1 line
Added a workaround for incorrect font references in LSL1VGA (which was the original purpose of the code removed in rev. 42219)
........
r42239 | thebluegr | 2009-07-08 06:17:07 +1000 (Wed, 08 Jul 2009) | 1 line
Improved the LSL1VGA workaround after talking with waltervn
........
r42240 | thebluegr | 2009-07-08 06:43:27 +1000 (Wed, 08 Jul 2009) | 1 line
Silenced the very chatty song iterator console messages by converting them to appropriate debug messages
........
svn-id: r42248
2009-07-07 23:24:34 +00:00
|
|
|
int gfxop_init(int version, GfxState *state,
|
2009-06-26 22:30:52 +00:00
|
|
|
gfx_options_t *options, ResourceManager *resManager,
|
|
|
|
Graphics::PixelFormat mode, int xfact, int yfact) {
|
2009-06-06 17:10:15 +00:00
|
|
|
//int color_depth = bpp ? bpp : 1;
|
|
|
|
//int initialized = 0;
|
2009-03-18 11:07:29 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
state->options = options;
|
2009-03-18 11:07:29 +00:00
|
|
|
state->visible_map = GFX_MASK_VISUAL;
|
|
|
|
state->fullscreen_override = NULL; // No magical override
|
|
|
|
state->options = options;
|
|
|
|
state->disable_dirty = 0;
|
|
|
|
state->_events.clear();
|
|
|
|
state->pic = state->pic_unscaled = NULL;
|
|
|
|
state->pic_nr = -1; // Set background pic number to an invalid value
|
|
|
|
state->tag_mode = 0;
|
2009-04-21 19:57:11 +00:00
|
|
|
state->pic_port_bounds = gfx_rect(0, 10, 320, 190);
|
2009-04-27 11:12:25 +00:00
|
|
|
state->_dirtyRects.clear();
|
2009-03-18 11:07:29 +00:00
|
|
|
|
2009-06-26 22:30:52 +00:00
|
|
|
state->driver = new GfxDriver(xfact, yfact, mode);
|
2009-03-18 11:07:29 +00:00
|
|
|
|
2009-07-11 17:25:49 +00:00
|
|
|
state->gfxResMan = new GfxResManager(state->options, state->driver, resManager);
|
2009-07-07 07:44:25 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
gfxop_set_clip_zone(state, gfx_rect(0, 0, 320, 200));
|
|
|
|
|
|
|
|
init_aux_pixmap(&(state->control_map));
|
|
|
|
init_aux_pixmap(&(state->priority_map));
|
|
|
|
init_aux_pixmap(&(state->static_priority_map));
|
|
|
|
|
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_exit(GfxState *state) {
|
2009-03-22 23:11:43 +00:00
|
|
|
state->gfxResMan->freeResManager();
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (state->control_map) {
|
2009-03-17 21:08:33 +00:00
|
|
|
gfx_free_pixmap(state->control_map);
|
2009-02-15 06:10:59 +00:00
|
|
|
state->control_map = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state->priority_map) {
|
2009-03-17 21:08:33 +00:00
|
|
|
gfx_free_pixmap(state->priority_map);
|
2009-02-15 06:10:59 +00:00
|
|
|
state->priority_map = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state->static_priority_map) {
|
2009-03-17 21:08:33 +00:00
|
|
|
gfx_free_pixmap(state->static_priority_map);
|
2009-02-15 06:10:59 +00:00
|
|
|
state->static_priority_map = NULL;
|
|
|
|
}
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
delete state->driver;
|
2009-02-21 08:47:07 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
static int _gfxop_scan_one_bitmask(gfx_pixmap_t *pixmap, rect_t zone) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int retval = 0;
|
2009-03-16 00:07:12 +00:00
|
|
|
int pixmap_xscale = pixmap->index_width / 320;
|
|
|
|
int pixmap_yscale = pixmap->index_height / 200;
|
|
|
|
int line_width = pixmap_yscale * pixmap->index_width;
|
2009-02-15 06:10:59 +00:00
|
|
|
int startindex = (line_width * zone.y) + (zone.x * pixmap_xscale);
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
startindex += pixmap_xscale >> 1; // Center on X
|
2009-03-16 00:07:12 +00:00
|
|
|
startindex += (pixmap_yscale >> 1) * pixmap->index_width; // Center on Y
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
if (_gfxop_clip(&zone, gfx_rect(0, 0, pixmap->index_width, pixmap->index_height)))
|
2009-02-15 06:10:59 +00:00
|
|
|
return 0;
|
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
while (zone.height--) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int i;
|
2009-03-16 00:07:12 +00:00
|
|
|
for (i = 0; i < (zone.width * pixmap_xscale); i += pixmap_xscale)
|
2009-02-15 06:10:59 +00:00
|
|
|
retval |= (1 << ((pixmap->index_data[startindex + i]) & 0xf));
|
|
|
|
|
|
|
|
startindex += line_width;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_scan_bitmask(GfxState *state, rect_t area, gfx_map_mask_t map) {
|
2009-02-15 22:33:36 +00:00
|
|
|
gfxr_pic_t *pic = (state->pic_unscaled) ? state->pic_unscaled : state->pic;
|
2009-02-15 06:10:59 +00:00
|
|
|
int retval = 0;
|
|
|
|
|
|
|
|
_gfxop_clip(&area, gfx_rect(0, 10, 320, 200));
|
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
if (area.width <= 0
|
|
|
|
|| area.height <= 0)
|
2009-02-15 06:10:59 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (map & GFX_MASK_VISUAL)
|
|
|
|
retval |= _gfxop_scan_one_bitmask(pic->visual_map, area);
|
|
|
|
|
|
|
|
if (map & GFX_MASK_PRIORITY)
|
|
|
|
retval |= _gfxop_scan_one_bitmask(state->priority_map, area);
|
|
|
|
if (map & GFX_MASK_CONTROL)
|
|
|
|
retval |= _gfxop_scan_one_bitmask(state->control_map, area);
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define MIN_X 0
|
|
|
|
#define MIN_Y 0
|
|
|
|
#define MAX_X 319
|
|
|
|
#define MAX_Y 199
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_set_clip_zone(GfxState *state, rect_t zone) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int xfact, yfact;
|
|
|
|
|
|
|
|
DDIRTY(stderr, "-- Setting clip zone %d %d %d %d\n", GFX_PRINT_RECT(zone));
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
xfact = state->driver->getMode()->xfact;
|
|
|
|
yfact = state->driver->getMode()->yfact;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (zone.x < MIN_X) {
|
2009-03-16 00:07:12 +00:00
|
|
|
zone.width -= (zone.x - MIN_X);
|
2009-02-15 06:10:59 +00:00
|
|
|
zone.x = MIN_X;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (zone.y < MIN_Y) {
|
2009-03-16 00:07:12 +00:00
|
|
|
zone.height -= (zone.y - MIN_Y);
|
2009-02-15 06:10:59 +00:00
|
|
|
zone.y = MIN_Y;
|
|
|
|
}
|
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
if (zone.x + zone.width > MAX_X)
|
|
|
|
zone.width = MAX_X + 1 - zone.x;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
if (zone.y + zone.height > MAX_Y)
|
|
|
|
zone.height = MAX_Y + 1 - zone.y;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
memcpy(&(state->clip_zone_unscaled), &zone, sizeof(rect_t));
|
|
|
|
|
|
|
|
state->clip_zone.x = state->clip_zone_unscaled.x * xfact;
|
|
|
|
state->clip_zone.y = state->clip_zone_unscaled.y * yfact;
|
2009-03-16 00:07:12 +00:00
|
|
|
state->clip_zone.width = state->clip_zone_unscaled.width * xfact;
|
|
|
|
state->clip_zone.height = state->clip_zone_unscaled.height * yfact;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_set_color(GfxState *state, gfx_color_t *color, int r, int g, int b, int a, int priority, int control) {
|
2009-02-21 08:47:07 +00:00
|
|
|
int mask = ((r >= 0 && g >= 0 && b >= 0) ? GFX_MASK_VISUAL : 0) | ((priority >= 0) ? GFX_MASK_PRIORITY : 0)
|
2009-02-15 22:33:36 +00:00
|
|
|
| ((control >= 0) ? GFX_MASK_CONTROL : 0);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (PALETTE_MODE && a >= GFXOP_ALPHA_THRESHOLD)
|
|
|
|
mask &= ~GFX_MASK_VISUAL;
|
|
|
|
|
|
|
|
color->mask = mask;
|
|
|
|
|
|
|
|
color->priority = priority;
|
|
|
|
color->control = control;
|
|
|
|
|
|
|
|
if (mask & GFX_MASK_VISUAL) {
|
|
|
|
color->visual.r = r;
|
|
|
|
color->visual.g = g;
|
|
|
|
color->visual.b = b;
|
|
|
|
color->alpha = a;
|
|
|
|
|
|
|
|
if (PALETTE_MODE) {
|
2009-06-06 10:21:48 +00:00
|
|
|
color->visual.parent_index = state->driver->getMode()->palette->findNearbyColor(r,g,b,true);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
}
|
2009-02-21 08:47:07 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-03-03 14:27:49 +00:00
|
|
|
// Wrapper for gfxop_set_color
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_set_color(GfxState *state, gfx_color_t *colorOut, gfx_color_t &colorIn) {
|
2009-05-25 19:48:52 +00:00
|
|
|
return gfxop_set_color(state, colorOut,
|
|
|
|
(colorIn.mask & GFX_MASK_VISUAL) ? colorIn.visual.r : -1,
|
|
|
|
(colorIn.mask & GFX_MASK_VISUAL) ? colorIn.visual.g : -1,
|
|
|
|
(colorIn.mask & GFX_MASK_VISUAL) ? colorIn.visual.b : -1,
|
|
|
|
(colorIn.mask & GFX_MASK_VISUAL) ? colorIn.alpha : -1,
|
|
|
|
(colorIn.mask & GFX_MASK_PRIORITY) ? colorIn.priority : -1,
|
|
|
|
(colorIn.mask & GFX_MASK_CONTROL) ? colorIn.control : -1);
|
2009-03-03 14:27:49 +00:00
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_set_system_color(GfxState *state, unsigned int index, gfx_color_t *color) {
|
2009-02-15 06:10:59 +00:00
|
|
|
if (!PALETTE_MODE)
|
|
|
|
return GFX_OK;
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
if (index >= state->driver->getMode()->palette->size()) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Attempt to set invalid color index %02x as system color", color->visual.parent_index);
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
state->driver->getMode()->palette->makeSystemColor(index, color->visual);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_free_color(GfxState *state, gfx_color_t *color) {
|
2009-03-08 20:17:01 +00:00
|
|
|
// FIXME: implement. (And call in the appropriate places!)
|
2009-03-08 20:43:36 +00:00
|
|
|
return GFX_OK;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-03-08 20:17:01 +00:00
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
// Generic drawing operations
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
static int line_check_bar(int *start, int *length, int clipstart, int cliplength) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int overlength;
|
|
|
|
|
|
|
|
if (*start < clipstart) {
|
|
|
|
*length -= (clipstart - *start);
|
|
|
|
*start = clipstart;
|
|
|
|
}
|
|
|
|
|
|
|
|
overlength = 1 + (*start + *length) - (clipstart + cliplength);
|
|
|
|
|
|
|
|
if (overlength > 0)
|
|
|
|
*length -= overlength;
|
|
|
|
|
|
|
|
return (*length < 0);
|
|
|
|
}
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
static void clip_line_partial(float *start, float *end, float delta_val, float pos_val, float start_val, float end_val) {
|
2009-02-15 06:10:59 +00:00
|
|
|
float my_start = (start_val - pos_val) * delta_val;
|
|
|
|
float my_end = (end_val - pos_val) * delta_val;
|
|
|
|
|
|
|
|
if (my_end < *end)
|
|
|
|
*end = my_end;
|
|
|
|
if (my_start > *start)
|
|
|
|
*start = my_start;
|
|
|
|
}
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
static int line_clip(rect_t *line, rect_t clip, int xfact, int yfact) {
|
|
|
|
// returns 1 if nothing is left, or 0 if part of the line is in the clip window
|
|
|
|
// Compensate for line thickness (should match precisely)
|
2009-03-16 00:07:12 +00:00
|
|
|
clip.width -= xfact;
|
|
|
|
clip.height -= yfact;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
if (!line->width) { // vbar
|
|
|
|
if (line->x < clip.x || line->x >= (clip.x + clip.width))
|
2009-02-15 06:10:59 +00:00
|
|
|
return 1;
|
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
return line_check_bar(&(line->y), &(line->height), clip.y, clip.height);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
} else {
|
2009-03-16 00:07:12 +00:00
|
|
|
if (!line->height) {// hbar
|
|
|
|
if (line->y < clip.y || line->y >= (clip.y + clip.height))
|
2009-02-15 22:33:36 +00:00
|
|
|
return 1;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
return line_check_bar(&(line->x), &(line->width), clip.x, clip.width);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
} else { // "normal" line
|
2009-07-01 20:51:04 +00:00
|
|
|
float start = 0.0f, end = 1.0f;
|
2009-03-16 00:07:12 +00:00
|
|
|
float xv = (float)line->width;
|
|
|
|
float yv = (float)line->height;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
if (line->width < 0)
|
|
|
|
clip_line_partial(&start, &end, (float)(1.0 / xv), (float)line->x, (float)(clip.x + clip.width), (float)clip.x);
|
2009-02-15 22:33:36 +00:00
|
|
|
else
|
2009-03-16 00:07:12 +00:00
|
|
|
clip_line_partial(&start, &end, (float)(1.0 / xv), (float)line->x, (float)clip.x, (float)(clip.x + clip.width));
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
if (line->height < 0)
|
|
|
|
clip_line_partial(&start, &end, (float)(1.0 / yv), (float)line->y, (float)(clip.y + clip.height), (float)clip.y);
|
2009-02-15 22:33:36 +00:00
|
|
|
else
|
2009-03-16 00:07:12 +00:00
|
|
|
clip_line_partial(&start, &end, (float)(1.0 / yv), (float)line->y, (float)clip.y, (float)(clip.y + clip.height));
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 22:33:36 +00:00
|
|
|
line->x += (int)(xv * start);
|
|
|
|
line->y += (int)(yv * start);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
line->width = (int)(xv * (end - start));
|
|
|
|
line->height = (int)(yv * (end - start));
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-07-01 20:51:04 +00:00
|
|
|
return (start > 1.0f || end < 0.0f);
|
2009-02-15 22:33:36 +00:00
|
|
|
}
|
2009-02-21 08:47:07 +00:00
|
|
|
}
|
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
static int point_clip(Common::Point *start, Common::Point *end, rect_t clip, int xfact, int yfact) {
|
2009-02-15 06:10:59 +00:00
|
|
|
rect_t line = gfx_rect(start->x, start->y, end->x - start->x, end->y - start->y);
|
|
|
|
int retval = line_clip(&line, clip, xfact, yfact);
|
|
|
|
|
|
|
|
start->x = line.x;
|
|
|
|
start->y = line.y;
|
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
end->x = line.x + line.width;
|
|
|
|
end->y = line.y + line.height;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
static void draw_line_to_control_map(GfxState *state, Common::Point start, Common::Point end, gfx_color_t color) {
|
2009-02-15 06:10:59 +00:00
|
|
|
if (color.mask & GFX_MASK_CONTROL)
|
|
|
|
if (!point_clip(&start, &end, state->clip_zone_unscaled, 0, 0))
|
|
|
|
gfx_draw_line_pixmap_i(state->control_map, start, end, color.control);
|
|
|
|
}
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
static int simulate_stippled_line_draw(GfxDriver *driver, int skipone, Common::Point start, Common::Point end, gfx_color_t color, gfx_line_mode_t line_mode) {
|
2009-02-21 08:47:07 +00:00
|
|
|
// Draws a stippled line if this isn't supported by the driver (skipone is ignored ATM)
|
2009-02-15 06:10:59 +00:00
|
|
|
int xl = end.x - start.x;
|
|
|
|
int yl = end.y - start.y;
|
2009-06-06 10:21:48 +00:00
|
|
|
int stepwidth = (xl) ? driver->getMode()->xfact : driver->getMode()->yfact;
|
2009-02-15 22:33:36 +00:00
|
|
|
int dbl_stepwidth = 2 * stepwidth;
|
|
|
|
int linelength = (line_mode == GFX_LINE_MODE_FINE) ? stepwidth - 1 : 0;
|
2009-03-22 22:02:25 +00:00
|
|
|
int16 *posvar;
|
2009-02-15 06:10:59 +00:00
|
|
|
int length;
|
|
|
|
int delta;
|
|
|
|
int length_left;
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
if (!xl) { // xl = 0, so we move along yl
|
2009-03-22 22:02:25 +00:00
|
|
|
posvar = &start.y;
|
2009-02-15 06:10:59 +00:00
|
|
|
length = yl;
|
2009-02-15 22:33:36 +00:00
|
|
|
delta = (yl < 0) ? -dbl_stepwidth : dbl_stepwidth;
|
2009-02-15 06:10:59 +00:00
|
|
|
} else {
|
2009-02-21 08:47:07 +00:00
|
|
|
assert(!yl); // We don't do diagonals; that's not needed ATM.
|
2009-03-22 22:02:25 +00:00
|
|
|
posvar = &start.x;
|
2009-02-15 06:10:59 +00:00
|
|
|
length = xl;
|
2009-02-15 22:33:36 +00:00
|
|
|
delta = (xl < 0) ? -dbl_stepwidth : dbl_stepwidth;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
length_left = length;
|
|
|
|
|
|
|
|
if (skipone) {
|
|
|
|
length_left -= stepwidth;
|
|
|
|
*posvar += stepwidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
length /= delta;
|
|
|
|
|
|
|
|
length_left -= length * dbl_stepwidth;
|
|
|
|
|
|
|
|
if (xl)
|
|
|
|
xl = linelength;
|
|
|
|
else
|
|
|
|
yl = linelength;
|
|
|
|
|
|
|
|
while (length--) {
|
|
|
|
int retval;
|
2009-02-17 19:15:37 +00:00
|
|
|
Common::Point nextpos = Common::Point(start.x + xl, start.y + yl);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
if ((retval = driver->drawLine(start, nextpos, color, line_mode, GFX_LINE_STYLE_NORMAL))) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Failed to draw partial stippled line (%d,%d) -- (%d,%d)", start.x, start.y, nextpos.x, nextpos.y);
|
2009-02-15 06:10:59 +00:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
*posvar += delta;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (length_left) {
|
|
|
|
int retval;
|
2009-02-17 19:15:37 +00:00
|
|
|
Common::Point nextpos;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (length_left > stepwidth)
|
|
|
|
length_left = stepwidth;
|
|
|
|
|
|
|
|
if (xl)
|
|
|
|
xl = length_left;
|
|
|
|
else
|
|
|
|
if (yl)
|
|
|
|
yl = length_left;
|
|
|
|
|
2009-02-17 19:15:37 +00:00
|
|
|
nextpos = Common::Point(start.x + xl, start.y + yl);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
if ((retval = driver->drawLine(start, nextpos, color, line_mode, GFX_LINE_STYLE_NORMAL))) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Failed to draw partial stippled line (%d,%d) -- (%d,%d)", start.x, start.y, nextpos.x, nextpos.y);
|
2009-02-15 06:10:59 +00:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
static int _gfxop_draw_line_clipped(GfxState *state, Common::Point start, Common::Point end, gfx_color_t color, gfx_line_mode_t line_mode,
|
2009-02-22 13:11:43 +00:00
|
|
|
gfx_line_style_t line_style) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int retval;
|
2009-02-21 08:47:07 +00:00
|
|
|
int skipone = (start.x ^ end.y) & 1; // Used for simulated line stippling
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-25 19:28:20 +00:00
|
|
|
_gfxop_full_pointer_refresh(state);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
// First, make sure that the line is normalized
|
2009-02-15 06:10:59 +00:00
|
|
|
if (start.y > end.y) {
|
2009-02-17 19:15:37 +00:00
|
|
|
Common::Point swap = start;
|
2009-02-15 06:10:59 +00:00
|
|
|
start = end;
|
|
|
|
end = swap;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (start.x < state->clip_zone.x
|
2009-02-15 22:33:36 +00:00
|
|
|
|| start.y < state->clip_zone.y
|
2009-03-16 00:07:12 +00:00
|
|
|
|| end.x >= (state->clip_zone.x + state->clip_zone.width)
|
|
|
|
|| end.y >= (state->clip_zone.y + state->clip_zone.height))
|
2009-06-06 10:21:48 +00:00
|
|
|
if (point_clip(&start, &end, state->clip_zone, state->driver->getMode()->xfact - 1, state->driver->getMode()->yfact - 1))
|
2009-02-21 08:47:07 +00:00
|
|
|
return GFX_OK; // Clipped off
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (line_style == GFX_LINE_STYLE_STIPPLED) {
|
|
|
|
if (start.x != end.x && start.y != end.y) {
|
2009-06-08 11:42:13 +00:00
|
|
|
warning("[GFX] Attempt to draw stippled line which is neither an hbar nor a vbar: (%d,%d) -- (%d,%d)", start.x, start.y, end.x, end.y);
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
2009-06-05 18:05:45 +00:00
|
|
|
return simulate_stippled_line_draw(state->driver, skipone, start, end, color, line_mode);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
if ((retval = state->driver->drawLine(start, end, color, line_mode, line_style))) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Failed to draw line (%d,%d) -- (%d,%d)", start.x, start.y, end.x, end.y);
|
2009-02-15 06:10:59 +00:00
|
|
|
return retval;
|
|
|
|
}
|
2009-02-21 08:47:07 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_draw_line(GfxState *state, Common::Point start, Common::Point end,
|
2009-02-22 13:11:43 +00:00
|
|
|
gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int xfact, yfact;
|
|
|
|
|
|
|
|
_gfxop_add_dirty_x(state, gfx_rect(start.x, start.y, end.x - start.x, end.y - start.y));
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
xfact = state->driver->getMode()->xfact;
|
|
|
|
yfact = state->driver->getMode()->yfact;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
draw_line_to_control_map(state, start, end, color);
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
_gfxop_scale_point(&start, state->driver->getMode());
|
|
|
|
_gfxop_scale_point(&end, state->driver->getMode());
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (line_mode == GFX_LINE_MODE_FINE) {
|
|
|
|
start.x += xfact >> 1;
|
|
|
|
start.y += yfact >> 1;
|
|
|
|
|
|
|
|
end.x += xfact >> 1;
|
|
|
|
end.y += yfact >> 1;
|
|
|
|
}
|
2009-03-12 23:23:46 +00:00
|
|
|
|
2009-03-08 20:17:01 +00:00
|
|
|
if (color.visual.parent_index == GFX_COLOR_INDEX_UNMAPPED)
|
2009-03-03 14:27:49 +00:00
|
|
|
gfxop_set_color(state, &color, color);
|
2009-02-15 06:10:59 +00:00
|
|
|
return _gfxop_draw_line_clipped(state, start, end, color, line_mode, line_style);
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_draw_rectangle(GfxState *state, rect_t rect, gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int retval = 0;
|
|
|
|
int xfact, yfact;
|
|
|
|
int x, y, xl, yl;
|
2009-02-17 19:15:37 +00:00
|
|
|
Common::Point upper_left_u, upper_right_u, lower_left_u, lower_right_u;
|
|
|
|
Common::Point upper_left, upper_right, lower_left, lower_right;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-25 19:28:20 +00:00
|
|
|
_gfxop_full_pointer_refresh(state);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
xfact = state->driver->getMode()->xfact;
|
|
|
|
yfact = state->driver->getMode()->yfact;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-19 21:27:01 +00:00
|
|
|
int offset = line_mode == GFX_LINE_MODE_FINE ? 1 : 0;
|
|
|
|
x = rect.x * xfact + (xfact - 1) * offset;
|
|
|
|
y = rect.y * yfact + (yfact - 1) * offset;
|
|
|
|
xl = offset + (rect.width - offset) * xfact;
|
|
|
|
yl = offset + (rect.height - offset) * yfact;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-17 19:15:37 +00:00
|
|
|
upper_left_u = Common::Point(rect.x, rect.y);
|
2009-03-16 00:07:12 +00:00
|
|
|
upper_right_u = Common::Point(rect.x + rect.width, rect.y);
|
|
|
|
lower_left_u = Common::Point(rect.x, rect.y + rect.height);
|
|
|
|
lower_right_u = Common::Point(rect.x + rect.width, rect.y + rect.height);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-17 19:15:37 +00:00
|
|
|
upper_left = Common::Point(x, y);
|
|
|
|
upper_right = Common::Point(x + xl, y);
|
|
|
|
lower_left = Common::Point(x, y + yl);
|
|
|
|
lower_right = Common::Point(x + xl, y + yl);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-22 13:11:43 +00:00
|
|
|
#define PARTIAL_LINE(pt1, pt2) \
|
2009-02-15 06:10:59 +00:00
|
|
|
retval |= _gfxop_draw_line_clipped(state, pt1, pt2, color, line_mode, line_style); \
|
|
|
|
draw_line_to_control_map(state, pt1##_u, pt2##_u, color); \
|
2009-02-21 08:47:07 +00:00
|
|
|
_gfxop_add_dirty_x(state, gfx_rect(pt1##_u.x, pt1##_u.y, pt2##_u.x - pt1##_u.x, pt2##_u.y - pt1##_u.y))
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-15 22:33:36 +00:00
|
|
|
PARTIAL_LINE(upper_left, upper_right);
|
|
|
|
PARTIAL_LINE(upper_right, lower_right);
|
|
|
|
PARTIAL_LINE(lower_right, lower_left);
|
|
|
|
PARTIAL_LINE(lower_left, upper_left);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
#undef PARTIAL_LINE
|
|
|
|
if (retval) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Failed to draw rectangle (%d,%d)+(%d,%d)", rect.x, rect.y, rect.width, rect.height);
|
2009-02-15 06:10:59 +00:00
|
|
|
return retval;
|
|
|
|
}
|
2009-02-21 08:47:07 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define COLOR_MIX(type, dist) ((color1.type * dist) + (color2.type * (1.0 - dist)))
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_draw_box(GfxState *state, rect_t box, gfx_color_t color1, gfx_color_t color2, gfx_box_shade_t shade_type) {
|
2009-06-06 10:21:48 +00:00
|
|
|
GfxDriver *drv = state->driver;
|
2009-02-21 08:47:07 +00:00
|
|
|
int reverse = 0; // switch color1 and color2
|
2009-07-01 20:51:04 +00:00
|
|
|
float mod_offset = 0.0f, mod_breadth = 1.0f; // 0.0 to 1.0: Color adjustment
|
2009-02-15 06:10:59 +00:00
|
|
|
gfx_rectangle_fill_t driver_shade_type;
|
|
|
|
rect_t new_box;
|
|
|
|
|
2009-02-25 19:28:20 +00:00
|
|
|
_gfxop_full_pointer_refresh(state);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-05 18:05:45 +00:00
|
|
|
shade_type = GFX_BOX_SHADE_FLAT;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
_gfxop_add_dirty(state, box);
|
|
|
|
|
|
|
|
if (color1.mask & GFX_MASK_CONTROL) {
|
2009-02-21 08:47:07 +00:00
|
|
|
// Write control block, clipped by 320x200
|
2009-02-15 06:10:59 +00:00
|
|
|
memcpy(&new_box, &box, sizeof(rect_t));
|
|
|
|
_gfxop_clip(&new_box, gfx_rect(0, 0, 320, 200));
|
|
|
|
|
|
|
|
gfx_draw_box_pixmap_i(state->control_map, new_box, color1.control);
|
|
|
|
}
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
_gfxop_scale_rect(&box, state->driver->getMode());
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (!(color1.mask & (GFX_MASK_VISUAL | GFX_MASK_PRIORITY)))
|
2009-02-21 08:47:07 +00:00
|
|
|
return GFX_OK;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
if (box.width <= 1 || box.height <= 1) {
|
2009-06-08 11:42:13 +00:00
|
|
|
debugC(2, kDebugLevelGraphics, "Attempt to draw box with size %dx%d", box.width, box.height);
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(&new_box, &box, sizeof(rect_t));
|
|
|
|
if (_gfxop_clip(&new_box, state->clip_zone))
|
|
|
|
return GFX_OK;
|
|
|
|
|
|
|
|
switch (shade_type) {
|
|
|
|
|
|
|
|
case GFX_BOX_SHADE_FLAT:
|
|
|
|
driver_shade_type = GFX_SHADE_FLAT;
|
|
|
|
break;
|
|
|
|
|
2009-02-15 22:33:36 +00:00
|
|
|
case GFX_BOX_SHADE_LEFT:
|
|
|
|
reverse = 1;
|
2009-02-15 06:10:59 +00:00
|
|
|
case GFX_BOX_SHADE_RIGHT:
|
|
|
|
driver_shade_type = GFX_SHADE_HORIZONTALLY;
|
2009-03-16 00:07:12 +00:00
|
|
|
mod_offset = (float)(((new_box.x - box.x) * 1.0) / (box.width * 1.0));
|
|
|
|
mod_breadth = (float)((new_box.width * 1.0) / (box.width * 1.0));
|
2009-02-15 06:10:59 +00:00
|
|
|
break;
|
|
|
|
|
2009-02-15 22:33:36 +00:00
|
|
|
case GFX_BOX_SHADE_UP:
|
|
|
|
reverse = 1;
|
2009-02-15 06:10:59 +00:00
|
|
|
case GFX_BOX_SHADE_DOWN:
|
|
|
|
driver_shade_type = GFX_SHADE_VERTICALLY;
|
2009-03-16 00:07:12 +00:00
|
|
|
mod_offset = (float)(((new_box.y - box.y) * 1.0) / (box.height * 1.0));
|
|
|
|
mod_breadth = (float)((new_box.height * 1.0) / (box.height * 1.0));
|
2009-02-15 06:10:59 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Invalid shade type: %d", shade_type);
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (reverse)
|
2009-02-15 22:33:36 +00:00
|
|
|
mod_offset = (float)(1.0 - (mod_offset + mod_breadth));
|
2009-02-21 08:47:07 +00:00
|
|
|
// Reverse offset if we have to interpret colors inversely
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-01 04:07:04 +00:00
|
|
|
if (shade_type == GFX_BOX_SHADE_FLAT) {
|
2009-03-08 13:43:11 +00:00
|
|
|
color1.priority = 0;
|
|
|
|
color1.control = 0;
|
2009-03-08 20:17:01 +00:00
|
|
|
if (color1.visual.parent_index == GFX_COLOR_INDEX_UNMAPPED)
|
2009-03-03 14:27:49 +00:00
|
|
|
gfxop_set_color(state, &color1, color1);
|
2009-06-06 10:21:48 +00:00
|
|
|
return drv->drawFilledRect(new_box, color1, color1, GFX_SHADE_FLAT);
|
2009-03-01 04:07:04 +00:00
|
|
|
} else {
|
2009-02-15 06:10:59 +00:00
|
|
|
if (PALETTE_MODE) {
|
2009-06-08 11:42:13 +00:00
|
|
|
warning("[GFX] Attempting to draw shaded box in palette mode");
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
|
|
|
|
2009-03-08 20:17:01 +00:00
|
|
|
gfx_color_t draw_color1; // CHECKME
|
|
|
|
gfx_color_t draw_color2;
|
|
|
|
gfxop_set_color(state, &draw_color1, 0, 0, 0, 0, 0, 0);
|
|
|
|
gfxop_set_color(state, &draw_color2, 0, 0, 0, 0, 0, 0);
|
2009-02-15 23:49:42 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
draw_color1.mask = draw_color2.mask = color1.mask;
|
|
|
|
draw_color1.priority = draw_color2.priority = color1.priority;
|
|
|
|
|
|
|
|
if (draw_color1.mask & GFX_MASK_VISUAL) {
|
2009-06-06 10:40:32 +00:00
|
|
|
draw_color1.visual.r = (byte) COLOR_MIX(visual.r, mod_offset);
|
|
|
|
draw_color1.visual.g = (byte) COLOR_MIX(visual.g, mod_offset);
|
|
|
|
draw_color1.visual.b = (byte) COLOR_MIX(visual.b, mod_offset);
|
|
|
|
draw_color1.alpha = (byte) COLOR_MIX(alpha, mod_offset);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
mod_offset += mod_breadth;
|
|
|
|
|
2009-06-06 10:40:32 +00:00
|
|
|
draw_color2.visual.r = (byte) COLOR_MIX(visual.r, mod_offset);
|
|
|
|
draw_color2.visual.g = (byte) COLOR_MIX(visual.g, mod_offset);
|
|
|
|
draw_color2.visual.b = (byte) COLOR_MIX(visual.b, mod_offset);
|
|
|
|
draw_color2.alpha = (byte) COLOR_MIX(alpha, mod_offset);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
if (reverse)
|
2009-06-06 10:21:48 +00:00
|
|
|
return drv->drawFilledRect(new_box, draw_color2, draw_color1, driver_shade_type);
|
2009-02-15 06:10:59 +00:00
|
|
|
else
|
2009-06-06 10:21:48 +00:00
|
|
|
return drv->drawFilledRect(new_box, draw_color1, draw_color2, driver_shade_type);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#undef COLOR_MIX
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_fill_box(GfxState *state, rect_t box, gfx_color_t color) {
|
2009-02-15 06:10:59 +00:00
|
|
|
return gfxop_draw_box(state, box, color, color, GFX_BOX_SHADE_FLAT);
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
static int _gfxop_buffer_propagate_box(GfxState *state, rect_t box, gfx_buffer_t buffer) {
|
2009-04-24 10:44:10 +00:00
|
|
|
int err;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
if (_gfxop_clip(&box, gfx_rect(0, 0, 320 * state->driver->getMode()->xfact, 200 * state->driver->getMode()->yfact)))
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_OK;
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
if ((err = state->driver->update(box, Common::Point(box.x, box.y), buffer))) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Error occured while updating region (%d,%d,%d,%d) in buffer %d", box.x, box.y, box.width, box.height, buffer);
|
2009-04-24 10:44:10 +00:00
|
|
|
return err;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
2009-02-21 08:47:07 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-02-22 13:11:43 +00:00
|
|
|
extern int sci0_palette;
|
2009-02-21 08:47:07 +00:00
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_clear_box(GfxState *state, rect_t box) {
|
2009-02-25 19:28:20 +00:00
|
|
|
_gfxop_full_pointer_refresh(state);
|
2009-02-15 06:10:59 +00:00
|
|
|
_gfxop_add_dirty(state, box);
|
|
|
|
DDIRTY(stderr, "[] clearing box %d %d %d %d\n", GFX_PRINT_RECT(box));
|
|
|
|
|
|
|
|
_gfxop_clip(&box, gfx_rect(0, 0, 320, 200));
|
|
|
|
#ifdef PRECISE_PRIORITY_MAP
|
|
|
|
if (state->pic_unscaled)
|
|
|
|
gfx_copy_pixmap_box_i(state->priority_map, state->static_priority_map, box);
|
|
|
|
#endif
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
_gfxop_scale_rect(&box, state->driver->getMode());
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
return _gfxop_buffer_propagate_box(state, box, GFX_BUFFER_BACK);
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_set_visible_map(GfxState *state, gfx_map_mask_t visible_map) {
|
2009-02-15 06:10:59 +00:00
|
|
|
switch (visible_map) {
|
|
|
|
|
|
|
|
case GFX_MASK_VISUAL:
|
|
|
|
state->fullscreen_override = NULL;
|
|
|
|
if (visible_map != state->visible_map) {
|
|
|
|
rect_t rect = gfx_rect(0, 0, 320, 200);
|
|
|
|
gfxop_clear_box(state, rect);
|
|
|
|
gfxop_update_box(state, rect);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GFX_MASK_PRIORITY:
|
|
|
|
state->fullscreen_override = state->priority_map;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GFX_MASK_CONTROL:
|
|
|
|
state->fullscreen_override = state->control_map;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2009-05-31 10:02:16 +00:00
|
|
|
warning("Invalid display map %d selected", visible_map);
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
state->visible_map = visible_map;
|
2009-02-21 08:47:07 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_update(GfxState *state) {
|
2009-07-06 10:39:22 +00:00
|
|
|
int retval = _gfxop_clear_dirty_rec(state, state->_dirtyRects);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (state->fullscreen_override) {
|
2009-02-21 08:47:07 +00:00
|
|
|
// We've been asked to re-draw the active full-screen image, essentially.
|
2009-02-15 06:10:59 +00:00
|
|
|
rect_t rect = gfx_rect(0, 0, 320, 200);
|
2009-06-06 10:21:48 +00:00
|
|
|
gfx_xlate_pixmap(state->fullscreen_override, state->driver->getMode(), GFX_XLATE_FILTER_NONE);
|
2009-02-17 19:15:37 +00:00
|
|
|
gfxop_draw_pixmap(state, state->fullscreen_override, rect, Common::Point(0, 0));
|
2009-02-15 06:10:59 +00:00
|
|
|
retval |= _gfxop_update_box(state, rect);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retval) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Clearing the dirty rectangles failed");
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (state->tag_mode) {
|
2009-02-21 08:47:07 +00:00
|
|
|
// This usually happens after a pic and all resources have been drawn
|
2009-03-17 23:30:57 +00:00
|
|
|
|
2009-03-22 23:11:43 +00:00
|
|
|
state->gfxResMan->freeTaggedResources();
|
2009-03-17 23:30:57 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
state->tag_mode = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_update_box(GfxState *state, rect_t box) {
|
2009-02-15 06:10:59 +00:00
|
|
|
if (state->disable_dirty)
|
|
|
|
_gfxop_update_box(state, box);
|
|
|
|
else
|
|
|
|
_gfxop_add_dirty(state, box);
|
|
|
|
|
|
|
|
return gfxop_update(state);
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_enable_dirty_frames(GfxState *state) {
|
2009-02-15 06:10:59 +00:00
|
|
|
state->disable_dirty = 0;
|
|
|
|
|
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_disable_dirty_frames(GfxState *state) {
|
2009-02-15 06:10:59 +00:00
|
|
|
state->disable_dirty = 1;
|
|
|
|
|
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
// Pointer and IO ops
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_sleep(GfxState *state, uint32 msecs) {
|
2009-02-24 20:33:31 +00:00
|
|
|
uint32 time;
|
2009-02-24 20:50:09 +00:00
|
|
|
const uint32 wakeup_time = g_system->getMillis() + msecs;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-24 20:33:31 +00:00
|
|
|
while (true) {
|
2009-02-25 18:23:28 +00:00
|
|
|
// let backend process events and update the screen
|
|
|
|
gfxop_get_event(state, SCI_EVT_PEEK);
|
|
|
|
g_system->updateScreen();
|
2009-02-21 22:00:24 +00:00
|
|
|
time = g_system->getMillis();
|
2009-02-25 18:23:28 +00:00
|
|
|
if (time + 10 < wakeup_time) {
|
|
|
|
g_system->delayMillis(10);
|
|
|
|
} else {
|
|
|
|
if (time < wakeup_time)
|
|
|
|
g_system->delayMillis(wakeup_time - time);
|
2009-02-24 20:33:31 +00:00
|
|
|
break;
|
2009-02-25 18:23:28 +00:00
|
|
|
}
|
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-02-24 20:33:31 +00:00
|
|
|
return GFX_OK;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
static int _gfxop_set_pointer(GfxState *state, gfx_pixmap_t *pxm, Common::Point *hotspot) {
|
2009-05-24 18:41:19 +00:00
|
|
|
// FIXME: We may have to store this pxm somewhere, as the global palette
|
|
|
|
// may change when a new PIC is loaded. The cursor has to be regenerated
|
|
|
|
// from this pxm at that point. (An alternative might be to ensure the
|
|
|
|
// cursor only uses colours in the static part of the palette?)
|
2009-06-26 22:30:52 +00:00
|
|
|
if (pxm && state->driver->getMode()->palette) {
|
|
|
|
assert(pxm->palette);
|
2009-06-06 10:21:48 +00:00
|
|
|
pxm->palette->mergeInto(state->driver->getMode()->palette);
|
2009-06-26 22:30:52 +00:00
|
|
|
}
|
2009-06-06 10:21:48 +00:00
|
|
|
state->driver->setPointer(pxm, hotspot);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_set_pointer_cursor(GfxState *state, int nr) {
|
2009-02-15 06:10:59 +00:00
|
|
|
if (nr == GFXOP_NO_POINTER)
|
2009-04-24 12:30:57 +00:00
|
|
|
return _gfxop_set_pointer(state, NULL, NULL);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-04-24 12:30:57 +00:00
|
|
|
gfx_pixmap_t *new_pointer = state->gfxResMan->getCursor(nr);
|
|
|
|
|
|
|
|
if (!new_pointer) {
|
2009-06-08 11:42:13 +00:00
|
|
|
warning("[GFX] Attempt to set invalid pointer #%d\n", nr);
|
2009-04-24 12:30:57 +00:00
|
|
|
return GFX_ERROR;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-04-24 12:30:57 +00:00
|
|
|
Common::Point p = Common::Point(new_pointer->xoffset, new_pointer->yoffset);
|
|
|
|
return _gfxop_set_pointer(state, new_pointer, &p);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_set_pointer_view(GfxState *state, int nr, int loop, int cel, Common::Point *hotspot) {
|
2009-05-29 08:25:42 +00:00
|
|
|
int real_loop = loop;
|
|
|
|
int real_cel = cel;
|
|
|
|
// FIXME: For now, don't palettize pointers
|
|
|
|
gfx_pixmap_t *new_pointer = _gfxr_get_cel(state, nr, &real_loop, &real_cel, 0);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-04-24 12:30:57 +00:00
|
|
|
if (!new_pointer) {
|
2009-06-08 11:42:13 +00:00
|
|
|
warning("[GFX] Attempt to set invalid pointer #%d", nr);
|
2009-04-24 12:30:57 +00:00
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (real_loop != loop || real_cel != cel) {
|
2009-06-08 11:42:13 +00:00
|
|
|
debugC(2, kDebugLevelGraphics, "Changed loop/cel from %d/%d to %d/%d in view %d\n", loop, cel, real_loop, real_cel, nr);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-04-24 12:30:57 +00:00
|
|
|
// Eco Quest 1 uses a 1x1 transparent cursor to hide the cursor from the user. Some scalers don't seem to support this.
|
2009-05-15 12:41:27 +00:00
|
|
|
if (new_pointer->width < 2 || new_pointer->height < 2)
|
2009-04-24 12:30:57 +00:00
|
|
|
return _gfxop_set_pointer(state, NULL, NULL);
|
2009-04-23 20:37:41 +00:00
|
|
|
|
2009-04-24 12:30:57 +00:00
|
|
|
if (hotspot)
|
|
|
|
return _gfxop_set_pointer(state, new_pointer, hotspot);
|
|
|
|
else {
|
|
|
|
// Compute hotspot from xoffset/yoffset
|
|
|
|
Common::Point p = Common::Point(new_pointer->xoffset + (new_pointer->width >> 1), new_pointer->yoffset + new_pointer->height - 1);
|
|
|
|
return _gfxop_set_pointer(state, new_pointer, &p);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_set_pointer_position(GfxState *state, Common::Point pos) {
|
2009-02-15 06:10:59 +00:00
|
|
|
state->pointer_pos = pos;
|
|
|
|
|
2009-02-15 22:33:36 +00:00
|
|
|
if (pos.x > 320 || pos.y > 200) {
|
2009-06-08 11:42:13 +00:00
|
|
|
warning("[GFX] Attempt to place pointer at invalid coordinates (%d, %d)", pos.x, pos.y);
|
2009-02-21 08:47:07 +00:00
|
|
|
return 0; // Not fatal
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
g_system->warpMouse(pos.x * state->driver->getMode()->xfact, pos.y * state->driver->getMode()->yfact);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-25 19:28:20 +00:00
|
|
|
_gfxop_full_pointer_refresh(state);
|
2009-02-15 06:10:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define SCANCODE_ROWS_NR 3
|
|
|
|
|
|
|
|
struct scancode_row {
|
|
|
|
int offset;
|
|
|
|
const char *keys;
|
|
|
|
} scancode_rows[SCANCODE_ROWS_NR] = {
|
|
|
|
{0x10, "QWERTYUIOP[]"},
|
|
|
|
{0x1e, "ASDFGHJKL;'\\"},
|
|
|
|
{0x2c, "ZXCVBNM,./"}
|
|
|
|
};
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
static int _gfxop_scancode(int ch) {
|
|
|
|
// Calculates a PC keyboard scancode from a character */
|
2009-02-15 06:10:59 +00:00
|
|
|
int row;
|
|
|
|
int c = toupper((char)ch);
|
|
|
|
|
|
|
|
for (row = 0; row < SCANCODE_ROWS_NR; row++) {
|
|
|
|
const char *keys = scancode_rows[row].keys;
|
|
|
|
int offset = scancode_rows[row].offset;
|
|
|
|
|
|
|
|
while (*keys) {
|
|
|
|
if (*keys == c)
|
|
|
|
return offset << 8;
|
|
|
|
|
|
|
|
offset++;
|
|
|
|
keys++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
return ch;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
int _gfxop_shiftify(int c) {
|
2009-02-15 06:10:59 +00:00
|
|
|
char shifted_numbers[] = ")!@#$%^&*(";
|
2009-02-15 22:33:36 +00:00
|
|
|
|
|
|
|
if (c < 256) {
|
2009-02-15 06:10:59 +00:00
|
|
|
c = toupper((char)c);
|
|
|
|
|
|
|
|
if (c >= 'A' && c <= 'Z')
|
|
|
|
return c;
|
|
|
|
|
|
|
|
if (c >= '0' && c <= '9')
|
|
|
|
return shifted_numbers[c-'0'];
|
2009-02-15 22:33:36 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
switch (c) {
|
2009-02-25 19:52:17 +00:00
|
|
|
case SCI_K_TAB:
|
2009-02-15 22:33:36 +00:00
|
|
|
return SCI_K_SHIFT_TAB;
|
|
|
|
case ']':
|
|
|
|
return '}';
|
|
|
|
case '[':
|
|
|
|
return '{';
|
|
|
|
case '`':
|
|
|
|
return '~';
|
|
|
|
case '-':
|
|
|
|
return '_';
|
|
|
|
case '=':
|
|
|
|
return '+';
|
|
|
|
case ';':
|
|
|
|
return ':';
|
|
|
|
case '\'':
|
|
|
|
return '"';
|
|
|
|
case '\\':
|
|
|
|
return '|';
|
|
|
|
case ',':
|
|
|
|
return '<';
|
|
|
|
case '.':
|
|
|
|
return '>';
|
|
|
|
case '/':
|
|
|
|
return '?';
|
|
|
|
default:
|
2009-02-21 08:47:07 +00:00
|
|
|
return c; // No match
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-04 08:28:20 +00:00
|
|
|
if (c >= SCI_K_F1 && c <= SCI_K_F10)
|
|
|
|
return c + 25;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
static int _gfxop_numlockify(int c) {
|
2009-02-15 06:10:59 +00:00
|
|
|
switch (c) {
|
2009-02-25 19:52:17 +00:00
|
|
|
case SCI_K_DELETE:
|
2009-02-15 22:33:36 +00:00
|
|
|
return '.';
|
2009-02-25 19:52:17 +00:00
|
|
|
case SCI_K_INSERT:
|
2009-02-15 22:33:36 +00:00
|
|
|
return '0';
|
2009-02-25 19:52:17 +00:00
|
|
|
case SCI_K_END:
|
2009-02-15 22:33:36 +00:00
|
|
|
return '1';
|
2009-02-25 19:52:17 +00:00
|
|
|
case SCI_K_DOWN:
|
2009-02-15 22:33:36 +00:00
|
|
|
return '2';
|
2009-02-25 19:52:17 +00:00
|
|
|
case SCI_K_PGDOWN:
|
2009-02-15 22:33:36 +00:00
|
|
|
return '3';
|
2009-02-25 19:52:17 +00:00
|
|
|
case SCI_K_LEFT:
|
2009-02-15 22:33:36 +00:00
|
|
|
return '4';
|
|
|
|
case SCI_K_CENTER:
|
|
|
|
return '5';
|
2009-02-25 19:52:17 +00:00
|
|
|
case SCI_K_RIGHT:
|
2009-02-15 22:33:36 +00:00
|
|
|
return '6';
|
2009-02-25 19:52:17 +00:00
|
|
|
case SCI_K_HOME:
|
2009-02-15 22:33:36 +00:00
|
|
|
return '7';
|
2009-02-25 19:52:17 +00:00
|
|
|
case SCI_K_UP:
|
2009-02-15 22:33:36 +00:00
|
|
|
return '8';
|
2009-02-25 19:52:17 +00:00
|
|
|
case SCI_K_PGUP:
|
2009-02-15 22:33:36 +00:00
|
|
|
return '9';
|
|
|
|
default:
|
2009-02-21 08:47:07 +00:00
|
|
|
return c; // Unchanged
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
static sci_event_t scummvm_get_event(GfxDriver *drv) {
|
2009-05-31 01:11:06 +00:00
|
|
|
static int _modifierStates = 0; // FIXME: Avoid non-const global vars
|
2009-03-07 19:23:32 +00:00
|
|
|
sci_event_t input = { SCI_EVT_NONE, 0, 0, 0 };
|
|
|
|
|
|
|
|
Common::EventManager *em = g_system->getEventManager();
|
|
|
|
Common::Event ev;
|
|
|
|
|
|
|
|
bool found = em->pollEvent(ev);
|
|
|
|
Common::Point p = ev.mouse;
|
|
|
|
|
|
|
|
// Don't generate events for mouse movement
|
|
|
|
while (found && ev.type == Common::EVENT_MOUSEMOVE) {
|
|
|
|
found = em->pollEvent(ev);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found && !ev.synthetic && ev.type != Common::EVENT_MOUSEMOVE) {
|
|
|
|
int modifiers = em->getModifierState();
|
|
|
|
|
|
|
|
// We add the modifier key status to buckybits
|
|
|
|
// SDL sends a keydown event if a modifier key is turned on and a keyup event if it's off
|
|
|
|
//
|
2009-03-07 19:24:31 +00:00
|
|
|
// FIXME: This code is semi-bogus. It only records the modifier key being *pressed*.
|
|
|
|
// It does not track correctly whether capslock etc. is active. To do that, we
|
|
|
|
// would have to record the fact that the modifier was pressed in global var,
|
|
|
|
// and also watch for Common::EVENT_KEYUP events.
|
|
|
|
// But this is still not quite good enough, because not all events might
|
|
|
|
// pass through here (e.g. the GUI might be running with its own event loop).
|
|
|
|
//
|
|
|
|
// The best solution likely would be to add code to the EventManager class
|
|
|
|
// for tracking which keys are pressed and which are not...
|
2009-03-07 19:23:32 +00:00
|
|
|
if (ev.type == Common::EVENT_KEYDOWN || ev.type == Common::EVENT_KEYUP) {
|
2009-03-07 19:24:31 +00:00
|
|
|
switch (ev.kbd.keycode) {
|
2009-03-07 19:23:32 +00:00
|
|
|
case Common::KEYCODE_CAPSLOCK:
|
|
|
|
if (ev.type == Common::EVENT_KEYDOWN) {
|
|
|
|
_modifierStates |= SCI_EVM_CAPSLOCK;
|
|
|
|
} else {
|
|
|
|
_modifierStates &= ~SCI_EVM_CAPSLOCK;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_NUMLOCK:
|
|
|
|
if (ev.type == Common::EVENT_KEYDOWN) {
|
|
|
|
_modifierStates |= SCI_EVM_NUMLOCK;
|
|
|
|
} else {
|
|
|
|
_modifierStates &= ~SCI_EVM_NUMLOCK;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_SCROLLOCK:
|
|
|
|
if (ev.type == Common::EVENT_KEYDOWN) {
|
|
|
|
_modifierStates |= SCI_EVM_SCRLOCK;
|
|
|
|
} else {
|
|
|
|
_modifierStates &= ~SCI_EVM_SCRLOCK;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//TODO: SCI_EVM_INSERT
|
|
|
|
|
|
|
|
input.buckybits =
|
|
|
|
((modifiers & Common::KBD_ALT) ? SCI_EVM_ALT : 0) |
|
|
|
|
((modifiers & Common::KBD_CTRL) ? SCI_EVM_CTRL : 0) |
|
|
|
|
((modifiers & Common::KBD_SHIFT) ? SCI_EVM_LSHIFT | SCI_EVM_RSHIFT : 0) |
|
|
|
|
_modifierStates;
|
|
|
|
|
|
|
|
switch (ev.type) {
|
|
|
|
// Keyboard events
|
|
|
|
case Common::EVENT_KEYDOWN:
|
|
|
|
input.data = ev.kbd.keycode;
|
|
|
|
input.character = ev.kbd.ascii;
|
|
|
|
|
2009-03-11 02:05:49 +00:00
|
|
|
// Debug console
|
2009-06-02 19:03:43 +00:00
|
|
|
if (ev.kbd.flags == Common::KBD_CTRL && ev.kbd.keycode == Common::KEYCODE_d) {
|
|
|
|
// Open debug console
|
2009-07-03 14:22:50 +00:00
|
|
|
Console *con = ((Sci::SciEngine*)g_engine)->getSciDebugger();
|
|
|
|
con->attach();
|
2009-03-11 02:05:49 +00:00
|
|
|
|
|
|
|
// Clear keyboard event
|
|
|
|
input.type = SCI_EVT_NONE;
|
|
|
|
input.character = 0;
|
|
|
|
input.data = 0;
|
|
|
|
input.buckybits = 0;
|
|
|
|
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
2009-03-07 19:23:32 +00:00
|
|
|
if (!(input.data & 0xFF00)) {
|
|
|
|
// Directly accept most common keys without conversion
|
|
|
|
input.type = SCI_EVT_KEYBOARD;
|
|
|
|
if (input.data == Common::KEYCODE_TAB) {
|
|
|
|
// Tab
|
|
|
|
input.type = SCI_EVT_KEYBOARD;
|
|
|
|
input.data = SCI_K_TAB;
|
|
|
|
if (input.buckybits & (SCI_EVM_LSHIFT | SCI_EVM_RSHIFT))
|
|
|
|
input.character = SCI_K_SHIFT_TAB;
|
|
|
|
else
|
|
|
|
input.character = SCI_K_TAB;
|
|
|
|
}
|
|
|
|
} else if ((input.data >= Common::KEYCODE_F1) && input.data <= Common::KEYCODE_F10) {
|
|
|
|
// F1-F10
|
|
|
|
input.type = SCI_EVT_KEYBOARD;
|
|
|
|
// SCI_K_F1 == 59 << 8
|
|
|
|
// SCI_K_SHIFT_F1 == 84 << 8
|
|
|
|
input.data = SCI_K_F1 + ((input.data - Common::KEYCODE_F1)<<8);
|
|
|
|
if (input.buckybits & (SCI_EVM_LSHIFT | SCI_EVM_RSHIFT))
|
2009-06-04 08:28:20 +00:00
|
|
|
input.character = input.data + 25;
|
2009-03-07 19:23:32 +00:00
|
|
|
else
|
|
|
|
input.character = input.data;
|
|
|
|
} else {
|
|
|
|
// Special keys that need conversion
|
|
|
|
input.type = SCI_EVT_KEYBOARD;
|
|
|
|
switch (ev.kbd.keycode) {
|
|
|
|
case Common::KEYCODE_UP:
|
|
|
|
input.data = SCI_K_UP;
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_DOWN:
|
|
|
|
input.data = SCI_K_DOWN;
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_RIGHT:
|
|
|
|
input.data = SCI_K_RIGHT;
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_LEFT:
|
|
|
|
input.data = SCI_K_LEFT;
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_INSERT:
|
|
|
|
input.data = SCI_K_INSERT;
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_HOME:
|
|
|
|
input.data = SCI_K_HOME;
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_END:
|
|
|
|
input.data = SCI_K_END;
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_PAGEUP:
|
|
|
|
input.data = SCI_K_PGUP;
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_PAGEDOWN:
|
|
|
|
input.data = SCI_K_PGDOWN;
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_DELETE:
|
|
|
|
input.data = SCI_K_DELETE;
|
|
|
|
break;
|
|
|
|
// Keypad keys
|
|
|
|
case Common::KEYCODE_KP8: // up
|
|
|
|
if (!(_modifierStates & SCI_EVM_NUMLOCK))
|
|
|
|
input.data = SCI_K_UP;
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_KP2: // down
|
|
|
|
if (!(_modifierStates & SCI_EVM_NUMLOCK))
|
|
|
|
input.data = SCI_K_DOWN;
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_KP6: // right
|
|
|
|
if (!(_modifierStates & SCI_EVM_NUMLOCK))
|
|
|
|
input.data = SCI_K_RIGHT;
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_KP4: // left
|
|
|
|
if (!(_modifierStates & SCI_EVM_NUMLOCK))
|
|
|
|
input.data = SCI_K_LEFT;
|
|
|
|
break;
|
|
|
|
case Common::KEYCODE_KP5: // center
|
|
|
|
if (!(_modifierStates & SCI_EVM_NUMLOCK))
|
|
|
|
input.data = SCI_K_CENTER;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
input.type = SCI_EVT_NONE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
input.character = input.data;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Mouse events
|
|
|
|
case Common::EVENT_LBUTTONDOWN:
|
|
|
|
input.type = SCI_EVT_MOUSE_PRESS;
|
|
|
|
input.data = 1;
|
|
|
|
break;
|
|
|
|
case Common::EVENT_RBUTTONDOWN:
|
|
|
|
input.type = SCI_EVT_MOUSE_PRESS;
|
|
|
|
input.data = 2;
|
|
|
|
break;
|
|
|
|
case Common::EVENT_LBUTTONUP:
|
|
|
|
input.type = SCI_EVT_MOUSE_RELEASE;
|
|
|
|
input.data = 1;
|
|
|
|
break;
|
|
|
|
case Common::EVENT_RBUTTONUP:
|
|
|
|
input.type = SCI_EVT_MOUSE_RELEASE;
|
|
|
|
input.data = 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Misc events
|
|
|
|
case Common::EVENT_QUIT:
|
|
|
|
input.type = SCI_EVT_QUIT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
sci_event_t gfxop_get_event(GfxState *state, unsigned int mask) {
|
2009-07-06 11:10:35 +00:00
|
|
|
//sci_event_t error_event = { SCI_EVT_ERROR, 0, 0, 0 };
|
2009-02-25 18:23:28 +00:00
|
|
|
sci_event_t event = { 0, 0, 0, 0 };
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-25 19:28:20 +00:00
|
|
|
_gfxop_full_pointer_refresh(state);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-25 18:59:00 +00:00
|
|
|
// Update the screen here, since it's called very often
|
|
|
|
g_system->updateScreen();
|
|
|
|
|
2009-02-25 18:23:28 +00:00
|
|
|
// Get all queued events from graphics driver
|
|
|
|
do {
|
2009-03-07 19:23:32 +00:00
|
|
|
event = scummvm_get_event(state->driver);
|
|
|
|
if (event.type != SCI_EVT_NONE)
|
|
|
|
state->_events.push_back(event);
|
2009-02-26 12:10:11 +00:00
|
|
|
} while (event.type != SCI_EVT_NONE);
|
2009-02-25 18:23:28 +00:00
|
|
|
|
|
|
|
// Search for matching event in queue
|
2009-03-07 19:23:32 +00:00
|
|
|
Common::List<sci_event_t>::iterator iter = state->_events.begin();
|
|
|
|
while (iter != state->_events.end() && !((*iter).type & mask))
|
2009-02-25 18:23:28 +00:00
|
|
|
++iter;
|
|
|
|
|
2009-03-07 19:23:32 +00:00
|
|
|
if (iter != state->_events.end()) {
|
2009-02-25 18:23:28 +00:00
|
|
|
// Event found
|
|
|
|
event = *iter;
|
|
|
|
|
|
|
|
// If not peeking at the queue, remove the event
|
|
|
|
if (!(mask & SCI_EVT_PEEK)) {
|
2009-03-07 19:23:32 +00:00
|
|
|
state->_events.erase(iter);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
2009-02-26 12:10:11 +00:00
|
|
|
} else {
|
|
|
|
// No event found: we must return a SCI_EVT_NONE event.
|
|
|
|
|
|
|
|
// Because event.type is SCI_EVT_NONE already here,
|
|
|
|
// there is no need to change it.
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-02-25 19:28:20 +00:00
|
|
|
_gfxop_full_pointer_refresh(state);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-02-18 12:26:37 +00:00
|
|
|
if (event.type == SCI_EVT_KEYBOARD) {
|
2009-02-21 08:47:07 +00:00
|
|
|
// Do we still have to translate the key?
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
event.character = event.data;
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
// Scancodify if appropriate
|
2009-02-15 06:10:59 +00:00
|
|
|
if (event.buckybits & SCI_EVM_ALT)
|
|
|
|
event.character = _gfxop_scancode(event.character);
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
// Shift if appropriate
|
|
|
|
else if (((event.buckybits & (SCI_EVM_RSHIFT | SCI_EVM_LSHIFT)) && !(event.buckybits & SCI_EVM_CAPSLOCK))
|
|
|
|
|| (!(event.buckybits & (SCI_EVM_RSHIFT | SCI_EVM_LSHIFT)) && (event.buckybits & SCI_EVM_CAPSLOCK)))
|
2009-02-15 06:10:59 +00:00
|
|
|
event.character = _gfxop_shiftify(event.character);
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
// Numlockify if appropriate
|
2009-02-15 06:10:59 +00:00
|
|
|
else if (event.buckybits & SCI_EVM_NUMLOCK)
|
|
|
|
event.data = _gfxop_numlockify(event.data);
|
|
|
|
}
|
|
|
|
|
|
|
|
return event;
|
|
|
|
}
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
// View operations
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_lookup_view_get_loops(GfxState *state, int nr) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int loop = 0, cel = 0;
|
|
|
|
gfxr_view_t *view = NULL;
|
|
|
|
|
2009-03-22 23:11:43 +00:00
|
|
|
view = state->gfxResMan->getView(nr, &loop, &cel, 0);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (!view) {
|
2009-06-08 11:42:13 +00:00
|
|
|
warning("[GFX] Attempt to retrieve number of loops from invalid view %d", nr);
|
2009-02-15 06:10:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return view->loops_nr;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_lookup_view_get_cels(GfxState *state, int nr, int loop) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int real_loop = loop, cel = 0;
|
|
|
|
gfxr_view_t *view = NULL;
|
|
|
|
|
2009-03-22 23:11:43 +00:00
|
|
|
view = state->gfxResMan->getView(nr, &real_loop, &cel, 0);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (!view) {
|
2009-06-08 11:42:13 +00:00
|
|
|
warning("[GFX] Attempt to retrieve number of cels from invalid/broken view %d", nr);
|
2009-02-15 06:10:59 +00:00
|
|
|
return 0;
|
|
|
|
} else if (real_loop != loop) {
|
2009-06-08 11:42:13 +00:00
|
|
|
warning("[GFX] Loop number was corrected from %d to %d in view %d", loop, real_loop, nr);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return view->loops[real_loop].cels_nr;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_check_cel(GfxState *state, int nr, int *loop, int *cel) {
|
2009-03-22 23:11:43 +00:00
|
|
|
gfxr_view_t *testView = state->gfxResMan->getView(nr, loop, cel, 0);
|
2009-03-17 23:30:57 +00:00
|
|
|
|
|
|
|
if (!testView) {
|
2009-06-08 11:42:13 +00:00
|
|
|
warning("[GFX] Attempt to verify loop/cel values for invalid view %d", nr);
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_overflow_cel(GfxState *state, int nr, int *loop, int *cel) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int loop_v = *loop;
|
|
|
|
int cel_v = *cel;
|
|
|
|
|
2009-03-22 23:11:43 +00:00
|
|
|
gfxr_view_t *testView = state->gfxResMan->getView(nr, &loop_v, &cel_v, 0);
|
2009-03-17 23:30:57 +00:00
|
|
|
|
|
|
|
if (!testView) {
|
2009-06-08 11:42:13 +00:00
|
|
|
warning("[GFX] Attempt to verify loop/cel values for invalid view %d", nr);
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop_v != *loop)
|
|
|
|
*loop = 0;
|
|
|
|
|
|
|
|
if (loop_v != *loop
|
2009-02-15 22:33:36 +00:00
|
|
|
|| cel_v != *cel)
|
2009-02-15 06:10:59 +00:00
|
|
|
*cel = 0;
|
|
|
|
|
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_get_cel_parameters(GfxState *state, int nr, int loop, int cel, int *width, int *height, Common::Point *offset) {
|
2009-02-15 06:10:59 +00:00
|
|
|
gfxr_view_t *view = NULL;
|
|
|
|
gfx_pixmap_t *pxm = NULL;
|
|
|
|
|
2009-03-22 23:11:43 +00:00
|
|
|
view = state->gfxResMan->getView(nr, &loop, &cel, 0);
|
2009-03-17 23:30:57 +00:00
|
|
|
|
|
|
|
if (!view) {
|
2009-06-08 11:42:13 +00:00
|
|
|
warning("[GFX] Attempt to get cel parameters for invalid view %d", nr);
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
pxm = view->loops[loop].cels[cel];
|
2009-03-16 00:07:12 +00:00
|
|
|
*width = pxm->index_width;
|
|
|
|
*height = pxm->index_height;
|
2009-02-15 06:10:59 +00:00
|
|
|
offset->x = pxm->xoffset;
|
|
|
|
offset->y = pxm->yoffset;
|
|
|
|
|
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
static int _gfxop_draw_cel_buffer(GfxState *state, int nr, int loop, int cel, Common::Point pos, gfx_color_t color, int static_buf, int palette) {
|
2009-02-15 22:33:36 +00:00
|
|
|
int priority = (color.mask & GFX_MASK_PRIORITY) ? color.priority : -1;
|
|
|
|
int control = (color.mask & GFX_MASK_CONTROL) ? color.control : -1;
|
2009-02-15 06:10:59 +00:00
|
|
|
gfxr_view_t *view = NULL;
|
|
|
|
gfx_pixmap_t *pxm = NULL;
|
|
|
|
int old_x, old_y;
|
|
|
|
|
2009-03-22 23:11:43 +00:00
|
|
|
view = state->gfxResMan->getView(nr, &loop, &cel, palette);
|
2009-03-17 23:30:57 +00:00
|
|
|
|
|
|
|
if (!view) {
|
2009-06-08 11:42:13 +00:00
|
|
|
warning("[GFX] Attempt to draw loop/cel %d/%d in invalid view %d\n", loop, cel, nr);
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
|
|
|
pxm = view->loops[loop].cels[cel];
|
|
|
|
|
|
|
|
old_x = pos.x -= pxm->xoffset;
|
|
|
|
old_y = pos.y -= pxm->yoffset;
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
pos.x *= state->driver->getMode()->xfact;
|
|
|
|
pos.y *= state->driver->getMode()->yfact;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (!static_buf)
|
2009-03-16 00:07:12 +00:00
|
|
|
_gfxop_add_dirty(state, gfx_rect(old_x, old_y, pxm->index_width, pxm->index_height));
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
return _gfxop_draw_pixmap(state->driver, pxm, priority, control, gfx_rect(0, 0, pxm->width, pxm->height),
|
|
|
|
gfx_rect(pos.x, pos.y, pxm->width, pxm->height), state->clip_zone, static_buf , state->control_map,
|
2009-02-21 08:47:07 +00:00
|
|
|
static_buf ? state->static_priority_map : state->priority_map);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_draw_cel(GfxState *state, int nr, int loop, int cel, Common::Point pos, gfx_color_t color, int palette) {
|
2009-02-15 06:10:59 +00:00
|
|
|
return _gfxop_draw_cel_buffer(state, nr, loop, cel, pos, color, 0, palette);
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_draw_cel_static(GfxState *state, int nr, int loop, int cel, Common::Point pos, gfx_color_t color, int palette) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int retval;
|
|
|
|
rect_t oldclip = state->clip_zone;
|
|
|
|
|
|
|
|
state->clip_zone = gfx_rect_fullscreen;
|
2009-06-06 10:21:48 +00:00
|
|
|
_gfxop_scale_rect(&(state->clip_zone), state->driver->getMode());
|
2009-02-21 08:47:07 +00:00
|
|
|
retval = gfxop_draw_cel_static_clipped(state, nr, loop, cel, pos, color, palette);
|
|
|
|
// Except that the area it's clipped against is... unusual ;-)
|
2009-02-15 06:10:59 +00:00
|
|
|
state->clip_zone = oldclip;
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_draw_cel_static_clipped(GfxState *state, int nr, int loop, int cel, Common::Point pos, gfx_color_t color, int palette) {
|
2009-02-15 06:10:59 +00:00
|
|
|
return _gfxop_draw_cel_buffer(state, nr, loop, cel, pos, color, 1, palette);
|
|
|
|
}
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
// Pic operations
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
static int _gfxop_set_pic(GfxState *state) {
|
2009-02-15 06:10:59 +00:00
|
|
|
gfx_copy_pixmap_box_i(state->control_map, state->pic->control_map, gfx_rect(0, 0, 320, 200));
|
2009-02-15 22:33:36 +00:00
|
|
|
gfx_copy_pixmap_box_i(state->priority_map, state->pic_unscaled->priority_map, gfx_rect(0, 0, 320, 200));
|
2009-02-15 06:10:59 +00:00
|
|
|
gfx_copy_pixmap_box_i(state->static_priority_map, state->pic_unscaled->priority_map, gfx_rect(0, 0, 320, 200));
|
|
|
|
|
2009-05-24 18:41:19 +00:00
|
|
|
// Reset global palette to this PIC's palette
|
|
|
|
// FIXME: The _gfxop_install_pixmap call below updates the OSystem palette.
|
|
|
|
// This is too soon, since it causes brief palette corruption until the
|
|
|
|
// screen is updated too. (Possibly related: EngineState::pic_not_valid .)
|
2009-07-16 12:43:42 +00:00
|
|
|
if (state->pic->visual_map->palette && state->driver->getMode()->palette) {
|
2009-06-26 22:30:52 +00:00
|
|
|
state->pic->visual_map->palette->forceInto(state->driver->getMode()->palette);
|
2009-07-16 08:13:08 +00:00
|
|
|
_gfxop_install_pixmap(state->driver, state->pic->visual_map);
|
|
|
|
}
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-04-01 20:32:45 +00:00
|
|
|
#ifdef CUSTOM_GRAPHICS_OPTIONS
|
2009-02-15 06:10:59 +00:00
|
|
|
if (state->options->pic0_unscaled)
|
2009-04-01 20:32:45 +00:00
|
|
|
#endif
|
2009-06-06 10:21:48 +00:00
|
|
|
state->pic->priority_map = gfx_pixmap_scale_index_data(state->pic->priority_map, state->driver->getMode());
|
|
|
|
return state->driver->setStaticBuffer(state->pic->visual_map, state->pic->priority_map);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int *gfxop_get_pic_metainfo(GfxState *state) {
|
2009-03-14 00:05:01 +00:00
|
|
|
return (state->pic) ? state->pic->priorityTable : NULL;
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_new_pic(GfxState *state, int nr, int flags, int default_palette) {
|
2009-03-22 23:11:43 +00:00
|
|
|
state->gfxResMan->tagResources();
|
2009-02-15 06:10:59 +00:00
|
|
|
state->tag_mode = 1;
|
|
|
|
state->palette_nr = default_palette;
|
2009-03-22 23:11:43 +00:00
|
|
|
state->pic = state->gfxResMan->getPic(nr, GFX_MASK_VISUAL, flags, default_palette, true);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
if (state->driver->getMode()->xfact == 1 && state->driver->getMode()->yfact == 1) {
|
2009-02-15 06:10:59 +00:00
|
|
|
state->pic_unscaled = state->pic;
|
2009-03-17 21:08:33 +00:00
|
|
|
} else {
|
2009-06-26 23:04:46 +00:00
|
|
|
state->pic_unscaled = state->gfxResMan->getPic(nr, GFX_MASK_VISUAL, flags, default_palette, false);
|
2009-03-17 21:08:33 +00:00
|
|
|
}
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (!state->pic || !state->pic_unscaled) {
|
2009-07-06 10:39:22 +00:00
|
|
|
warning("Could not retrieve background pic %d", nr);
|
2009-02-15 06:10:59 +00:00
|
|
|
if (state->pic) {
|
2009-07-06 10:39:22 +00:00
|
|
|
warning(" -- Inconsistency: scaled pic _was_ retrieved!");
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (state->pic_unscaled) {
|
2009-07-06 10:39:22 +00:00
|
|
|
warning(" -- Inconsistency: unscaled pic _was_ retrieved!");
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Error occured in gfxop_new_pic()");
|
2009-02-15 06:10:59 +00:00
|
|
|
state->pic = state->pic_unscaled = NULL;
|
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
state->pic_nr = nr;
|
|
|
|
|
|
|
|
return _gfxop_set_pic(state);
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_add_to_pic(GfxState *state, int nr, int flags, int default_palette) {
|
2009-02-15 06:10:59 +00:00
|
|
|
if (!state->pic) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Attempt to add to pic with no pic active");
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
|
|
|
|
2009-03-22 23:11:43 +00:00
|
|
|
state->pic = state->gfxResMan->addToPic(state->pic_nr, nr, flags, state->palette_nr, default_palette);
|
2009-03-17 23:30:57 +00:00
|
|
|
|
|
|
|
if (!state->pic) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Could not add pic #%d to pic #%d", state->pic_nr, nr);
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
2009-03-17 23:30:57 +00:00
|
|
|
|
2009-03-22 23:11:43 +00:00
|
|
|
state->pic_unscaled = state->gfxResMan->addToPic(state->pic_nr, nr, flags, state->palette_nr, default_palette);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
return _gfxop_set_pic(state);
|
|
|
|
}
|
|
|
|
|
2009-02-21 08:47:07 +00:00
|
|
|
// Text operations
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-12 23:23:46 +00:00
|
|
|
// FIXME: only the resstate member of state is used -- inline the reference by:
|
2009-04-27 11:12:08 +00:00
|
|
|
// replacing GfxState* state parameter with gfx_resstate_t* gfxResourceState and adjust callers accordingly
|
|
|
|
int gfxop_get_font_height(GfxState *state, int font_nr) {
|
2009-02-15 06:10:59 +00:00
|
|
|
gfx_bitmap_font_t *font;
|
|
|
|
|
2009-03-22 23:11:43 +00:00
|
|
|
font = state->gfxResMan->getFont(font_nr);
|
2009-03-17 21:08:33 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
if (!font)
|
|
|
|
return GFX_ERROR;
|
|
|
|
|
|
|
|
return font->line_height;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_get_text_params(GfxState *state, int font_nr, const char *text, int maxwidth, int *width, int *height, int text_flags,
|
2009-02-21 08:47:07 +00:00
|
|
|
int *lines_nr, int *lineheight, int *lastline_width) {
|
2009-04-28 12:32:59 +00:00
|
|
|
Common::Array<TextFragment> fragments;
|
|
|
|
bool textsplits;
|
2009-02-15 06:10:59 +00:00
|
|
|
gfx_bitmap_font_t *font;
|
|
|
|
|
2009-03-22 23:11:43 +00:00
|
|
|
font = state->gfxResMan->getFont(font_nr);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (!font) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Attempt to calculate text size with invalid font #%d", font_nr);
|
2009-02-15 06:10:59 +00:00
|
|
|
*width = *height = 0;
|
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
|
|
|
|
2009-04-01 20:32:45 +00:00
|
|
|
#ifdef CUSTOM_GRAPHICS_OPTIONS
|
2009-04-28 12:32:59 +00:00
|
|
|
textsplits = gfxr_font_calculate_size(fragments, font, maxwidth, text, width, height, lineheight, lastline_width,
|
2009-02-21 08:47:07 +00:00
|
|
|
(state->options->workarounds & GFX_WORKAROUND_WHITESPACE_COUNT) | text_flags);
|
2009-04-01 20:32:45 +00:00
|
|
|
#else
|
2009-04-28 12:32:59 +00:00
|
|
|
textsplits = gfxr_font_calculate_size(fragments, font, maxwidth, text, width, height, lineheight, lastline_width, text_flags);
|
2009-04-01 20:32:45 +00:00
|
|
|
#endif
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (!textsplits) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Could not calculate text size");
|
2009-02-15 06:10:59 +00:00
|
|
|
*width = *height = 0;
|
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
|
|
|
|
2009-04-28 12:32:59 +00:00
|
|
|
if (lines_nr)
|
|
|
|
*lines_nr = fragments.size();
|
2009-02-21 08:47:07 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-04-27 14:21:39 +00:00
|
|
|
TextHandle *gfxop_new_text(GfxState *state, int font_nr, const Common::String &text, int maxwidth, gfx_alignment_t halign,
|
2009-02-21 08:47:07 +00:00
|
|
|
gfx_alignment_t valign, gfx_color_t color1, gfx_color_t color2, gfx_color_t bg_color, int flags) {
|
2009-04-27 14:21:39 +00:00
|
|
|
TextHandle *handle;
|
2009-02-15 23:49:42 +00:00
|
|
|
gfx_bitmap_font_t *font;
|
2009-04-28 12:32:59 +00:00
|
|
|
int err = 0;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-03 14:27:49 +00:00
|
|
|
// mapping text colors to palette
|
2009-04-24 10:44:10 +00:00
|
|
|
err |= gfxop_set_color(state, &color1, color1);
|
|
|
|
err |= gfxop_set_color(state, &color2, color2);
|
|
|
|
err |= gfxop_set_color(state, &bg_color, bg_color);
|
|
|
|
if (err) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Unable to set up colors");
|
2009-03-12 23:23:46 +00:00
|
|
|
return NULL;
|
2009-03-03 14:27:49 +00:00
|
|
|
}
|
2009-03-12 23:23:46 +00:00
|
|
|
|
2009-03-22 23:11:43 +00:00
|
|
|
font = state->gfxResMan->getFont(font_nr);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (!font) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Attempt to draw text with invalid font #%d", font_nr);
|
2009-02-15 06:10:59 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-04-27 14:21:39 +00:00
|
|
|
handle = new TextHandle();
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-04-27 14:21:39 +00:00
|
|
|
handle->_text = text;
|
2009-02-15 06:10:59 +00:00
|
|
|
handle->halign = halign;
|
|
|
|
handle->valign = valign;
|
|
|
|
handle->line_height = font->line_height;
|
|
|
|
|
2009-04-28 12:32:59 +00:00
|
|
|
bool result;
|
2009-04-01 20:32:45 +00:00
|
|
|
#ifdef CUSTOM_GRAPHICS_OPTIONS
|
2009-04-28 12:32:59 +00:00
|
|
|
result = gfxr_font_calculate_size(handle->lines, font, maxwidth, handle->_text.c_str(), &(handle->width), &(handle->height),
|
2009-02-21 08:47:07 +00:00
|
|
|
NULL, NULL, ((state->options->workarounds & GFX_WORKAROUND_WHITESPACE_COUNT) ?
|
2009-03-25 17:51:22 +00:00
|
|
|
kFontCountWhitespace : 0) | flags);
|
2009-04-01 20:32:45 +00:00
|
|
|
#else
|
2009-04-28 12:32:59 +00:00
|
|
|
result = gfxr_font_calculate_size(handle->lines, font, maxwidth, handle->_text.c_str(), &(handle->width), &(handle->height),
|
2009-04-01 20:32:45 +00:00
|
|
|
NULL, NULL, flags);
|
|
|
|
#endif
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-04-28 12:32:59 +00:00
|
|
|
if (!result) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Could not calculate text parameters in font #%d", font_nr);
|
2009-04-27 14:21:39 +00:00
|
|
|
delete handle;
|
2009-02-15 06:10:59 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-03-25 17:51:22 +00:00
|
|
|
if (flags & kFontNoNewlines) {
|
2009-04-28 12:32:59 +00:00
|
|
|
handle->lines.resize(1);
|
|
|
|
handle->lines[0].length = text.size();
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-04-28 12:32:59 +00:00
|
|
|
handle->text_pixmaps.resize(handle->lines.size());
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-04-28 12:32:59 +00:00
|
|
|
for (uint i = 0; i < handle->lines.size(); i++) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int chars_nr = handle->lines[i].length;
|
|
|
|
|
|
|
|
handle->text_pixmaps[i] = gfxr_draw_font(font, handle->lines[i].offset, chars_nr,
|
2009-03-03 14:27:49 +00:00
|
|
|
(color1.mask & GFX_MASK_VISUAL) ? &color1.visual : NULL,
|
|
|
|
(color2.mask & GFX_MASK_VISUAL) ? &color2.visual : NULL,
|
|
|
|
(bg_color.mask & GFX_MASK_VISUAL) ? &bg_color.visual : NULL);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (!handle->text_pixmaps[i]) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Failed to draw text pixmap for line %d/%d", i, handle->lines.size());
|
2009-04-27 14:21:39 +00:00
|
|
|
delete handle;
|
2009-02-15 06:10:59 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
handle->font = font;
|
|
|
|
|
2009-02-15 22:33:36 +00:00
|
|
|
handle->priority = (color1.mask & GFX_MASK_PRIORITY) ? color1.priority : -1;
|
|
|
|
handle->control = (color1.mask & GFX_MASK_CONTROL) ? color1.control : -1;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
2009-04-27 14:21:39 +00:00
|
|
|
int gfxop_free_text(GfxState *state, TextHandle *handle) {
|
|
|
|
delete handle;
|
2009-02-21 08:47:07 +00:00
|
|
|
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-04-27 14:21:39 +00:00
|
|
|
TextHandle::TextHandle() {
|
|
|
|
line_height = 0;
|
|
|
|
font = 0;
|
|
|
|
|
|
|
|
width = height = 0;
|
|
|
|
|
|
|
|
priority = control = 0;
|
|
|
|
halign = valign = ALIGN_BOTTOM;
|
|
|
|
}
|
|
|
|
|
|
|
|
TextHandle::~TextHandle() {
|
2009-04-28 12:32:59 +00:00
|
|
|
for (uint j = 0; j < text_pixmaps.size(); j++)
|
|
|
|
if (text_pixmaps[j])
|
|
|
|
gfx_free_pixmap(text_pixmaps[j]);
|
2009-04-27 14:21:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int gfxop_draw_text(GfxState *state, TextHandle *handle, rect_t zone) {
|
2009-02-15 06:10:59 +00:00
|
|
|
int line_height;
|
|
|
|
rect_t pos;
|
2009-02-25 19:28:20 +00:00
|
|
|
_gfxop_full_pointer_refresh(state);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
if (!handle) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Attempt to draw text with NULL handle");
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
|
|
|
|
2009-04-28 12:32:59 +00:00
|
|
|
if (handle->lines.empty()) {
|
2009-06-08 11:42:13 +00:00
|
|
|
debugC(2, kDebugLevelGraphics, "Skipping draw_text operation because number of lines is zero\n");
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
_gfxop_scale_rect(&zone, state->driver->getMode());
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
line_height = handle->line_height * state->driver->getMode()->yfact;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
pos.y = zone.y;
|
|
|
|
|
|
|
|
switch (handle->valign) {
|
|
|
|
|
|
|
|
case ALIGN_TOP:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ALIGN_CENTER:
|
2009-04-28 12:32:59 +00:00
|
|
|
pos.y += (zone.height - (line_height * handle->lines.size())) >> 1;
|
2009-02-15 06:10:59 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ALIGN_BOTTOM:
|
2009-04-28 12:32:59 +00:00
|
|
|
pos.y += (zone.height - (line_height * handle->lines.size()));
|
2009-02-15 06:10:59 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Invalid vertical alignment %d", handle->valign);
|
2009-02-21 08:47:07 +00:00
|
|
|
return GFX_FATAL; // Internal error...
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-04-28 12:32:59 +00:00
|
|
|
for (uint i = 0; i < handle->lines.size(); i++) {
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
gfx_pixmap_t *pxm = handle->text_pixmaps[i];
|
|
|
|
|
|
|
|
if (!pxm->data) {
|
2009-04-01 20:32:45 +00:00
|
|
|
#ifdef CUSTOM_GRAPHICS_OPTIONS
|
2009-06-06 10:21:48 +00:00
|
|
|
gfx_xlate_pixmap(pxm, state->driver->getMode(), state->options->text_xlate_filter);
|
2009-04-01 20:32:45 +00:00
|
|
|
#else
|
2009-06-06 10:21:48 +00:00
|
|
|
gfx_xlate_pixmap(pxm, state->driver->getMode(), GFX_XLATE_FILTER_NONE);
|
2009-04-01 20:32:45 +00:00
|
|
|
#endif
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
if (!pxm) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Could not find text pixmap %d/%d", i, handle->lines.size());
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
pos.x = zone.x;
|
|
|
|
|
|
|
|
switch (handle->halign) {
|
|
|
|
|
|
|
|
case ALIGN_LEFT:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ALIGN_CENTER:
|
2009-03-16 00:07:12 +00:00
|
|
|
pos.x += (zone.width - pxm->width) >> 1;
|
2009-02-15 06:10:59 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ALIGN_RIGHT:
|
2009-03-16 00:07:12 +00:00
|
|
|
pos.x += (zone.width - pxm->width);
|
2009-02-15 06:10:59 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Invalid vertical alignment %d", handle->valign);
|
2009-02-21 08:47:07 +00:00
|
|
|
return GFX_FATAL; // Internal error...
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
pos.width = pxm->width;
|
|
|
|
pos.height = pxm->height;
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
_gfxop_add_dirty(state, pos);
|
|
|
|
_gfxop_draw_pixmap(state->driver, pxm, handle->priority, handle->control,
|
2009-03-16 00:07:12 +00:00
|
|
|
gfx_rect(0, 0, pxm->width, pxm->height), pos, state->clip_zone, 0, state->control_map, state->priority_map);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
pos.y += line_height;
|
|
|
|
}
|
|
|
|
|
|
|
|
return GFX_OK;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
gfx_pixmap_t *gfxop_grab_pixmap(GfxState *state, rect_t area) {
|
2009-02-15 06:10:59 +00:00
|
|
|
gfx_pixmap_t *pixmap = NULL;
|
2009-02-21 08:47:07 +00:00
|
|
|
rect_t resultzone; // Ignored for this application
|
2009-02-25 19:28:20 +00:00
|
|
|
_gfxop_full_pointer_refresh(state);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
_gfxop_scale_rect(&area, state->driver->getMode());
|
2009-03-16 00:07:12 +00:00
|
|
|
if (_gfxop_grab_pixmap(state, &pixmap, area.x, area.y, area.width, area.height, 0, &resultzone))
|
2009-02-21 08:47:07 +00:00
|
|
|
return NULL; // area CUT the visual screen had a null or negative size
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
return pixmap;
|
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_draw_pixmap(GfxState *state, gfx_pixmap_t *pxm, rect_t zone, Common::Point pos) {
|
2009-02-15 06:10:59 +00:00
|
|
|
rect_t target;
|
|
|
|
|
|
|
|
if (!pxm) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Attempt to draw NULL pixmap");
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
|
|
|
|
2009-02-25 19:28:20 +00:00
|
|
|
_gfxop_full_pointer_refresh(state);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-03-16 00:07:12 +00:00
|
|
|
target = gfx_rect(pos.x, pos.y, zone.width, zone.height);
|
2009-02-15 06:10:59 +00:00
|
|
|
|
|
|
|
_gfxop_add_dirty(state, target);
|
|
|
|
|
|
|
|
if (!pxm) {
|
2009-07-06 10:39:22 +00:00
|
|
|
error("Attempt to draw_pixmap with pxm=NULL");
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_ERROR;
|
|
|
|
}
|
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
_gfxop_scale_rect(&zone, state->driver->getMode());
|
|
|
|
_gfxop_scale_rect(&target, state->driver->getMode());
|
2009-02-15 06:10:59 +00:00
|
|
|
|
2009-06-06 10:21:48 +00:00
|
|
|
return _gfxop_draw_pixmap(state->driver, pxm, -1, -1, zone, target, gfx_rect(0, 0, 320*state->driver->getMode()->xfact,
|
|
|
|
200*state->driver->getMode()->yfact), 0, NULL, NULL);
|
2009-02-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
2009-04-27 11:12:08 +00:00
|
|
|
int gfxop_free_pixmap(GfxState *state, gfx_pixmap_t *pxm) {
|
2009-03-17 21:08:33 +00:00
|
|
|
gfx_free_pixmap(pxm);
|
2009-02-15 06:10:59 +00:00
|
|
|
return GFX_OK;
|
|
|
|
}
|
2009-02-21 10:23:36 +00:00
|
|
|
|
|
|
|
} // End of namespace Sci
|