src/gfx.cpp
changeset 6852 439563b70fd3
parent 6831 cf918fdb9e8a
child 6878 5cefd3ac59c7
equal deleted inserted replaced
6851:0a0a094fb9f1 6852:439563b70fd3
    17 #include "table/control_codes.h"
    17 #include "table/control_codes.h"
    18 #include "fontcache.h"
    18 #include "fontcache.h"
    19 #include "genworld.h"
    19 #include "genworld.h"
    20 #include "debug.h"
    20 #include "debug.h"
    21 #include "zoom.hpp"
    21 #include "zoom.hpp"
       
    22 #include "blitter/blitter.hpp"
    22 
    23 
    23 #ifdef _DEBUG
    24 #ifdef _DEBUG
    24 bool _dbg_screen_rect;
    25 bool _dbg_screen_rect;
    25 #endif
    26 #endif
    26 
    27 
    43 int _pal_last_dirty;
    44 int _pal_last_dirty;
    44 
    45 
    45 Colour _cur_palette[256];
    46 Colour _cur_palette[256];
    46 byte _stringwidth_table[FS_END][224];
    47 byte _stringwidth_table[FS_END][224];
    47 
    48 
    48 enum BlitterMode {
    49 static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode);
    49 	BM_NORMAL,
       
    50 	BM_COLOUR_REMAP,
       
    51 	BM_TRANSPARENT,
       
    52 };
       
    53 
       
    54 template <BlitterMode Tmode>
       
    55 static inline void GfxMainBlitter(const Sprite *sprite, int x, int y);
       
    56 
    50 
    57 FontSize _cur_fontsize;
    51 FontSize _cur_fontsize;
    58 static FontSize _last_fontsize;
    52 static FontSize _last_fontsize;
    59 static Pixel _cursor_backup[64 * 64];
    53 static Pixel _cursor_backup[64 * 64];
    60 static Rect _invalid_rect;
    54 static Rect _invalid_rect;
   681 			return x;
   675 			return x;
   682 		}
   676 		}
   683 		if (IsPrintable(c)) {
   677 		if (IsPrintable(c)) {
   684 			if (x >= dpi->left + dpi->width) goto skip_char;
   678 			if (x >= dpi->left + dpi->width) goto skip_char;
   685 			if (x + 26 >= dpi->left) {
   679 			if (x + 26 >= dpi->left) {
   686 				GfxMainBlitter<BM_COLOUR_REMAP>(GetGlyph(size, c), x, y);
   680 				GfxMainBlitter(GetGlyph(size, c), x, y, BM_COLOUR_REMAP);
   687 			}
   681 			}
   688 			x += GetCharacterWidth(size, c);
   682 			x += GetCharacterWidth(size, c);
   689 		} else if (c == '\n') { // newline = {}
   683 		} else if (c == '\n') { // newline = {}
   690 			x = xo;
   684 			x = xo;
   691 			y += GetCharacterHeight(size);
   685 			y += GetCharacterHeight(size);
   718 
   712 
   719 void DrawSprite(SpriteID img, SpriteID pal, int x, int y)
   713 void DrawSprite(SpriteID img, SpriteID pal, int x, int y)
   720 {
   714 {
   721 	if (HASBIT(img, PALETTE_MODIFIER_TRANSPARENT)) {
   715 	if (HASBIT(img, PALETTE_MODIFIER_TRANSPARENT)) {
   722 		_color_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH)) + 1;
   716 		_color_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH)) + 1;
   723 		GfxMainBlitter<BM_TRANSPARENT>(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y);
   717 		GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y, BM_TRANSPARENT);
   724 	} else if (pal != PAL_NONE) {
   718 	} else if (pal != PAL_NONE) {
   725 		_color_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH)) + 1;
   719 		_color_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH)) + 1;
   726 		GfxMainBlitter<BM_COLOUR_REMAP>(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y);
   720 		GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y, BM_COLOUR_REMAP);
   727 	} else {
   721 	} else {
   728 		GfxMainBlitter<BM_NORMAL>(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y);
   722 		GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y, BM_NORMAL);
   729 	}
   723 	}
   730 }
   724 }
   731 
   725 
   732 struct BlitterParams {
   726 static inline void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode)
   733 	int start_x, start_y;
       
   734 	const byte *sprite;
       
   735 	Pixel *dst;
       
   736 	int width, height;
       
   737 	int width_org;
       
   738 	int pitch;
       
   739 };
       
   740 
       
   741 template <BlitterMode Tmode, ZoomLevel Tzoom>
       
   742 static inline void GfxBlitZoomUncomp(BlitterParams *bp)
       
   743 {
       
   744 	const byte *src = bp->sprite + bp->start_y * bp->width_org + bp->start_x;
       
   745 	Pixel *dst = bp->dst;
       
   746 	int height = bp->height;
       
   747 	int width = bp->width;
       
   748 	int i;
       
   749 
       
   750 	assert(height > 0);
       
   751 	assert(width > 0);
       
   752 
       
   753 	height = UnScaleByZoom(height, Tzoom);
       
   754 
       
   755 	switch (Tmode) {
       
   756 		case BM_COLOUR_REMAP: {
       
   757 			const byte *ctab = _color_remap_ptr;
       
   758 
       
   759 			for (; height != 0; height--) {
       
   760 				for (i = 0; i != UnScaleByZoom(width, Tzoom); i++) {
       
   761 					byte b = ctab[src[ScaleByZoom(i, Tzoom)]];
       
   762 
       
   763 					if (b != 0) dst[i] = b;
       
   764 				}
       
   765 				src += ScaleByZoom(bp->width_org, Tzoom);
       
   766 				dst += bp->pitch;
       
   767 			}
       
   768 			break;
       
   769 		}
       
   770 
       
   771 		case BM_TRANSPARENT: {
       
   772 			const byte *ctab = _color_remap_ptr;
       
   773 
       
   774 			for (; height != 0; height--) {
       
   775 				for (i = 0; i != UnScaleByZoom(width, Tzoom); i++)
       
   776 					if (src[ScaleByZoom(i, Tzoom)] != 0) dst[i] = ctab[dst[i]];
       
   777 				src += ScaleByZoom(bp->width_org, Tzoom);
       
   778 				dst += bp->pitch;
       
   779 			}
       
   780 			break;
       
   781 		}
       
   782 
       
   783 		default:
       
   784 			for (; height != 0; height--) {
       
   785 				for (i = 0; i != UnScaleByZoom(width, Tzoom); i++)
       
   786 					if (src[ScaleByZoom(i, Tzoom)] != 0) dst[i] = src[ScaleByZoom(i, Tzoom)];
       
   787 				src += ScaleByZoom(bp->width_org, Tzoom);
       
   788 				dst += bp->pitch;
       
   789 			}
       
   790 			break;
       
   791 	}
       
   792 }
       
   793 
       
   794 template <BlitterMode Tmode, ZoomLevel Tzoom>
       
   795 static inline void GfxBlitTileZoom(BlitterParams *bp)
       
   796 {
       
   797 	const byte *src_o = bp->sprite;
       
   798 	const byte *src;
       
   799 	int num, skip;
       
   800 	byte done;
       
   801 	Pixel *dst;
       
   802 	const byte *ctab;
       
   803 
       
   804 	src_o += ReadLE16Aligned(src_o + bp->start_y * 2);
       
   805 
       
   806 	for (;;) {
       
   807 		do {
       
   808 			done = src_o[0];
       
   809 			num = done & 0x7F;
       
   810 			skip = src_o[1];
       
   811 			src = src_o + 2;
       
   812 			src_o += num + 2;
       
   813 
       
   814 			dst = bp->dst;
       
   815 
       
   816 			if (Tzoom >= ZOOM_LVL_OUT_2X && (skip & 1)) {
       
   817 				skip += 1;
       
   818 				src += 1;
       
   819 				num -= 1;
       
   820 				if (num <= 0) continue;
       
   821 			}
       
   822 
       
   823 			if (Tzoom >= ZOOM_LVL_OUT_4X && (skip & 2)) {
       
   824 				skip += 2;
       
   825 				src += 2;
       
   826 				num -= 2;
       
   827 				if (num <= 0) continue;
       
   828 			}
       
   829 
       
   830 			if (Tzoom >= ZOOM_LVL_OUT_8X && (skip & 4)) {
       
   831 				skip += 4;
       
   832 				src += 4;
       
   833 				num -= 4;
       
   834 				if (num <= 0) continue;
       
   835 			}
       
   836 
       
   837 			if (Tzoom >= ZOOM_LVL_OUT_16X && (skip & 8)) {
       
   838 				skip += 8;
       
   839 				src += 8;
       
   840 				num -= 8;
       
   841 				if (num <= 0) continue;
       
   842 			}
       
   843 
       
   844 			if ( (skip -= bp->start_x) > 0) {
       
   845 				dst += UnScaleByZoom(skip, Tzoom);
       
   846 			} else {
       
   847 				src -= skip;
       
   848 				num += skip;
       
   849 				if (num <= 0) continue;
       
   850 				skip = 0;
       
   851 			}
       
   852 
       
   853 			skip = skip + num - bp->width;
       
   854 			if (skip > 0) {
       
   855 				num -= skip;
       
   856 				if (num <= 0) continue;
       
   857 			}
       
   858 
       
   859 			num = UnScaleByZoom(num, Tzoom);
       
   860 
       
   861 			switch (Tmode) {
       
   862 				case BM_COLOUR_REMAP:
       
   863 					ctab = _color_remap_ptr;
       
   864 					for (; num != 0; num--) {
       
   865 							*dst = ctab[*src];
       
   866 							dst++;
       
   867 							src += ScaleByZoom(1, Tzoom);
       
   868 					}
       
   869 					break;
       
   870 
       
   871 				case BM_TRANSPARENT:
       
   872 					ctab = _color_remap_ptr;
       
   873 					for (; num != 0; num--) {
       
   874 							*dst = ctab[*dst];
       
   875 							dst++;
       
   876 					}
       
   877 					break;
       
   878 
       
   879 				default:
       
   880 					if (Tzoom == ZOOM_LVL_NORMAL) {
       
   881 						memcpy(dst, src, num);
       
   882 					} else {
       
   883 						for (; num != 0; num--) {
       
   884 								*dst = *src;
       
   885 								dst++;
       
   886 								src += ScaleByZoom(1, Tzoom);
       
   887 						}
       
   888 					}
       
   889 					break;
       
   890 			}
       
   891 
       
   892 
       
   893 		} while (!(done & 0x80));
       
   894 
       
   895 		bp->dst += bp->pitch;
       
   896 		if (--bp->height == 0) return;
       
   897 
       
   898 		for (int i = 0; i < ScaleByZoom(1, Tzoom) - 1; i++) {
       
   899 			do {
       
   900 				done = src_o[0];
       
   901 				src_o += (done & 0x7F) + 2;
       
   902 			} while (!(done & 0x80));
       
   903 			if (--bp->height == 0) return;
       
   904 		}
       
   905 	}
       
   906 }
       
   907 
       
   908 template <BlitterMode Tmode>
       
   909 static inline void GfxMainBlitter(const Sprite *sprite, int x, int y)
       
   910 {
   727 {
   911 	const DrawPixelInfo *dpi = _cur_dpi;
   728 	const DrawPixelInfo *dpi = _cur_dpi;
   912 	int start_x, start_y;
   729 	Blitter::BlitterParams bp;
   913 	BlitterParams bp;
   730 
   914 	int zoom_mask = ~(ScaleByZoom(1, dpi->zoom) - 1);
   731 	/* Move to the correct offset */
   915 
       
   916 	/* decode sprite header */
       
   917 	x += sprite->x_offs;
   732 	x += sprite->x_offs;
   918 	y += sprite->y_offs;
   733 	y += sprite->y_offs;
   919 	bp.width_org = bp.width = sprite->width;
   734 
   920 	bp.height = sprite->height;
   735 	/* Copy the main data directly from the sprite */
   921 	bp.sprite = sprite->data;
   736 	bp.sprite = sprite->data;
       
   737 	bp.sprite_width = sprite->width;
       
   738 	bp.sprite_height = sprite->height;
       
   739 	bp.width = UnScaleByZoom(sprite->width, dpi->zoom);
       
   740 	bp.height = UnScaleByZoom(sprite->height, dpi->zoom);
       
   741 	bp.top = 0;
       
   742 	bp.left = 0;
       
   743 	bp.skip_left = 0;
       
   744 	bp.skip_top = 0;
   922 	bp.dst = dpi->dst_ptr;
   745 	bp.dst = dpi->dst_ptr;
   923 	bp.pitch = dpi->pitch;
   746 	bp.pitch = dpi->pitch;
   924 
   747 	bp.remap = _color_remap_ptr;
   925 	assert(bp.height > 0);
   748 
   926 	assert(bp.width > 0);
   749 	assert(sprite->width > 0);
   927 
   750 	assert(sprite->height > 0);
   928 	start_y = 0;
   751 
   929 	if (dpi->zoom > ZOOM_LVL_NORMAL) {
   752 	if (bp.width <= 0) return;
   930 		start_y += bp.height & ~zoom_mask;
   753 	if (bp.height <= 0) return;
   931 		bp.height &= zoom_mask;
   754 
   932 		if (bp.height == 0) return;
   755 	y -= dpi->top;
   933 		y &= zoom_mask;
   756 	/* Check for top overflow */
   934 	}
   757 	if (y < 0) {
   935 
   758 		bp.height -= -UnScaleByZoom(y, dpi->zoom);
   936 	if ( (y -= dpi->top) < 0) {
       
   937 		bp.height += y;
       
   938 		if (bp.height <= 0) return;
   759 		if (bp.height <= 0) return;
   939 		start_y -= y;
   760 		bp.skip_top += -UnScaleByZoom(y, dpi->zoom);
   940 		y = 0;
   761 		y = 0;
   941 	} else {
   762 	} else {
   942 		bp.dst += bp.pitch * UnScaleByZoom(y, dpi->zoom);
   763 		bp.top = UnScaleByZoom(y, dpi->zoom);
   943 	}
   764 	}
   944 	bp.start_y = start_y;
   765 
   945 
   766 	/* Check for bottom overflow */
   946 	if ( (y = y + bp.height - dpi->height) > 0) {
   767 	y += ScaleByZoom(bp.height, dpi->zoom) - dpi->height;
   947 		bp.height -= y;
   768 	if (y > 0) {
       
   769 		bp.height -= UnScaleByZoom(y, dpi->zoom);
   948 		if (bp.height <= 0) return;
   770 		if (bp.height <= 0) return;
   949 	}
   771 	}
   950 
   772 
   951 	start_x = 0;
   773 	x -= dpi->left;
   952 	x &= zoom_mask;
   774 	/* Check for left overflow */
   953 	if ( (x -= dpi->left) < 0) {
   775 	if (x < 0) {
   954 		bp.width += x;
   776 		bp.width -= -UnScaleByZoom(x, dpi->zoom);
   955 		if (bp.width <= 0) return;
   777 		if (bp.width <= 0) return;
   956 		start_x -= x;
   778 		bp.skip_left += -UnScaleByZoom(x, dpi->zoom);
   957 		x = 0;
   779 		x = 0;
   958 	}
   780 	} else {
   959 	bp.start_x = start_x;
   781 		bp.left = UnScaleByZoom(x, dpi->zoom);
   960 	bp.dst += UnScaleByZoom(x, dpi->zoom);
   782 	}
   961 
   783 
   962 	if ( (x = x + bp.width - dpi->width) > 0) {
   784 	/* Check for right overflow */
   963 		bp.width -= x;
   785 	x += ScaleByZoom(bp.width, dpi->zoom) - dpi->width;
       
   786 	if (x > 0) {
       
   787 		bp.width -= UnScaleByZoom(x, dpi->zoom);
   964 		if (bp.width <= 0) return;
   788 		if (bp.width <= 0) return;
   965 	}
   789 	}
   966 
   790 
   967 	if (sprite->info & 8) {
   791 	BlitterFactoryBase::GetCurrentBlitter()->Draw(&bp, mode, dpi->zoom);
   968 		switch (dpi->zoom) {
       
   969 			case ZOOM_LVL_NORMAL:  GfxBlitTileZoom<Tmode, ZOOM_LVL_NORMAL>(&bp);  break;
       
   970 			case ZOOM_LVL_OUT_2X:  GfxBlitTileZoom<Tmode, ZOOM_LVL_OUT_2X>(&bp);  break;
       
   971 			case ZOOM_LVL_OUT_4X:  GfxBlitTileZoom<Tmode, ZOOM_LVL_OUT_4X>(&bp);  break;
       
   972 			case ZOOM_LVL_OUT_8X:  GfxBlitTileZoom<Tmode, ZOOM_LVL_OUT_8X>(&bp);  break;
       
   973 			case ZOOM_LVL_OUT_16X: GfxBlitTileZoom<Tmode, ZOOM_LVL_OUT_16X>(&bp); break;
       
   974 			default: NOT_REACHED();
       
   975 		}
       
   976 	} else {
       
   977 		switch (dpi->zoom) {
       
   978 			case ZOOM_LVL_NORMAL:  GfxBlitZoomUncomp<Tmode, ZOOM_LVL_NORMAL>(&bp);  break;
       
   979 			case ZOOM_LVL_OUT_2X:  GfxBlitZoomUncomp<Tmode, ZOOM_LVL_OUT_2X>(&bp);  break;
       
   980 			case ZOOM_LVL_OUT_4X:  GfxBlitZoomUncomp<Tmode, ZOOM_LVL_OUT_4X>(&bp);  break;
       
   981 			case ZOOM_LVL_OUT_8X:  GfxBlitZoomUncomp<Tmode, ZOOM_LVL_OUT_8X>(&bp);  break;
       
   982 			case ZOOM_LVL_OUT_16X: GfxBlitZoomUncomp<Tmode, ZOOM_LVL_OUT_16X>(&bp); break;
       
   983 			default: NOT_REACHED();
       
   984 		}
       
   985 	}
       
   986 }
   792 }
   987 
   793 
   988 void DoPaletteAnimations();
   794 void DoPaletteAnimations();
   989 
   795 
   990 void GfxInitPalettes()
   796 void GfxInitPalettes()