From 66bbf336c6af7353ef0aeed58002c46543b30635 Mon Sep 17 00:00:00 2001 From: rubidium Date: Tue, 2 Jan 2007 19:19:48 +0000 Subject: (svn r7759) -Merge: makefile rewrite. This merge features: - A proper ./configure, so everything needs to be configured only once, not for every make. - Usage of makedepend when available. This greatly reduces the time needed for generating the dependencies. - A generator for all project files. There is a single file with sources, which is used to generate Makefiles and the project files for MSVC. - Proper support for OSX universal binaries. - Object files for non-MSVC compiles are also placed in separate directories, making is faster to switch between debug and release compiles and it does not touch the directory with the source files. - Functionality to make a bundle of all needed files for for example a nightly or distribution of a binary with all needed GRFs and language files. Note: as this merge moves almost all files, it is recommended to make a backup of your working copy before updating your working copy. --- gfx.c | 2025 ----------------------------------------------------------------- 1 file changed, 2025 deletions(-) delete mode 100644 gfx.c (limited to 'gfx.c') diff --git a/gfx.c b/gfx.c deleted file mode 100644 index 1d48fa25d..000000000 --- a/gfx.c +++ /dev/null @@ -1,2025 +0,0 @@ -/* $Id$ */ - -#include "stdafx.h" -#include "openttd.h" -#include "functions.h" -#include "macros.h" -#include "spritecache.h" -#include "strings.h" -#include "string.h" -#include "gfx.h" -#include "table/palettes.h" -#include "table/sprites.h" -#include "hal.h" -#include "variables.h" -#include "table/control_codes.h" -#include "fontcache.h" -#include "genworld.h" -#include "debug.h" - -#ifdef _DEBUG -bool _dbg_screen_rect; -#endif - -Colour _cur_palette[256]; -byte _stringwidth_table[FS_END][224]; - -static void GfxMainBlitter(const Sprite *sprite, int x, int y, int mode); - -FontSize _cur_fontsize; -static FontSize _last_fontsize; -static Pixel _cursor_backup[64 * 64]; -static Rect _invalid_rect; -static const byte *_color_remap_ptr; -static byte _string_colorremap[3]; - -#define DIRTY_BYTES_PER_LINE (MAX_SCREEN_WIDTH / 64) -static byte _dirty_blocks[DIRTY_BYTES_PER_LINE * MAX_SCREEN_HEIGHT / 8]; - -void memcpy_pitch(void *dst, void *src, int w, int h, int srcpitch, int dstpitch) -{ - byte *dstp = (byte*)dst; - byte *srcp = (byte*)src; - - assert(h >= 0); - for (; h != 0; --h) { - memcpy(dstp, srcp, w); - dstp += dstpitch; - srcp += srcpitch; - } -} - -void GfxScroll(int left, int top, int width, int height, int xo, int yo) -{ - const Pixel *src; - Pixel *dst; - int p; - int ht; - - if (xo == 0 && yo == 0) return; - - if (_cursor.visible) UndrawMouseCursor(); - UndrawTextMessage(); - - p = _screen.pitch; - - if (yo > 0) { - // Calculate pointers - dst = _screen.dst_ptr + (top + height - 1) * p + left; - src = dst - yo * p; - - // Decrease height and increase top - top += yo; - height -= yo; - assert(height > 0); - - // Adjust left & width - if (xo >= 0) { - dst += xo; - left += xo; - width -= xo; - } else { - src -= xo; - width += xo; - } - - for (ht = height; ht > 0; --ht) { - memcpy(dst, src, width); - src -= p; - dst -= p; - } - } else { - // Calculate pointers - dst = _screen.dst_ptr + top * p + left; - src = dst - yo * p; - - // Decrese height. (yo is <=0). - height += yo; - assert(height > 0); - - // Adjust left & width - if (xo >= 0) { - dst += xo; - left += xo; - width -= xo; - } else { - src -= xo; - width += xo; - } - - // the y-displacement may be 0 therefore we have to use memmove, - // because source and destination may overlap - for (ht = height; ht > 0; --ht) { - memmove(dst, src, width); - src += p; - dst += p; - } - } - // This part of the screen is now dirty. - _video_driver->make_dirty(left, top, width, height); -} - - -void GfxFillRect(int left, int top, int right, int bottom, int color) -{ - const DrawPixelInfo* dpi = _cur_dpi; - Pixel *dst; - const int otop = top; - const int oleft = left; - - if (dpi->zoom != 0) return; - if (left > right || top > bottom) return; - if (right < dpi->left || left >= dpi->left + dpi->width) return; - if (bottom < dpi->top || top >= dpi->top + dpi->height) return; - - if ( (left -= dpi->left) < 0) left = 0; - right = right - dpi->left + 1; - if (right > dpi->width) right = dpi->width; - right -= left; - assert(right > 0); - - if ( (top -= dpi->top) < 0) top = 0; - bottom = bottom - dpi->top + 1; - if (bottom > dpi->height) bottom = dpi->height; - bottom -= top; - assert(bottom > 0); - - dst = dpi->dst_ptr + top * dpi->pitch + left; - - if (!(color & PALETTE_MODIFIER_GREYOUT)) { - if (!(color & USE_COLORTABLE)) { - do { - memset(dst, color, right); - dst += dpi->pitch; - } while (--bottom); - } else { - /* use colortable mode */ - const byte* ctab = GetNonSprite(color & COLORTABLE_MASK) + 1; - - do { - int i; - for (i = 0; i != right; i++) dst[i] = ctab[dst[i]]; - dst += dpi->pitch; - } while (--bottom); - } - } else { - byte bo = (oleft - left + dpi->left + otop - top + dpi->top) & 1; - do { - int i; - for (i = (bo ^= 1); i < right; i += 2) dst[i] = (byte)color; - dst += dpi->pitch; - } while (--bottom > 0); - } -} - -static void GfxSetPixel(int x, int y, int color) -{ - const DrawPixelInfo* dpi = _cur_dpi; - if ((x-=dpi->left) < 0 || x>=dpi->width || (y-=dpi->top)<0 || y>=dpi->height) - return; - dpi->dst_ptr[y * dpi->pitch + x] = color; -} - -void GfxDrawLine(int x, int y, int x2, int y2, int color) -{ - int dy; - int dx; - int stepx; - int stepy; - int frac; - - // Check clipping first - { - DrawPixelInfo *dpi = _cur_dpi; - int t; - - if (x < dpi->left && x2 < dpi->left) return; - - if (y < dpi->top && y2 < dpi->top) return; - - t = dpi->left + dpi->width; - if (x > t && x2 > t) return; - - t = dpi->top + dpi->height; - if (y > t && y2 > t) return; - } - - dy = (y2 - y) * 2; - if (dy < 0) { - dy = -dy; - stepy = -1; - } else { - stepy = 1; - } - - dx = (x2 - x) * 2; - if (dx < 0) { - dx = -dx; - stepx = -1; - } else { - stepx = 1; - } - - GfxSetPixel(x, y, color); - if (dx > dy) { - frac = dy - (dx >> 1); - while (x != x2) { - if (frac >= 0) { - y += stepy; - frac -= dx; - } - x += stepx; - frac += dy; - GfxSetPixel(x, y, color); - } - } else { - frac = dx - (dy >> 1); - while (y != y2) { - if (frac >= 0) { - x += stepx; - frac -= dy; - } - y += stepy; - frac += dx; - GfxSetPixel(x, y, color); - } - } -} - - -/** Truncate a given string to a maximum width if neccessary. - * If the string is truncated, add three dots ('...') to show this. - * @param *dest string that is checked and possibly truncated - * @param maxw maximum width in pixels of the string - * @return new width of (truncated) string */ -static int TruncateString(char *str, int maxw) -{ - int w = 0; - FontSize size = _cur_fontsize; - int ddd, ddd_w; - - WChar c; - char *ddd_pos; - - ddd_w = ddd = GetCharacterWidth(size, '.') * 3; - - for (ddd_pos = str; (c = Utf8Consume((const char **)&str)) != '\0'; ) { - if (IsPrintable(c)) { - w += GetCharacterWidth(size, c); - - if (w >= maxw) { - // string got too big... insert dotdotdot - ddd_pos[0] = ddd_pos[1] = ddd_pos[2] = '.'; - ddd_pos[3] = 0; - return ddd_w; - } - } else { - if (c == SCC_SETX) str++; - else if (c == SCC_SETXY) str += 2; - else if (c == SCC_TINYFONT) { - size = FS_SMALL; - ddd = GetCharacterWidth(size, '.') * 3; - } else if (c == SCC_BIGFONT) { - size = FS_LARGE; - ddd = GetCharacterWidth(size, '.') * 3; - } - } - - // Remember the last position where three dots fit. - if (w + ddd < maxw) { - ddd_w = w + ddd; - ddd_pos = str; - } - } - - return w; -} - -static inline int TruncateStringID(StringID src, char *dest, int maxw, const char* last) -{ - GetString(dest, src, last); - return TruncateString(dest, maxw); -} - -/* returns right coordinate */ -int DrawString(int x, int y, StringID str, uint16 color) -{ - char buffer[512]; - - GetString(buffer, str, lastof(buffer)); - return DoDrawString(buffer, x, y, color); -} - -int DrawStringTruncated(int x, int y, StringID str, uint16 color, uint maxw) -{ - char buffer[512]; - TruncateStringID(str, buffer, maxw, lastof(buffer)); - return DoDrawString(buffer, x, y, color); -} - - -int DrawStringRightAligned(int x, int y, StringID str, uint16 color) -{ - char buffer[512]; - int w; - - GetString(buffer, str, lastof(buffer)); - w = GetStringBoundingBox(buffer).width; - DoDrawString(buffer, x - w, y, color); - - return w; -} - -void DrawStringRightAlignedTruncated(int x, int y, StringID str, uint16 color, uint maxw) -{ - char buffer[512]; - - TruncateStringID(str, buffer, maxw, lastof(buffer)); - DoDrawString(buffer, x - GetStringBoundingBox(buffer).width, y, color); -} - -void DrawStringRightAlignedUnderline(int x, int y, StringID str, uint16 color) -{ - int w = DrawStringRightAligned(x, y, str, color); - GfxFillRect(x - w, y + 10, x, y + 10, _string_colorremap[1]); -} - - -int DrawStringCentered(int x, int y, StringID str, uint16 color) -{ - char buffer[512]; - int w; - - GetString(buffer, str, lastof(buffer)); - - w = GetStringBoundingBox(buffer).width; - DoDrawString(buffer, x - w / 2, y, color); - - return w; -} - -int DrawStringCenteredTruncated(int xl, int xr, int y, StringID str, uint16 color) -{ - char buffer[512]; - int w = TruncateStringID(str, buffer, xr - xl, lastof(buffer)); - return DoDrawString(buffer, (xl + xr - w) / 2, y, color); -} - -int DoDrawStringCentered(int x, int y, const char *str, uint16 color) -{ - int w = GetStringBoundingBox(str).width; - DoDrawString(str, x - w / 2, y, color); - return w; -} - -void DrawStringCenterUnderline(int x, int y, StringID str, uint16 color) -{ - int w = DrawStringCentered(x, y, str, color); - GfxFillRect(x - (w >> 1), y + 10, x - (w >> 1) + w, y + 10, _string_colorremap[1]); -} - -void DrawStringCenterUnderlineTruncated(int xl, int xr, int y, StringID str, uint16 color) -{ - int w = DrawStringCenteredTruncated(xl, xr, y, str, color); - GfxFillRect((xl + xr - w) / 2, y + 10, (xl + xr + w) / 2, y + 10, _string_colorremap[1]); -} - -/** 'Correct' a string to a maximum length. Longer strings will be cut into - * additional lines at whitespace characters if possible. The string parameter - * is modified with terminating characters mid-string which are the - * placeholders for the newlines.
- * The string WILL be truncated if there was no whitespace for the current - * line's maximum width. - * - * @note To know if the the terminating '\0' is the string end or just a - * newline, the returned 'num' value should be consulted. The num'th '\0', - * starting with index 0 is the real string end. - * - * @param str string to check and correct for length restrictions - * @param maxw the maximum width the string can have on one line - * @return return a 32bit wide number consisting of 2 packed values: - * 0 - 15 the number of lines ADDED to the string - * 16 - 31 the fontsize in which the length calculation was done at */ -uint32 FormatStringLinebreaks(char *str, int maxw) -{ - FontSize size = _cur_fontsize; - int num = 0; - - assert(maxw > 0); - - for (;;) { - char *last_space = NULL; - int w = 0; - - for (;;) { - WChar c = Utf8Consume((const char **)&str); - /* whitespace is where we will insert the line-break */ - if (c == ' ') last_space = str; - - if (IsPrintable(c)) { - w += GetCharacterWidth(size, c); - /* string is longer than maximum width so we need to decide what to - * do. We can do two things: - * 1. If no whitespace was found at all up until now (on this line) then - * we will truncate the string and bail out. - * 2. In all other cases force a linebreak at the last seen whitespace */ - if (w > maxw) { - if (last_space == NULL) { - str[-1] = '\0'; - return num + (size << 16); - } - str = last_space; - break; - } - } else { - switch (c) { - case '\0': return num + (size << 16); break; - case SCC_SETX: str++; break; - case SCC_SETXY: str +=2; break; - case SCC_TINYFONT: size = FS_SMALL; break; - case SCC_BIGFONT: size = FS_LARGE; break; - case '\n': goto end_of_inner_loop; - } - } - } -end_of_inner_loop: - /* string didn't fit on line, so 'dummy' terminate and increase linecount */ - num++; - str[-1] = '\0'; - } -} - -/** Draw a given string with the centre around the given x coordinates - * @param x Centre the string around this pixel width - * @param y Draw the string at this pixel height (first line's bottom) - * @param str String to draw - * @param max Maximum width the string can have before it is wrapped */ -void DrawStringMultiCenter(int x, int y, StringID str, int maxw) -{ - char buffer[512]; - uint32 tmp; - int num, w, mt; - const char *src; - WChar c; - - GetString(buffer, str, lastof(buffer)); - - tmp = FormatStringLinebreaks(buffer, maxw); - num = GB(tmp, 0, 16); - - mt = GetCharacterHeight(GB(tmp, 16, 16)); - - y -= (mt >> 1) * num; - - src = buffer; - - for (;;) { - w = GetStringBoundingBox(src).width; - DoDrawString(src, x - (w>>1), y, 0xFE); - _cur_fontsize = _last_fontsize; - - for (;;) { - c = Utf8Consume(&src); - if (c == 0) { - y += mt; - if (--num < 0) { - _cur_fontsize = FS_NORMAL; - return; - } - break; - } else if (c == SCC_SETX) { - src++; - } else if (c == SCC_SETXY) { - src+=2; - } - } - } -} - - -uint DrawStringMultiLine(int x, int y, StringID str, int maxw) -{ - char buffer[512]; - uint32 tmp; - int num, mt; - uint total_height; - const char *src; - WChar c; - - GetString(buffer, str, lastof(buffer)); - - tmp = FormatStringLinebreaks(buffer, maxw); - num = GB(tmp, 0, 16); - - mt = GetCharacterHeight(GB(tmp, 16, 16)); - total_height = (num + 1) * mt; - - src = buffer; - - for (;;) { - DoDrawString(src, x, y, 0xFE); - _cur_fontsize = _last_fontsize; - - for (;;) { - c = Utf8Consume(&src); - if (c == 0) { - y += mt; - if (--num < 0) { - _cur_fontsize = FS_NORMAL; - return total_height; - } - break; - } else if (c == SCC_SETX) { - src++; - } else if (c == SCC_SETXY) { - src+=2; - } - } - } -} - -/** Return the string dimension in pixels. The height and width are returned - * in a single BoundingRect value. TINYFONT, BIGFONT modifiers are only - * supported as the first character of the string. The returned dimensions - * are therefore a rough estimation correct for all the current strings - * but not every possible combination - * @param str string to calculate pixel-width - * @return string width and height in pixels */ -BoundingRect GetStringBoundingBox(const char *str) -{ - FontSize size = _cur_fontsize; - BoundingRect br; - int max_width; - WChar c; - - br.width = br.height = max_width = 0; - for (;;) { - c = Utf8Consume(&str); - if (c == 0) break; - if (IsPrintable(c)) { - br.width += GetCharacterWidth(size, c); - } else { - switch (c) { - case SCC_SETX: br.width += (byte)*str++; break; - case SCC_SETXY: - br.width += (byte)*str++; - br.height += (byte)*str++; - break; - case SCC_TINYFONT: size = FS_SMALL; break; - case SCC_BIGFONT: size = FS_LARGE; break; - case '\n': - br.height += GetCharacterHeight(size); - if (br.width > max_width) max_width = br.width; - br.width = 0; - break; - } - } - } - br.height += GetCharacterHeight(size); - - br.width = max(br.width, max_width); - return br; -} - -/** Draw a string at the given coordinates with the given colour - * @param string the string to draw - * @param x offset from left side of the screen, if negative offset from the right side - * @param x offset from top side of the screen, if negative offset from the bottom - * @param real_color colour of the string, see _string_colormap in - * table/palettes.h or docs/ottd-colourtext-palette.png - * @return the x-coordinates where the drawing has finished. If nothing is drawn - * the originally passed x-coordinate is returned */ -int DoDrawString(const char *string, int x, int y, uint16 real_color) -{ - DrawPixelInfo *dpi = _cur_dpi; - FontSize size = _cur_fontsize; - WChar c; - byte color; - int xo = x, yo = y; - - color = real_color & 0xFF; - - if (color != 0xFE) { - if (x >= dpi->left + dpi->width || - x + _screen.width*2 <= dpi->left || - y >= dpi->top + dpi->height || - y + _screen.height <= dpi->top) - return x; - - if (color != 0xFF) { -switch_color:; - if (real_color & IS_PALETTE_COLOR) { - _string_colorremap[1] = color; - _string_colorremap[2] = 215; - } else { - _string_colorremap[1] = _string_colormap[color].text; - _string_colorremap[2] = _string_colormap[color].shadow; - } - _color_remap_ptr = _string_colorremap; - } - } - -check_bounds: - if (y + 19 <= dpi->top || dpi->top + dpi->height <= y) { -skip_char:; - for (;;) { - c = Utf8Consume(&string); - if (!IsPrintable(c)) goto skip_cont; - } - } - - for (;;) { - c = Utf8Consume(&string); -skip_cont:; - if (c == 0) { - _last_fontsize = size; - return x; - } - if (IsPrintable(c)) { - if (x >= dpi->left + dpi->width) goto skip_char; - if (x + 26 >= dpi->left) { - GfxMainBlitter(GetGlyph(size, c), x, y, 1); - } - x += GetCharacterWidth(size, c); - } else if (c == '\n') { // newline = {} - x = xo; - y += GetCharacterHeight(size); - goto check_bounds; - } else if (c >= SCC_BLUE && c <= SCC_BLACK) { // change color? - color = (byte)(c - SCC_BLUE); - goto switch_color; - } else if (c == SCC_SETX) { // {SETX} - x = xo + (byte)*string++; - } else if (c == SCC_SETXY) {// {SETXY} - x = xo + (byte)*string++; - y = yo + (byte)*string++; - } else if (c == SCC_TINYFONT) { // {TINYFONT} - size = FS_SMALL; - } else if (c == SCC_BIGFONT) { // {BIGFONT} - size = FS_LARGE; - } else { - DEBUG(misc, 0, "[utf8] unknown string command character %d", c); - } - } -} - -int DoDrawStringTruncated(const char *str, int x, int y, uint16 color, uint maxw) -{ - char buffer[512]; - ttd_strlcpy(buffer, str, sizeof(buffer)); - TruncateString(buffer, maxw); - return DoDrawString(buffer, x, y, color); -} - -void DrawSprite(uint32 img, int x, int y) -{ - if (img & PALETTE_MODIFIER_COLOR) { - _color_remap_ptr = GetNonSprite(GB(img, PALETTE_SPRITE_START, PALETTE_SPRITE_WIDTH)) + 1; - GfxMainBlitter(GetSprite(img & SPRITE_MASK), x, y, 1); - } else if (img & PALETTE_MODIFIER_TRANSPARENT) { - _color_remap_ptr = GetNonSprite(GB(img, PALETTE_SPRITE_START, PALETTE_SPRITE_WIDTH)) + 1; - GfxMainBlitter(GetSprite(img & SPRITE_MASK), x, y, 2); - } else { - GfxMainBlitter(GetSprite(img & SPRITE_MASK), x, y, 0); - } -} - -typedef struct BlitterParams { - int start_x, start_y; - const byte *sprite; - Pixel *dst; - int mode; - int width, height; - int width_org; - int pitch; -} BlitterParams; - -static void GfxBlitTileZoomIn(BlitterParams *bp) -{ - const byte *src_o = bp->sprite; - const byte *src; - int num, skip; - byte done; - Pixel *dst; - const byte *ctab; - - src_o += ReadLE16Aligned(src_o + bp->start_y * 2); - switch (bp->mode) { - case 1: - do { - do { - done = src_o[0]; - num = done & 0x7F; - skip = src_o[1]; - src = src_o + 2; - src_o += num + 2; - - dst = bp->dst; - - if ( (skip -= bp->start_x) > 0) { - dst += skip; - } else { - src -= skip; - num += skip; - if (num <= 0) continue; - skip = 0; - } - - skip = skip + num - bp->width; - if (skip > 0) { - num -= skip; - if (num <= 0) continue; - } - - ctab = _color_remap_ptr; - - for (; num >= 4; num -=4) { - dst[3] = ctab[src[3]]; - dst[2] = ctab[src[2]]; - dst[1] = ctab[src[1]]; - dst[0] = ctab[src[0]]; - dst += 4; - src += 4; - } - for (; num != 0; num--) *dst++ = ctab[*src++]; - } while (!(done & 0x80)); - - bp->dst += bp->pitch; - } while (--bp->height != 0); - break; - - case 2: - do { - do { - done = src_o[0]; - num = done & 0x7F; - skip = src_o[1]; - src_o += num + 2; - - dst = bp->dst; - - if ( (skip -= bp->start_x) > 0) { - dst += skip; - } else { - num += skip; - if (num <= 0) continue; - skip = 0; - } - - skip = skip + num - bp->width; - if (skip > 0) { - num -= skip; - if (num <= 0) continue; - } - - ctab = _color_remap_ptr; - for (; num != 0; num--) { - *dst = ctab[*dst]; - dst++; - } - } while (!(done & 0x80)); - - bp->dst += bp->pitch; - } while (--bp->height != 0); - break; - - default: - do { - do { - done = src_o[0]; - num = done & 0x7F; - skip = src_o[1]; - src = src_o + 2; - src_o += num + 2; - - dst = bp->dst; - - if ( (skip -= bp->start_x) > 0) { - dst += skip; - } else { - src -= skip; - num += skip; - if (num <= 0) continue; - skip = 0; - } - - skip = skip + num - bp->width; - if (skip > 0) { - num -= skip; - if (num <= 0) continue; - } -#if defined(_WIN32) - if (num & 1) *dst++ = *src++; - if (num & 2) { *(uint16*)dst = *(uint16*)src; dst += 2; src += 2; } - if (num >>= 2) { - do { - *(uint32*)dst = *(uint32*)src; - dst += 4; - src += 4; - } while (--num != 0); - } -#else - memcpy(dst, src, num); -#endif - } while (!(done & 0x80)); - - bp->dst += bp->pitch; - } while (--bp->height != 0); - break; - } -} - -static void GfxBlitZoomInUncomp(BlitterParams *bp) -{ - const byte *src = bp->sprite; - Pixel *dst = bp->dst; - int height = bp->height; - int width = bp->width; - int i; - - assert(height > 0); - assert(width > 0); - - switch (bp->mode) { - case 1: { - const byte *ctab = _color_remap_ptr; - - do { - for (i = 0; i != width; i++) { - byte b = ctab[src[i]]; - - if (b != 0) dst[i] = b; - } - src += bp->width_org; - dst += bp->pitch; - } while (--height != 0); - break; - } - - case 2: { - const byte *ctab = _color_remap_ptr; - - do { - for (i = 0; i != width; i++) - if (src[i] != 0) dst[i] = ctab[dst[i]]; - src += bp->width_org; - dst += bp->pitch; - } while (--height != 0); - break; - } - - default: - do { - int n = width; - - for (; n >= 4; n -= 4) { - if (src[0] != 0) dst[0] = src[0]; - if (src[1] != 0) dst[1] = src[1]; - if (src[2] != 0) dst[2] = src[2]; - if (src[3] != 0) dst[3] = src[3]; - - dst += 4; - src += 4; - } - - for (; n != 0; n--) { - if (src[0] != 0) dst[0] = src[0]; - src++; - dst++; - } - - src += bp->width_org - width; - dst += bp->pitch - width; - } while (--height != 0); - break; - } -} - -static void GfxBlitTileZoomMedium(BlitterParams *bp) -{ - const byte *src_o = bp->sprite; - const byte *src; - int num, skip; - byte done; - Pixel *dst; - const byte *ctab; - - src_o += ReadLE16Aligned(src_o + bp->start_y * 2); - switch (bp->mode) { - case 1: - do { - do { - done = src_o[0]; - num = done & 0x7F; - skip = src_o[1]; - src = src_o + 2; - src_o += num + 2; - - dst = bp->dst; - - if (skip & 1) { - skip++; - src++; - if (--num == 0) continue; - } - - if ( (skip -= bp->start_x) > 0) { - dst += skip >> 1; - } else { - src -= skip; - num += skip; - if (num <= 0) continue; - skip = 0; - } - - skip = skip + num - bp->width; - if (skip > 0) { - num -= skip; - if (num <= 0) continue; - } - - ctab = _color_remap_ptr; - num = (num + 1) >> 1; - for (; num != 0; num--) { - *dst = ctab[*src]; - dst++; - src += 2; - } - } while (!(done & 0x80)); - bp->dst += bp->pitch; - if (--bp->height == 0) return; - - do { - done = src_o[0]; - src_o += (done & 0x7F) + 2; - } while (!(done & 0x80)); - } while (--bp->height != 0); - break; - - case 2: - do { - do { - done = src_o[0]; - num = done & 0x7F; - skip = src_o[1]; - src_o += num + 2; - - dst = bp->dst; - - if (skip & 1) { - skip++; - if (--num == 0) continue; - } - - if ( (skip -= bp->start_x) > 0) { - dst += skip >> 1; - } else { - num += skip; - if (num <= 0) continue; - skip = 0; - } - - skip = skip + num - bp->width; - if (skip > 0) { - num -= skip; - if (num <= 0) continue; - } - - ctab = _color_remap_ptr; - num = (num + 1) >> 1; - for (; num != 0; num--) { - *dst = ctab[*dst]; - dst++; - } - } while (!(done & 0x80)); - bp->dst += bp->pitch; - if (--bp->height == 0) return; - - do { - done = src_o[0]; - src_o += (done & 0x7F) + 2; - } while (!(done & 0x80)); - } while (--bp->height != 0); - break; - - default: - do { - do { - done = src_o[0]; - num = done & 0x7F; - skip = src_o[1]; - src = src_o + 2; - src_o += num + 2; - - dst = bp->dst; - - if (skip & 1) { - skip++; - src++; - if (--num == 0) continue; - } - - if ( (skip -= bp->start_x) > 0) { - dst += skip >> 1; - } else { - src -= skip; - num += skip; - if (num <= 0) continue; - skip = 0; - } - - skip = skip + num - bp->width; - if (skip > 0) { - num -= skip; - if (num <= 0) continue; - } - - num = (num + 1) >> 1; - - for (; num != 0; num--) { - *dst = *src; - dst++; - src += 2; - } - - } while (!(done & 0x80)); - - bp->dst += bp->pitch; - if (--bp->height == 0) return; - - do { - done = src_o[0]; - src_o += (done & 0x7F) + 2; - } while (!(done & 0x80)); - } while (--bp->height != 0); - break; - } -} - -static void GfxBlitZoomMediumUncomp(BlitterParams *bp) -{ - const byte *src = bp->sprite; - Pixel *dst = bp->dst; - int height = bp->height; - int width = bp->width; - int i; - - assert(height > 0); - assert(width > 0); - - switch (bp->mode) { - case 1: { - const byte *ctab = _color_remap_ptr; - - for (height >>= 1; height != 0; height--) { - for (i = 0; i != width >> 1; i++) { - byte b = ctab[src[i * 2]]; - - if (b != 0) dst[i] = b; - } - src += bp->width_org * 2; - dst += bp->pitch; - } - break; - } - - case 2: { - const byte *ctab = _color_remap_ptr; - - for (height >>= 1; height != 0; height--) { - for (i = 0; i != width >> 1; i++) - if (src[i * 2] != 0) dst[i] = ctab[dst[i]]; - src += bp->width_org * 2; - dst += bp->pitch; - } - break; - } - - default: - for (height >>= 1; height != 0; height--) { - for (i = 0; i != width >> 1; i++) - if (src[i * 2] != 0) dst[i] = src[i * 2]; - src += bp->width_org * 2; - dst += bp->pitch; - } - break; - } -} - -static void GfxBlitTileZoomOut(BlitterParams *bp) -{ - const byte *src_o = bp->sprite; - const byte *src; - int num, skip; - byte done; - Pixel *dst; - const byte *ctab; - - src_o += ReadLE16Aligned(src_o + bp->start_y * 2); - switch (bp->mode) { - case 1: - for (;;) { - do { - done = src_o[0]; - num = done & 0x7F; - skip = src_o[1]; - src = src_o + 2; - src_o += num + 2; - - dst = bp->dst; - - if (skip & 1) { - skip++; - src++; - if (--num == 0) continue; - } - - if (skip & 2) { - skip += 2; - src += 2; - num -= 2; - if (num <= 0) continue; - } - - if ( (skip -= bp->start_x) > 0) { - dst += skip >> 2; - } else { - src -= skip; - num += skip; - if (num <= 0) continue; - skip = 0; - } - - skip = skip + num - bp->width; - if (skip > 0) { - num -= skip; - if (num <= 0) continue; - } - - ctab = _color_remap_ptr; - num = (num + 3) >> 2; - for (; num != 0; num--) { - *dst = ctab[*src]; - dst++; - src += 4; - } - } while (!(done & 0x80)); - bp->dst += bp->pitch; - if (--bp->height == 0) return; - - do { - done = src_o[0]; - src_o += (done & 0x7F) + 2; - } while (!(done & 0x80)); - if (--bp->height == 0) return; - - do { - done = src_o[0]; - src_o += (done & 0x7F) + 2; - } while (!(done & 0x80)); - if (--bp->height == 0) return; - - do { - done = src_o[0]; - src_o += (done & 0x7F) + 2; - } while (!(done & 0x80)); - if (--bp->height == 0) return; - } - break; - - case 2: - for (;;) { - do { - done = src_o[0]; - num = done & 0x7F; - skip = src_o[1]; - src_o += num + 2; - - dst = bp->dst; - - if (skip & 1) { - skip++; - if (--num == 0) continue; - } - - if (skip & 2) { - skip += 2; - num -= 2; - if (num <= 0) continue; - } - - if ( (skip -= bp->start_x) > 0) { - dst += skip >> 2; - } else { - num += skip; - if (num <= 0) continue; - skip = 0; - } - - skip = skip + num - bp->width; - if (skip > 0) { - num -= skip; - if (num <= 0) continue; - } - - ctab = _color_remap_ptr; - num = (num + 3) >> 2; - for (; num != 0; num--) { - *dst = ctab[*dst]; - dst++; - } - - } while (!(done & 0x80)); - bp->dst += bp->pitch; - if (--bp->height == 0) return; - - do { - done = src_o[0]; - src_o += (done & 0x7F) + 2; - } while (!(done & 0x80)); - if (--bp->height == 0) return; - - do { - done = src_o[0]; - src_o += (done & 0x7F) + 2; - } while (!(done & 0x80)); - if (--bp->height == 0) return; - - do { - done = src_o[0]; - src_o += (done & 0x7F) + 2; - } while (!(done & 0x80)); - if (--bp->height == 0) return; - } - break; - - default: - for (;;) { - do { - done = src_o[0]; - num = done & 0x7F; - skip = src_o[1]; - src = src_o + 2; - src_o += num + 2; - - dst = bp->dst; - - if (skip & 1) { - skip++; - src++; - if (--num == 0) continue; - } - - if (skip & 2) { - skip += 2; - src += 2; - num -= 2; - if (num <= 0) continue; - } - - if ( (skip -= bp->start_x) > 0) { - dst += skip >> 2; - } else { - src -= skip; - num += skip; - if (num <= 0) continue; - skip = 0; - } - - skip = skip + num - bp->width; - if (skip > 0) { - num -= skip; - if (num <= 0) continue; - } - - num = (num + 3) >> 2; - - for (; num != 0; num--) { - *dst = *src; - dst++; - src += 4; - } - } while (!(done & 0x80)); - - bp->dst += bp->pitch; - if (--bp->height == 0) return; - - do { - done = src_o[0]; - src_o += (done & 0x7F) + 2; - } while (!(done & 0x80)); - if (--bp->height == 0) return; - - do { - done = src_o[0]; - src_o += (done & 0x7F) + 2; - } while (!(done & 0x80)); - if (--bp->height == 0) return; - - do { - done = src_o[0]; - src_o += (done & 0x7F) + 2; - } while (!(done & 0x80)); - if (--bp->height == 0) return; - } - break; - } -} - -static void GfxBlitZoomOutUncomp(BlitterParams *bp) -{ - const byte *src = bp->sprite; - Pixel *dst = bp->dst; - int height = bp->height; - int width = bp->width; - int i; - - assert(height > 0); - assert(width > 0); - - switch (bp->mode) { - case 1: { - const byte *ctab = _color_remap_ptr; - - for (height >>= 2; height != 0; height--) { - for (i = 0; i != width >> 2; i++) { - byte b = ctab[src[i * 4]]; - - if (b != 0) dst[i] = b; - } - src += bp->width_org * 4; - dst += bp->pitch; - } - break; - } - - case 2: { - const byte *ctab = _color_remap_ptr; - - for (height >>= 2; height != 0; height--) { - for (i = 0; i != width >> 2; i++) - if (src[i * 4] != 0) dst[i] = ctab[dst[i]]; - src += bp->width_org * 4; - dst += bp->pitch; - } - break; - } - - default: - for (height >>= 2; height != 0; height--) { - for (i = 0; i != width >> 2; i++) - if (src[i * 4] != 0) dst[i] = src[i * 4]; - src += bp->width_org * 4; - dst += bp->pitch; - } - break; - } -} - - -static void GfxMainBlitter(const Sprite *sprite, int x, int y, int mode) -{ - const DrawPixelInfo *dpi = _cur_dpi; - int start_x, start_y; - BlitterParams bp; - int zoom_mask = ~((1 << dpi->zoom) - 1); - - /* decode sprite header */ - x += sprite->x_offs; - y += sprite->y_offs; - bp.width_org = bp.width = sprite->width; - bp.height = sprite->height; - bp.sprite = sprite->data; - bp.dst = dpi->dst_ptr; - bp.mode = mode; - bp.pitch = dpi->pitch; - - assert(bp.height > 0); - assert(bp.width > 0); - - if (sprite->info & 8) { - /* tile blit */ - start_y = 0; - - if (dpi->zoom > 0) { - start_y += bp.height & ~zoom_mask; - bp.height &= zoom_mask; - if (bp.height == 0) return; - y &= zoom_mask; - } - - if ( (y -= dpi->top) < 0) { - bp.height += y; - if (bp.height <= 0) return; - start_y -= y; - y = 0; - } else { - bp.dst += bp.pitch * (y >> dpi->zoom); - } - bp.start_y = start_y; - - if ( (y = y + bp.height - dpi->height) > 0) { - bp.height -= y; - if (bp.height <= 0) return; - } - - start_x = 0; - x &= zoom_mask; - if ( (x -= dpi->left) < 0) { - bp.width += x; - if (bp.width <= 0) return; - start_x -= x; - x = 0; - } - bp.start_x = start_x; - bp.dst += x >> dpi->zoom; - - if ( (x = x + bp.width - dpi->width) > 0) { - bp.width -= x; - if (bp.width <= 0) return; - } - - switch (dpi->zoom) { - default: NOT_REACHED(); - case 0: GfxBlitTileZoomIn(&bp); break; - case 1: GfxBlitTileZoomMedium(&bp); break; - case 2: GfxBlitTileZoomOut(&bp); break; - } - } else { - bp.sprite += bp.width * (bp.height & ~zoom_mask); - bp.height &= zoom_mask; - if (bp.height == 0) return; - - y &= zoom_mask; - - if ( (y -= dpi->top) < 0) { - bp.height += y; - if (bp.height <= 0) return; - bp.sprite -= bp.width * y; - y = 0; - } else { - bp.dst += bp.pitch * (y >> dpi->zoom); - } - - if (bp.height > dpi->height - y) { - bp.height = dpi->height - y; - if (bp.height <= 0) return; - } - - x &= zoom_mask; - - if ( (x -= dpi->left) < 0) { - bp.width += x; - if (bp.width <= 0) return; - bp.sprite -= x; - x = 0; - } - bp.dst += x >> dpi->zoom; - - if (bp.width > dpi->width - x) { - bp.width = dpi->width - x; - if (bp.width <= 0) return; - } - - switch (dpi->zoom) { - default: NOT_REACHED(); - case 0: GfxBlitZoomInUncomp(&bp); break; - case 1: GfxBlitZoomMediumUncomp(&bp); break; - case 2: GfxBlitZoomOutUncomp(&bp); break; - } - } -} - -void DoPaletteAnimations(void); - -void GfxInitPalettes(void) -{ - memcpy(_cur_palette, _palettes[_use_dos_palette ? 1 : 0], sizeof(_cur_palette)); - - _pal_first_dirty = 0; - _pal_last_dirty = 255; - DoPaletteAnimations(); -} - -#define EXTR(p, q) (((uint16)(_timer_counter * (p)) * (q)) >> 16) -#define EXTR2(p, q) (((uint16)(~_timer_counter * (p)) * (q)) >> 16) - -void DoPaletteAnimations(void) -{ - const Colour *s; - Colour *d; - /* Amount of colors to be rotated. - * A few more for the DOS palette, because the water colors are - * 245-254 for DOS and 217-226 for Windows. */ - const ExtraPaletteValues *ev = &_extra_palette_values; - int c = _use_dos_palette ? 38 : 28; - Colour old_val[38]; // max(38, 28) - uint i; - uint j; - - d = &_cur_palette[217]; - memcpy(old_val, d, c * sizeof(*old_val)); - - // Dark blue water - s = (_opt.landscape == LT_CANDY) ? ev->ac : ev->a; - j = EXTR(320, 5); - for (i = 0; i != 5; i++) { - *d++ = s[j]; - j++; - if (j == 5) j = 0; - } - - // Glittery water - s = (_opt.landscape == LT_CANDY) ? ev->bc : ev->b; - j = EXTR(128, 15); - for (i = 0; i != 5; i++) { - *d++ = s[j]; - j += 3; - if (j >= 15) j -= 15; - } - - s = ev->e; - j = EXTR2(512, 5); - for (i = 0; i != 5; i++) { - *d++ = s[j]; - j++; - if (j == 5) j = 0; - } - - // Oil refinery fire animation - s = ev->oil_ref; - j = EXTR2(512, 7); - for (i = 0; i != 7; i++) { - *d++ = s[j]; - j++; - if (j == 7) j = 0; - } - - // Radio tower blinking - { - byte i = (_timer_counter >> 1) & 0x7F; - byte v; - - (v = 255, i < 0x3f) || - (v = 128, i < 0x4A || i >= 0x75) || - (v = 20); - d->r = v; - d->g = 0; - d->b = 0; - d++; - - i ^= 0x40; - (v = 255, i < 0x3f) || - (v = 128, i < 0x4A || i >= 0x75) || - (v = 20); - d->r = v; - d->g = 0; - d->b = 0; - d++; - } - - // Handle lighthouse and stadium animation - s = ev->lighthouse; - j = EXTR(256, 4); - for (i = 0; i != 4; i++) { - *d++ = s[j]; - j++; - if (j == 4) j = 0; - } - - // Animate water for old DOS graphics - if (_use_dos_palette) { - // Dark blue water DOS - s = (_opt.landscape == LT_CANDY) ? ev->ac : ev->a; - j = EXTR(320, 5); - for (i = 0; i != 5; i++) { - *d++ = s[j]; - j++; - if (j == 5) j = 0; - } - - // Glittery water DOS - s = (_opt.landscape == LT_CANDY) ? ev->bc : ev->b; - j = EXTR(128, 15); - for (i = 0; i != 5; i++) { - *d++ = s[j]; - j += 3; - if (j >= 15) j -= 15; - } - } - - if (memcmp(old_val, &_cur_palette[217], c * sizeof(*old_val)) != 0) { - if (_pal_first_dirty > 217) _pal_first_dirty = 217; - if (_pal_last_dirty < 217 + c) _pal_last_dirty = 217 + c; - } -} - - -void LoadStringWidthTable(void) -{ - uint i; - - /* Normal font */ - for (i = 0; i != 224; i++) { - _stringwidth_table[FS_NORMAL][i] = GetGlyphWidth(FS_NORMAL, i + 32); - } - - /* Small font */ - for (i = 0; i != 224; i++) { - _stringwidth_table[FS_SMALL][i] = GetGlyphWidth(FS_SMALL, i + 32); - } - - /* Large font */ - for (i = 0; i != 224; i++) { - _stringwidth_table[FS_LARGE][i] = GetGlyphWidth(FS_LARGE, i + 32); - } -} - - -byte GetCharacterWidth(FontSize size, WChar key) -{ - if (key >= 32 && key < 256) return _stringwidth_table[size][key - 32]; - - return GetGlyphWidth(size, key); -} - - -void ScreenSizeChanged(void) -{ - // check the dirty rect - if (_invalid_rect.right >= _screen.width) _invalid_rect.right = _screen.width; - if (_invalid_rect.bottom >= _screen.height) _invalid_rect.bottom = _screen.height; - - // screen size changed and the old bitmap is invalid now, so we don't want to undraw it - _cursor.visible = false; -} - -void UndrawMouseCursor(void) -{ - if (_cursor.visible) { - _cursor.visible = false; - memcpy_pitch( - _screen.dst_ptr + _cursor.draw_pos.x + _cursor.draw_pos.y * _screen.pitch, - _cursor_backup, - _cursor.draw_size.x, _cursor.draw_size.y, _cursor.draw_size.x, _screen.pitch); - - _video_driver->make_dirty(_cursor.draw_pos.x, _cursor.draw_pos.y, _cursor.draw_size.x, _cursor.draw_size.y); - } -} - -void DrawMouseCursor(void) -{ - int x; - int y; - int w; - int h; - - /* Redraw mouse cursor but only when it's inside the window */ - if (!_cursor.in_window) return; - - // Don't draw the mouse cursor if it's already drawn - if (_cursor.visible) { - if (!_cursor.dirty) return; - UndrawMouseCursor(); - } - - w = _cursor.size.x; - x = _cursor.pos.x + _cursor.offs.x; - if (x < 0) { - w += x; - x = 0; - } - if (w > _screen.width - x) w = _screen.width - x; - if (w <= 0) return; - _cursor.draw_pos.x = x; - _cursor.draw_size.x = w; - - h = _cursor.size.y; - y = _cursor.pos.y + _cursor.offs.y; - if (y < 0) { - h += y; - y = 0; - } - if (h > _screen.height - y) h = _screen.height - y; - if (h <= 0) return; - _cursor.draw_pos.y = y; - _cursor.draw_size.y = h; - - assert(w * h < (int)sizeof(_cursor_backup)); - - // Make backup of stuff below cursor - memcpy_pitch( - _cursor_backup, - _screen.dst_ptr + _cursor.draw_pos.x + _cursor.draw_pos.y * _screen.pitch, - _cursor.draw_size.x, _cursor.draw_size.y, _screen.pitch, _cursor.draw_size.x); - - // Draw cursor on screen - _cur_dpi = &_screen; - DrawSprite(_cursor.sprite, _cursor.pos.x, _cursor.pos.y); - - _video_driver->make_dirty(_cursor.draw_pos.x, _cursor.draw_pos.y, _cursor.draw_size.x, _cursor.draw_size.y); - - _cursor.visible = true; - _cursor.dirty = false; -} - -#if defined(_DEBUG) -static void DbgScreenRect(int left, int top, int right, int bottom) -{ - DrawPixelInfo dp; - DrawPixelInfo *old; - - old = _cur_dpi; - _cur_dpi = &dp; - dp = _screen; - GfxFillRect(left, top, right - 1, bottom - 1, rand() & 255); - _cur_dpi = old; -} -#endif - -void RedrawScreenRect(int left, int top, int right, int bottom) -{ - assert(right <= _screen.width && bottom <= _screen.height); - if (_cursor.visible) { - if (right > _cursor.draw_pos.x && - left < _cursor.draw_pos.x + _cursor.draw_size.x && - bottom > _cursor.draw_pos.y && - top < _cursor.draw_pos.y + _cursor.draw_size.y) { - UndrawMouseCursor(); - } - } - UndrawTextMessage(); - -#if defined(_DEBUG) - if (_dbg_screen_rect) - DbgScreenRect(left, top, right, bottom); - else -#endif - DrawOverlappedWindowForAll(left, top, right, bottom); - - _video_driver->make_dirty(left, top, right - left, bottom - top); -} - -void DrawDirtyBlocks(void) -{ - byte *b = _dirty_blocks; - const int w = ALIGN(_screen.width, 64); - const int h = ALIGN(_screen.height, 8); - int x; - int y; - - if (IsGeneratingWorld() && !IsGeneratingWorldReadyForPaint()) return; - - y = 0; - do { - x = 0; - do { - if (*b != 0) { - int left; - int top; - int right = x + 64; - int bottom = y; - byte *p = b; - int h2; - - // First try coalescing downwards - do { - *p = 0; - p += DIRTY_BYTES_PER_LINE; - bottom += 8; - } while (bottom != h && *p != 0); - - // Try coalescing to the right too. - h2 = (bottom - y) >> 3; - assert(h2 > 0); - p = b; - - while (right != w) { - byte *p2 = ++p; - int h = h2; - // Check if a full line of dirty flags is set. - do { - if (!*p2) goto no_more_coalesc; - p2 += DIRTY_BYTES_PER_LINE; - } while (--h != 0); - - // Wohoo, can combine it one step to the right! - // Do that, and clear the bits. - right += 64; - - h = h2; - p2 = p; - do { - *p2 = 0; - p2 += DIRTY_BYTES_PER_LINE; - } while (--h != 0); - } - no_more_coalesc: - - left = x; - top = y; - - if (left < _invalid_rect.left ) left = _invalid_rect.left; - if (top < _invalid_rect.top ) top = _invalid_rect.top; - if (right > _invalid_rect.right ) right = _invalid_rect.right; - if (bottom > _invalid_rect.bottom) bottom = _invalid_rect.bottom; - - if (left < right && top < bottom) { - RedrawScreenRect(left, top, right, bottom); - } - - } - } while (b++, (x += 64) != w); - } while (b += -(w >> 6) + DIRTY_BYTES_PER_LINE, (y += 8) != h); - - _invalid_rect.left = w; - _invalid_rect.top = h; - _invalid_rect.right = 0; - _invalid_rect.bottom = 0; - - /* If we are generating a world, and waiting for a paint run, mark it here - * as done painting, so we can continue generating. */ - if (IsGeneratingWorld() && IsGeneratingWorldReadyForPaint()) { - SetGeneratingWorldPaintStatus(false); - } -} - - -void SetDirtyBlocks(int left, int top, int right, int bottom) -{ - byte *b; - int width; - int height; - - if (left < 0) left = 0; - if (top < 0) top = 0; - if (right > _screen.width) right = _screen.width; - if (bottom > _screen.height) bottom = _screen.height; - - if (left >= right || top >= bottom) return; - - if (left < _invalid_rect.left ) _invalid_rect.left = left; - if (top < _invalid_rect.top ) _invalid_rect.top = top; - if (right > _invalid_rect.right ) _invalid_rect.right = right; - if (bottom > _invalid_rect.bottom) _invalid_rect.bottom = bottom; - - left >>= 6; - top >>= 3; - - b = _dirty_blocks + top * DIRTY_BYTES_PER_LINE + left; - - width = ((right - 1) >> 6) - left + 1; - height = ((bottom - 1) >> 3) - top + 1; - - assert(width > 0 && height > 0); - - do { - int i = width; - - do b[--i] = 0xFF; while (i); - - b += DIRTY_BYTES_PER_LINE; - } while (--height != 0); -} - -void MarkWholeScreenDirty(void) -{ - SetDirtyBlocks(0, 0, _screen.width, _screen.height); -} - -/** Set up a clipping area for only drawing into a certain area. To do this, - * Fill a DrawPixelInfo object with the supplied relative rectangle, backup - * the original (calling) _cur_dpi and assign the just returned DrawPixelInfo - * _cur_dpi. When you are done, give restore _cur_dpi's original value - * @param *n the DrawPixelInfo that will be the clipping rectangle box allowed - * for drawing - * @param left,top,width,height the relative coordinates of the clipping - * rectangle relative to the current _cur_dpi. This will most likely be the - * offset from the calling window coordinates - * @return return false if the requested rectangle is not possible with the - * current dpi pointer. Only continue of the return value is true, or you'll - * get some nasty results */ -bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int height) -{ - const DrawPixelInfo *o = _cur_dpi; - - n->zoom = 0; - - assert(width > 0); - assert(height > 0); - - if ((left -= o->left) < 0) { - width += left; - if (width <= 0) return false; - n->left = -left; - left = 0; - } else { - n->left = 0; - } - - if (width > o->width - left) { - width = o->width - left; - if (width <= 0) return false; - } - n->width = width; - - if ((top -= o->top) < 0) { - height += top; - if (height <= 0) return false; - n->top = -top; - top = 0; - } else { - n->top = 0; - } - - n->dst_ptr = o->dst_ptr + left + top * (n->pitch = o->pitch); - - if (height > o->height - top) { - height = o->height - top; - if (height <= 0) return false; - } - n->height = height; - - return true; -} - -static void SetCursorSprite(CursorID cursor) -{ - CursorVars *cv = &_cursor; - const Sprite *p; - - if (cv->sprite == cursor) return; - - p = GetSprite(cursor & SPRITE_MASK); - cv->sprite = cursor; - cv->size.y = p->height; - cv->size.x = p->width; - cv->offs.x = p->x_offs; - cv->offs.y = p->y_offs; - - cv->dirty = true; -} - -static void SwitchAnimatedCursor(void) -{ - CursorVars *cv = &_cursor; - const CursorID *cur = cv->animate_cur; - CursorID sprite; - - // ANIM_CURSOR_END is 0xFFFF in table/animcursors.h - if (cur == NULL || *cur == 0xFFFF) cur = cv->animate_list; - - sprite = cur[0]; - cv->animate_timeout = cur[1]; - cv->animate_cur = cur + 2; - - SetCursorSprite(sprite); -} - -void CursorTick(void) -{ - if (_cursor.animate_timeout != 0 && --_cursor.animate_timeout == 0) - SwitchAnimatedCursor(); -} - -void SetMouseCursor(CursorID cursor) -{ - // Turn off animation - _cursor.animate_timeout = 0; - // Set cursor - SetCursorSprite(cursor); -} - -void SetAnimatedMouseCursor(const CursorID *table) -{ - _cursor.animate_list = table; - _cursor.animate_cur = NULL; - SwitchAnimatedCursor(); -} - -bool ChangeResInGame(int w, int h) -{ - return - (_screen.width == w && _screen.height == h) || - _video_driver->change_resolution(w, h); -} - -void ToggleFullScreen(bool fs) -{ - _video_driver->toggle_fullscreen(fs); - if (_fullscreen != fs && _num_resolutions == 0) { - DEBUG(driver, 0, "Could not find a suitable fullscreen resolution"); - } -} - -static int CDECL compare_res(const void *pa, const void *pb) -{ - int x = ((const uint16*)pa)[0] - ((const uint16*)pb)[0]; - if (x != 0) return x; - return ((const uint16*)pa)[1] - ((const uint16*)pb)[1]; -} - -void SortResolutions(int count) -{ - qsort(_resolutions, count, sizeof(_resolutions[0]), compare_res); -} -- cgit v1.2.3-70-g09d2