/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+* Artsoft Retro-Game Library *
*----------------------------------------------------------*
-* (c) 1995-98 Artsoft Entertainment *
-* Holger Schemel *
-* Oststrasse 11a *
-* 33604 Bielefeld *
-* phone: ++49 +521 290471 *
-* email: aeglos@valinor.owl.de *
+* (c) 1994-2002 Artsoft Entertainment *
+* Holger Schemel *
+* Detmolder Strasse 189 *
+* 33604 Bielefeld *
+* Germany *
+* e-mail: info@artsoft.org *
*----------------------------------------------------------*
-* text.c *
+* text.c *
***********************************************************/
#include <stdio.h>
/* ========================================================================= */
-/* exported variables */
+/* font functions */
/* ========================================================================= */
-struct FontInfo font;
+#define NUM_FONTS 2
+#define NUM_FONT_COLORS 4
+#define NUM_FONT_CHARS (FONT_LINES_PER_FONT * FONT_CHARS_PER_LINE)
+#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
+static GC tile_clip_gc = None;
+static Pixmap tile_clipmask[NUM_FONTS][NUM_FONT_COLORS][NUM_FONT_CHARS];
-/* ========================================================================= */
-/* font functions */
-/* ========================================================================= */
+static struct
+{
+ Bitmap **bitmap;
+ int xsize, ysize;
+} font_info[NUM_FONTS] =
+{
+ { &font.bitmap_big, FONT1_XSIZE, FONT1_YSIZE },
+ { &font.bitmap_medium, FONT6_XSIZE, FONT6_YSIZE }
+};
+
+static void InitFontClipmasks()
+{
+ static boolean clipmasks_initialized = FALSE;
+ boolean fonts_initialized = TRUE;
+ XGCValues clip_gc_values;
+ unsigned long clip_gc_valuemask;
+ GC copy_clipmask_gc;
+ int i, j, k;
+
+ for (i=0; i<NUM_FONTS; i++)
+ if (*font_info[i].bitmap == NULL)
+ fonts_initialized = FALSE;
+
+ if (!fonts_initialized)
+ return;
+
+ if (clipmasks_initialized)
+ for (i=0; i<NUM_FONTS; i++)
+ for (j=0; j<NUM_FONT_COLORS; j++)
+ for (k=0; k<NUM_FONT_CHARS; k++)
+ XFreePixmap(display, tile_clipmask[i][j][k]);
+
+ if (tile_clip_gc)
+ XFreeGC(display, tile_clip_gc);
+ tile_clip_gc = None;
+
+ /* This stuff is needed because X11 (XSetClipOrigin(), to be precise) is
+ often very slow when preparing a masked XCopyArea() for big Pixmaps.
+ To prevent this, create small (tile-sized) mask Pixmaps which will then
+ be set much faster with XSetClipOrigin() and speed things up a lot. */
+
+ clip_gc_values.graphics_exposures = False;
+ clip_gc_valuemask = GCGraphicsExposures;
+ tile_clip_gc = XCreateGC(display, window->drawable,
+ clip_gc_valuemask, &clip_gc_values);
+
+ /* create graphic context structures needed for clipping */
+ clip_gc_values.graphics_exposures = False;
+ clip_gc_valuemask = GCGraphicsExposures;
+ copy_clipmask_gc = XCreateGC(display, (*font_info[0].bitmap)->clip_mask,
+ clip_gc_valuemask, &clip_gc_values);
+
+ /* create only those clipping Pixmaps we really need */
+ for (i=0; i<NUM_FONTS; i++)
+ for (j=0; j<NUM_FONT_COLORS; j++)
+ for (k=0; k<NUM_FONT_CHARS; k++)
+ {
+ Bitmap *src_bitmap = *font_info[i].bitmap;
+ Pixmap src_pixmap = src_bitmap->clip_mask;
+ int xpos = k % FONT_CHARS_PER_LINE;
+ int ypos = k / FONT_CHARS_PER_LINE;
+ int xsize = font_info[i].xsize;
+ int ysize = font_info[i].ysize;
+ int src_x = xsize * xpos;
+ int src_y = ysize * (ypos + j * FONT_LINES_PER_FONT);
+
+ tile_clipmask[i][j][k] =
+ XCreatePixmap(display, window->drawable, xsize, ysize, 1);
+
+ XCopyArea(display, src_pixmap, tile_clipmask[i][j][k], copy_clipmask_gc,
+ src_x, src_y, xsize, ysize, 0, 0);
+ }
+
+ XFreeGC(display, copy_clipmask_gc);
+
+ clipmasks_initialized = TRUE;
+}
+#endif /* TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND */
-void InitFontInfo(Bitmap bitmap_big, Bitmap bitmap_medium,
- Bitmap bitmap_small)
+void InitFontInfo(Bitmap *bitmap_initial,
+ Bitmap *bitmap_big, Bitmap *bitmap_medium,
+ Bitmap *bitmap_small, Bitmap *bitmap_tile)
{
+ font.bitmap_initial = bitmap_initial;
font.bitmap_big = bitmap_big;
font.bitmap_medium = bitmap_medium;
font.bitmap_small = bitmap_small;
+ font.bitmap_tile = bitmap_tile;
+
+#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
+ InitFontClipmasks();
+#endif
}
int getFontWidth(int font_size, int font_type)
{
- return (font_size == FS_BIG ? FONT1_XSIZE :
- font_size == FS_MEDIUM ? FONT6_XSIZE :
- font_type == FC_SPECIAL1 ? FONT3_XSIZE :
+ return (font_type == FC_SPECIAL1 ? FONT3_XSIZE :
font_type == FC_SPECIAL2 ? FONT4_XSIZE :
font_type == FC_SPECIAL3 ? FONT5_XSIZE :
+ font_size == FS_BIG ? FONT1_XSIZE :
+ font_size == FS_MEDIUM ? FONT6_XSIZE :
+ font_size == FS_SMALL ? FONT2_XSIZE :
FONT2_XSIZE);
}
int getFontHeight(int font_size, int font_type)
{
- return (font_size == FS_BIG ? FONT1_YSIZE :
- font_size == FS_MEDIUM ? FONT6_YSIZE :
- font_type == FC_SPECIAL1 ? FONT3_YSIZE :
+ return (font_type == FC_SPECIAL1 ? FONT3_YSIZE :
font_type == FC_SPECIAL2 ? FONT4_YSIZE :
font_type == FC_SPECIAL3 ? FONT5_YSIZE :
+ font_size == FS_BIG ? FONT1_YSIZE :
+ font_size == FS_MEDIUM ? FONT6_YSIZE :
+ font_size == FS_SMALL ? FONT2_YSIZE :
FONT2_YSIZE);
}
void DrawInitText(char *text, int ypos, int color)
{
- if (window && font.bitmap_small)
+ if (window && font.bitmap_initial)
{
ClearRectangle(window, 0, ypos, video.width, FONT2_YSIZE);
DrawTextExt(window, (video.width - strlen(text) * FONT2_XSIZE)/2,
- ypos, text, FS_SMALL, color);
+ ypos, text, FS_INITIAL, color, FONT_OPAQUE);
FlushDisplay();
}
}
void DrawText(int x, int y, char *text, int font_size, int font_type)
{
- DrawTextExt(drawto, x, y, text, font_size, font_type);
+ int mask_mode = FONT_OPAQUE;
+
+ if (DrawingOnBackground(x, y))
+ mask_mode = FONT_MASKED;
+
+ DrawTextExt(drawto, x, y, text, font_size, font_type, mask_mode);
if (x < gfx.dx)
redraw_mask |= REDRAW_FIELD;
- else if (y < gfx.vy)
+ else if (y < gfx.vy || gfx.vy == 0)
redraw_mask |= REDRAW_DOOR_1;
}
-void DrawTextExt(DrawBuffer bitmap, int x, int y,
- char *text, int font_size, int font_type)
+void DrawTextExt(DrawBuffer *bitmap, int x, int y, char *text,
+ int font_size, int font_type, int mask_mode)
{
- Bitmap font_bitmap;
- int font_width, font_height, font_start;
+ Bitmap *font_bitmap;
+ int font_width, font_height, font_starty;
boolean print_inverse = FALSE;
- if (font_size != FS_SMALL && font_size != FS_BIG && font_size != FS_MEDIUM)
- font_size = FS_SMALL;
+ if (font_size != FS_BIG && font_size != FS_MEDIUM && font_size != FS_SMALL)
+ font_size = FS_INITIAL;
if (font_type < FC_RED || font_type > FC_SPECIAL3)
font_type = FC_RED;
font_width = getFontWidth(font_size, font_type);
font_height = getFontHeight(font_size, font_type);
- font_bitmap = (font_size == FS_BIG ? font.bitmap_big :
- font_size == FS_MEDIUM ? font.bitmap_medium :
- font.bitmap_small);
- font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE :
- font_size == FS_MEDIUM ? FONT6_YSIZE :
- FONT2_YSIZE) *
- FONT_LINES_PER_FONT);
+ font_bitmap = (font_type == FC_SPECIAL2 ? font.bitmap_tile :
+ font_size == FS_BIG ? font.bitmap_big :
+ font_size == FS_MEDIUM ? font.bitmap_medium :
+ font_size == FS_SMALL ? font.bitmap_small :
+ font.bitmap_initial);
+
+ if (font_bitmap == NULL)
+ return;
+
+ if (font_type == FC_SPECIAL2)
+ font_starty = (font_size == FS_BIG ? 0 : FONT1_YSIZE) * 5;
+ else
+ font_starty = (font_type * (font_size == FS_BIG ? FONT1_YSIZE :
+ font_size == FS_MEDIUM ? FONT6_YSIZE :
+ font_size == FS_SMALL ? FONT2_YSIZE :
+ FONT2_YSIZE) *
+ FONT_LINES_PER_FONT);
if (font_type == FC_SPECIAL3)
- font_start += (FONT4_YSIZE - FONT2_YSIZE) * FONT_LINES_PER_FONT;
+ font_starty -= FONT2_YSIZE * FONT_LINES_PER_FONT;
while (*text)
{
c = 92;
else if (c == 'ü' || c == 'Ü')
c = 93;
+ else if (c == '[' || c == ']') /* map to normal braces */
+ c = (c == '[' ? '(' : ')');
+ else if (c == '\\') /* bad luck ... */
+ c = '/';
- if (c >= 32 && c <= 95)
+ if ((c >= 32 && c <= 95) || c == '°' || c == '´' || c == '|')
{
int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
- int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
+ int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_starty;
int dest_x = x, dest_y = y;
- if (print_inverse)
+ if (c == '°' || c == '´' || c == '|') /* map '°' and 'TM' signs */
+ {
+ if (font_type == FC_SPECIAL2)
+ {
+ src_x = (c == '°' ? 1 : c == '´' ? 2 : 3) * font_width;
+ src_y = 4 * font_height;
+ }
+ else
+ {
+ src_x = FONT_CHARS_PER_LINE * font_width;
+ src_y = (c == '°' ? 1 : c == '´' ? 2 : 3) * font_height +font_starty;
+ }
+ }
+
+ if (print_inverse) /* special mode for text gadgets */
{
- BlitBitmap(font_bitmap, bitmap,
- FONT_CHARS_PER_LINE * font_width,
- 3 * font_height + font_start,
+ /* first step: draw solid colored rectangle (use "cursor" character) */
+ BlitBitmap(font_bitmap, bitmap, FONT_CHARS_PER_LINE * font_width,
+ 3 * font_height + font_starty,
font_width, font_height, x, y);
+ /* second step: draw masked black rectangle (use "space" character) */
SetClipOrigin(font_bitmap, font_bitmap->stored_clip_gc,
dest_x - src_x, dest_y - src_y);
BlitBitmapMasked(font_bitmap, bitmap,
0, 0, font_width, font_height, dest_x, dest_y);
}
- else
- BlitBitmap(font_bitmap, bitmap,
- src_x, src_y, font_width, font_height, dest_x, dest_y);
+ else if (mask_mode == FONT_MASKED)
+ {
+ /* clear font character background */
+ BlitBitmap(gfx.background_bitmap, bitmap,
+ dest_x - gfx.real_sx, dest_y - gfx.real_sy,
+ font_width, font_height, dest_x, dest_y);
+
+#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
+ /* use special font tile clipmasks, if available */
+ if (font_size == FS_BIG || font_size == FS_MEDIUM)
+ {
+ int font_nr = (font_size == FS_BIG ? 0 : 1);
+ int font_char = (c >= 32 && c <= 95 ? c - 32 : 0);
+
+ SetClipMask(font_bitmap, tile_clip_gc,
+ tile_clipmask[font_nr][font_type][font_char]);
+ SetClipOrigin(font_bitmap, tile_clip_gc, dest_x, dest_y);
+ }
+ else
+ {
+ SetClipOrigin(font_bitmap, font_bitmap->stored_clip_gc,
+ dest_x - src_x, dest_y - src_y);
+ }
+#else
+ SetClipOrigin(font_bitmap, font_bitmap->stored_clip_gc,
+ dest_x - src_x, dest_y - src_y);
+#endif
+
+ BlitBitmapMasked(font_bitmap, bitmap, src_x, src_y,
+ font_width, font_height, dest_x, dest_y);
+ }
+ else /* normal, non-masked font blitting */
+ {
+ BlitBitmap(font_bitmap, bitmap, src_x, src_y,
+ font_width, font_height, dest_x, dest_y);
+ }
}
x += font_width;