/* keyword to stop parser: "NO_MORE_ELEMENT_IMAGES" <-- do not change! */
{ "menu.frame", "RocksScreen.pcx" },
- { "menu.back", UNDEFINED_FILENAME },
+ { "menu.background", UNDEFINED_FILENAME },
{ "menu.door", "RocksDoor.pcx" },
{ "menu.toons", "RocksToons.pcx" },
{ "menu.font_big", "RocksFontBig.pcx" },
#define IMG_CUSTOM_126 734
#define IMG_CUSTOM_127 735
#define IMG_MENU_FRAME 736
-#define IMG_MENU_BACK 737
+#define IMG_MENU_BACKGROUND 737
#define IMG_MENU_DOOR 738
#define IMG_MENU_TOONS 739
#define IMG_MENU_FONT_BIG 740
-#define COMPILE_DATE_STRING "[2003-01-04 04:16]"
+#define COMPILE_DATE_STRING "[2003-01-05 20:26]"
static void DrawDrawingWindow()
{
+ SetBackgroundBitmap(NULL);
ClearWindow();
-
-#if 1
- ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
- redraw_mask |= REDRAW_FROM_BACKBUFFER;
-#endif
-
UnmapLevelEditorWindowGadgets();
+
AdjustDrawingAreaGadgets();
AdjustLevelScrollPosition();
AdjustEditorScrollbar(GADGET_ID_SCROLL_HORIZONTAL);
AdjustEditorScrollbar(GADGET_ID_SCROLL_VERTICAL);
+
DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
MapMainDrawingArea();
}
+static void DrawElementBorder(int dest_x, int dest_y, int width, int height)
+{
+ int border_graphic = IMG_SAND;
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+ int num_mini_tilex = width / MINI_TILEX + 1;
+ int num_mini_tiley = width / MINI_TILEY + 1;
+ int x, y;
+
+ getMiniGraphicSource(border_graphic, &src_bitmap, &src_x, &src_y);
+
+ for (y=0; y < num_mini_tiley; y++)
+ for (x=0; x < num_mini_tilex; x++)
+ BlitBitmap(src_bitmap, drawto, src_x, src_y, MINI_TILEX, MINI_TILEY,
+ dest_x - MINI_TILEX / 2 + x * MINI_TILEX,
+ dest_y - MINI_TILEY / 2 + y * MINI_TILEY);
+
+ ClearRectangle(drawto, dest_x - 1, dest_y - 1, width + 2, height + 2);
+}
+
static void DrawRandomPlacementBackgroundArea()
{
int area_x = ED_AREA_RANDOM_BACKGROUND_XPOS / MINI_TILEX;
int area_y = ED_AREA_RANDOM_BACKGROUND_YPOS / MINI_TILEY;
int area_sx = SX + ED_AREA_RANDOM_BACKGROUND_XPOS;
int area_sy = SY + ED_AREA_RANDOM_BACKGROUND_YPOS;
- int x, y;
ElementContent[0][0][0] = random_placement_background_element;
- /* draw decorative border for the object */
- for (y=0; y<2; y++)
- for (x=0; x<2; x++)
- DrawMiniElement(area_x + x, area_y + y, EL_SAND);
-
- ClearRectangle(drawto,
- area_sx + MINI_TILEX/2 - 1, area_sy + MINI_TILEY/2 - 1,
- MINI_TILEX + 2, MINI_TILEY + 2);
-
- /* copy border to the right location */
- BlitBitmap(drawto, drawto,
- area_sx, area_sy, 3 * MINI_TILEX, 3 * MINI_TILEY,
- area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
-
+ DrawElementBorder(area_sx, area_sy, MINI_TILEX, MINI_TILEY);
DrawMiniElement(area_x, area_y, ElementContent[0][0][0]);
MapDrawingArea(GADGET_ID_RANDOM_BACKGROUND);
int font_color = FC_GREEN;
int i, x, y;
+ SetBackgroundBitmap(new_graphic_info[IMG_MENU_BACKGROUND].bitmap);
ClearWindow();
UnmapLevelEditorWindowGadgets();
int area_sx = SX + ED_AREA_ELEM_CONTENT_XPOS;
int area_sy = SY + ED_AREA_ELEM_CONTENT_YPOS;
int font_color = FC_GREEN;
- int x, y;
ElementContent[0][0][0] = level.amoeba_content;
- /* draw decorative border for the object */
- for (y=0; y<2; y++)
- for (x=0; x<2; x++)
- DrawMiniElement(area_x + x, area_y + y, EL_SAND);
-
- ClearRectangle(drawto,
- area_sx + MINI_TILEX/2 - 1, area_sy + MINI_TILEY/2 - 1,
- MINI_TILEX + 2, MINI_TILEY + 2);
-
- /* copy border to the right location */
- BlitBitmap(drawto, drawto,
- area_sx, area_sy, 3 * MINI_TILEX, 3 * MINI_TILEY,
- area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
+ DrawElementBorder(area_sx, area_sy, MINI_TILEX, MINI_TILEY);
+ DrawMiniElement(area_x, area_y, ElementContent[0][0][0]);
DrawText(area_sx + TILEX, area_sy + 1, "Content of amoeba",
FS_SMALL, font_color);
- DrawMiniElement(area_x, area_y, ElementContent[0][0][0]);
-
MapDrawingArea(GADGET_ID_AMOEBA_CONTENT);
}
MapCounterButtons(counter_id);
/* delete content areas in case of reducing number of them */
- ClearRectangle(backbuffer,
- SX, area_sy - MINI_TILEX,
- SXSIZE, 12 * MINI_TILEY);
+ DrawBackground(SX, area_sy - MINI_TILEX, SXSIZE, 12 * MINI_TILEY);
- /* draw some decorative border for the objects */
for (i=0; i<level.num_yam_contents; i++)
- {
- for (y=0; y<4; y++)
- for (x=0; x<4; x++)
- DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
- EL_SAND);
-
- ClearRectangle(drawto,
- area_sx + 5 * (i % 4) * MINI_TILEX + MINI_TILEX/2 - 1,
- area_sy + 6 * (i / 4) * MINI_TILEY + MINI_TILEY/2 - 1,
- 3 * MINI_TILEX + 2, 3 * MINI_TILEY + 2);
- }
-
- /* copy border to the right location */
- BlitBitmap(drawto, drawto,
- area_sx, area_sy, (5 * 4 + 1) * MINI_TILEX, 11 * MINI_TILEY,
- area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
+ DrawElementBorder(area_sx + 5 * (i % 4) * MINI_TILEX,
+ area_sy + 6 * (i / 4) * MINI_TILEY,
+ 3 * MINI_TILEX, 3 * MINI_TILEY);
DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 0 * MINI_TILEY + 1,
"Content", FS_SMALL, font_color);
MapDrawingArea(GADGET_ID_ELEM_CONTENT_0 + i);
}
-#if 0
-static void DrawPropertiesElement(int xstart, int ystart, int element)
-{
- int x, y;
-
- /* draw some decorative border for the object */
- for (y=0; y<3; y++)
- for (x=0; x<3; x++)
- DrawMiniElement(xstart + x , ystart + y, EL_SAND);
-
- ClearRectangle(drawto,
- SX + xstart * MINI_TILEX + MINI_TILEX/2 - 1,
- SY + ystart * MINI_TILEY + MINI_TILEY/2 - 1,
- TILEX + 2, TILEY + 2);
-
- /* copy border to the right location */
- BlitBitmap(drawto, drawto,
- SX + xstart * MINI_TILEX,
- SY + ystart * MINI_TILEY,
- 2 * TILEX, 2 * TILEY,
- SX + xstart * MINI_TILEX - MINI_TILEX/2,
- SY + ystart * MINI_TILEY - MINI_TILEY/2);
-
- DrawGraphicAnimation(xstart / 2, ystart / 2, el2img(element));
-
- /* copy the whole stuff to the definitive location */
- BlitBitmap(drawto, drawto,
- SX + xstart * MINI_TILEX - MINI_TILEX/2,
- SY + ystart * MINI_TILEY - MINI_TILEY,
- 2 * TILEX, 2 * TILEY,
- SX + xstart * MINI_TILEX - MINI_TILEX/2,
- SY + ystart * MINI_TILEY - MINI_TILEY/2);
-
- FrameCounter++; /* increase animation frame counter */
-}
-#endif
-
#define TEXT_COLLECTING "Score for collecting"
#define TEXT_SMASHING "Score for smashing"
#define TEXT_CRACKING "Score for cracking"
{ -1, NULL, NULL }
};
+ SetBackgroundBitmap(new_graphic_info[IMG_MENU_BACKGROUND].bitmap);
ClearWindow();
UnmapLevelEditorWindowGadgets();
DrawText(SX + ED_SETTINGS2_XPOS, SY + ED_SETTINGS_YPOS,
"Element Settings", FS_BIG, FC_YELLOW);
-#if 1
- /* draw some decorative border for the object */
- for (y=0; y<3; y++)
- for (x=0; x<3; x++)
- DrawMiniElement(xstart + x , ystart + y, EL_SAND);
-
- ClearRectangle(drawto,
- SX + xstart * MINI_TILEX + MINI_TILEX/2 - 1,
- SY + ystart * MINI_TILEY + MINI_TILEY/2 - 1,
- TILEX + 2, TILEY + 2);
-
- /* copy border to the right location */
- BlitBitmap(drawto, drawto,
- SX + xstart * MINI_TILEX,
- SY + ystart * MINI_TILEY,
- 2 * TILEX, 2 * TILEY,
- SX + xstart * MINI_TILEX - MINI_TILEX/2,
- SY + ystart * MINI_TILEY - MINI_TILEY/2);
-
-#if 0
- DrawGraphic(xstart / 2, ystart / 2, el2img(properties_element), 0);
-#else
- DrawGraphicAnimation(xstart / 2, ystart / 2, el2img(properties_element));
-#endif
-
- /* copy the whole stuff to the definitive location */
- BlitBitmap(drawto, drawto,
- SX + xstart * MINI_TILEX - MINI_TILEX/2,
- SY + ystart * MINI_TILEY - MINI_TILEY,
- 2 * TILEX, 2 * TILEY,
- SX + xstart * MINI_TILEX - MINI_TILEX/2,
- SY + ystart * MINI_TILEY - MINI_TILEY/2);
-
- FrameCounter = 0; /* restart animation frame counter */
-
-#else
+ DrawElementBorder(SX + xstart * MINI_TILEX,
+ SY + ystart * MINI_TILEY + MINI_TILEY / 2,
+ TILEX, TILEY);
+ DrawGraphicAnimationExt(drawto,
+ SX + xstart * MINI_TILEX,
+ SY + ystart * MINI_TILEY + MINI_TILEY / 2,
+ el2img(properties_element), NO_MASKING);
FrameCounter = 0; /* restart animation frame counter */
- DrawPropertiesElement(xstart, ystart, properties_element);
-
-#endif
DrawTextF((xstart + 3) * MINI_TILEX, (ystart + 1) * MINI_TILEY,
font_color, getElementInfoText(properties_element));
if (!DelayReached(&action_delay, action_delay_value))
return;
- FY += MINI_TILEY / 2;
#if 1
- DrawGraphicAnimation(xpos, ypos, el2img(properties_element));
+
+ DrawGraphicAnimationExt(drawto,
+ SX + xpos * TILEX,
+ SY + ypos * TILEY + MINI_TILEY / 2,
+ el2img(properties_element), NO_MASKING);
+
#else
- DrawGraphicAnimation(xpos, ypos, el_dir_act2img(properties_element,
- MV_NO_MOVING,
- ...));
+ DrawGraphicAnimationExt(drawto,
+ SX + xpos * TILEX,
+ SY + ypos * TILEY + MINI_TILEY / 2,
+ el_dir_act2img(properties_element,
+ MV_NO_MOVING,
+ ...));
#endif
- FY -= MINI_TILEY / 2;
+
+ MarkTileDirty(xpos, ypos);
MarkTileDirty(xpos, ypos + 1);
FrameCounter++; /* increase animation frame counter */
void ClearEditorGadgetInfoText()
{
- ClearRectangle(drawto,
- INFOTEXT_XPOS, INFOTEXT_YPOS, INFOTEXT_XSIZE, INFOTEXT_YSIZE);
- redraw_mask |= REDRAW_FIELD;
+ DrawBackground(INFOTEXT_XPOS, INFOTEXT_YPOS, INFOTEXT_XSIZE, INFOTEXT_YSIZE);
}
void HandleEditorGadgetInfoText(void *ptr)
else
{
DrawTextExt(drawto, DX + XX_EMERALDS, DY + YY_EMERALDS,
- int2str(level_nr, 3), FS_SMALL, FC_SPECIAL3);
+ int2str(level_nr, 3), FS_SMALL, FC_SPECIAL3, FONT_OPAQUE);
BlitBitmap(drawto, drawto,
DX + XX_EMERALDS, DY + YY_EMERALDS + 1,
FONT5_XSIZE * 3, FONT5_YSIZE - 1,
new_graphic_info[IMG_MENU_FONT_SMALL].bitmap,
new_graphic_info[IMG_MENU_FONT_EM].bitmap);
+ SetBackgroundBitmap(NULL);
+
InitGadgets();
InitToons();
}
static void InitGraphicInfo()
{
+ static boolean clipmasks_initialized = FALSE;
static int gfx_action[NUM_IMAGE_FILES];
Bitmap *src_bitmap;
int src_x, src_y;
int first_frame, last_frame;
int i;
+#if defined(TARGET_X11_NATIVE)
+ Pixmap src_pixmap;
+ XGCValues clip_gc_values;
+ unsigned long clip_gc_valuemask;
+ GC copy_clipmask_gc = None;
+#endif
image_files = getCurrentImageList();
i++;
}
+#if defined(TARGET_X11_NATIVE)
+ if (clipmasks_initialized)
+ {
+ for (i=0; i<NUM_IMAGE_FILES; i++)
+ {
+ if (new_graphic_info[i].clip_mask)
+ XFreePixmap(display, new_graphic_info[i].clip_mask);
+ if (new_graphic_info[i].clip_gc)
+ XFreeGC(display, new_graphic_info[i].clip_gc);
+
+ new_graphic_info[i].clip_mask = None;
+ new_graphic_info[i].clip_gc = None;
+ }
+ }
+#endif
+
for (i=0; i<NUM_IMAGE_FILES; i++)
{
int *parameter = image_files[i].parameter;
/* now check if no animation frames are outside of the loaded image */
if (new_graphic_info[i].bitmap == NULL)
- continue; /* skip check for optional images */
+ continue; /* skip check for optional images that are undefined */
first_frame = 0;
getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
Error(ERR_EXIT, "error: last animation frame out of bounds (%d,%d)",
src_x, src_y);
}
+
+#if defined(TARGET_X11_NATIVE)
+ /* currently we need only a tile clip mask from the first frame */
+ getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
+
+ if (copy_clipmask_gc == None)
+ {
+ clip_gc_values.graphics_exposures = False;
+ clip_gc_valuemask = GCGraphicsExposures;
+ copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
+ clip_gc_valuemask, &clip_gc_values);
+ }
+
+ new_graphic_info[i].clip_mask =
+ XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
+
+ src_pixmap = src_bitmap->clip_mask;
+ XCopyArea(display, src_pixmap, new_graphic_info[i].clip_mask,
+ copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
+
+ clip_gc_values.graphics_exposures = False;
+ clip_gc_values.clip_mask = new_graphic_info[i].clip_mask;
+ clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
+ new_graphic_info[i].clip_gc =
+ XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
+#endif
}
+
+#if defined(TARGET_X11_NATIVE)
+ if (copy_clipmask_gc)
+ XFreeGC(display, copy_clipmask_gc);
+#endif
+
+ clipmasks_initialized = TRUE;
}
static void InitSoundInfo()
case GD_TYPE_NORMAL_BUTTON:
case GD_TYPE_CHECK_BUTTON:
case GD_TYPE_RADIO_BUTTON:
- BlitBitmap(gd->bitmap, drawto,
- gd->x, gd->y, gi->width, gi->height, gi->x, gi->y);
+ BlitBitmapOnBackground(gd->bitmap, drawto,
+ gd->x, gd->y, gi->width, gi->height,
+ gi->x, gi->y);
if (gi->deco.design.bitmap)
BlitBitmap(gi->deco.design.bitmap, drawto,
gi->deco.design.x, gi->deco.design.y,
border, gi->height, gi->x + gi->width - border, gi->y);
/* gadget text value */
- DrawText(gi->x + border, gi->y + border, text, FS_SMALL, font_type);
+ DrawTextExt(drawto,
+ gi->x + border, gi->y + border, text,
+ FS_SMALL, font_type, FONT_OPAQUE);
cursor_letter = gi->text.value[gi->text.cursor_position];
cursor_string[0] = '~';
/* draw cursor, if active */
if (pressed)
- DrawText(gi->x + border + gi->text.cursor_position * font_width,
- gi->y + border, cursor_string, FS_SMALL, font_type);
+ DrawTextExt(drawto,
+ gi->x + border + gi->text.cursor_position * font_width,
+ gi->y + border, cursor_string,
+ FS_SMALL, font_type, FONT_OPAQUE);
}
break;
int step_size_remain = size_body - num_steps * design_body;
/* clear scrollbar area */
- ClearRectangle(backbuffer, gi->x, gi->y, gi->width, gi->height);
+ ClearRectangleOnBackground(backbuffer, gi->x, gi->y,
+ gi->width, gi->height);
/* upper part of gadget */
- BlitBitmap(gd->bitmap, drawto,
- gd->x, gd->y,
- gi->width, gi->border.size,
- xpos, ypos);
+ BlitBitmapOnBackground(gd->bitmap, drawto,
+ gd->x, gd->y,
+ gi->width, gi->border.size,
+ xpos, ypos);
/* middle part of gadget */
for (i=0; i<num_steps; i++)
- BlitBitmap(gd->bitmap, drawto,
- gd->x, gd->y + gi->border.size,
- gi->width, design_body,
- xpos, ypos + gi->border.size + i * design_body);
+ BlitBitmapOnBackground(gd->bitmap, drawto,
+ gd->x, gd->y + gi->border.size,
+ gi->width, design_body,
+ xpos, ypos + gi->border.size
+ + i * design_body);
/* remaining middle part of gadget */
if (step_size_remain > 0)
- BlitBitmap(gd->bitmap, drawto,
- gd->x, gd->y + gi->border.size,
- gi->width, step_size_remain,
- xpos, ypos + gi->border.size + num_steps * design_body);
+ BlitBitmapOnBackground(gd->bitmap, drawto,
+ gd->x, gd->y + gi->border.size,
+ gi->width, step_size_remain,
+ xpos, ypos + gi->border.size
+ + num_steps * design_body);
/* lower part of gadget */
- BlitBitmap(gd->bitmap, drawto,
- gd->x, gd->y + design_full - gi->border.size,
- gi->width, gi->border.size,
- xpos, ypos + size_full - gi->border.size);
+ BlitBitmapOnBackground(gd->bitmap, drawto,
+ gd->x, gd->y + design_full - gi->border.size,
+ gi->width, gi->border.size,
+ xpos, ypos + size_full - gi->border.size);
}
break;
struct VideoSystemInfo video;
struct AudioSystemInfo audio;
struct GfxInfo gfx;
+struct FontInfo font;
struct ArtworkInfo artwork;
struct JoystickInfo joystick;
struct SetupInfo setup;
gfx.draw_deactivation_mask = draw_deactivation_mask;
}
+void SetBackgroundBitmap(Bitmap *background_bitmap)
+{
+ gfx.background_bitmap = background_bitmap;
+}
+
/* ========================================================================= */
/* video functions */
return FALSE;
}
+inline boolean DrawingOnBackground(int x, int y)
+{
+ return (gfx.background_bitmap != NULL && x < gfx.sx + gfx.sxsize);
+}
+
inline void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
int src_x, int src_y,
int width, int height,
#endif
}
+inline void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
+ int width, int height)
+{
+ if (!DrawingOnBackground(x, y))
+ ClearRectangle(bitmap, x, y, width, height);
+ else
+ BlitBitmap(gfx.background_bitmap, bitmap,
+ x - gfx.real_sx, y - gfx.real_sy, width, height, x, y);
+}
+
#if 0
#ifndef TARGET_SDL
static GC last_clip_gc = 0; /* needed for XCopyArea() through clip mask */
#endif
}
+inline void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
+ int src_x, int src_y,
+ int width, int height,
+ int dst_x, int dst_y)
+{
+ if (!DrawingOnBackground(src_x, src_y))
+ BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
+ dst_x, dst_y);
+ else
+ {
+ /* draw background */
+ BlitBitmap(gfx.background_bitmap, dst_bitmap,
+ dst_x - gfx.real_sx, dst_y - gfx.real_sy, width, height,
+ dst_x, dst_y);
+
+ /* draw foreground */
+ SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
+ dst_x - src_x, dst_y - src_y);
+ BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
+ dst_x, dst_y);
+ }
+}
+
inline void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
int to_x, int to_y)
{
int vxsize, vysize;
boolean draw_deactivation_mask;
+
+ Bitmap *background_bitmap;
+};
+
+struct FontInfo
+{
+ Bitmap *bitmap_initial;
+ Bitmap *bitmap_big;
+ Bitmap *bitmap_medium;
+ Bitmap *bitmap_small;
+ Bitmap *bitmap_tile;
};
struct JoystickInfo
extern struct VideoSystemInfo video;
extern struct AudioSystemInfo audio;
extern struct GfxInfo gfx;
+extern struct FontInfo font;
extern struct ArtworkInfo artwork;
extern struct JoystickInfo joystick;
extern struct SetupInfo setup;
void InitGfxDoor2Info(int, int, int, int);
void InitGfxScrollbufferInfo(int, int);
void SetDrawDeactivationMask(int );
+void SetBackgroundBitmap(Bitmap *);
inline void InitVideoDisplay(void);
inline void CloseVideoDisplay(void);
inline void FreeBitmap(Bitmap *);
inline void BlitBitmap(Bitmap *, Bitmap *, int, int, int, int, int, int);
inline void ClearRectangle(Bitmap *, int, int, int, int);
+inline void ClearRectangleOnBackground(Bitmap *, int, int, int, int);
inline void SetClipMask(Bitmap *, GC, Pixmap);
inline void SetClipOrigin(Bitmap *, GC, int, int);
inline void BlitBitmapMasked(Bitmap *, Bitmap *, int, int, int, int, int, int);
+inline boolean DrawingOnBackground(int, int);
+inline void BlitBitmapOnBackground(Bitmap *, Bitmap *, int, int, int, int, int,
+ int);
inline void DrawSimpleWhiteLine(Bitmap *, int, int, int, int);
inline void DrawLines(Bitmap *, struct XY *, int, Pixel);
inline Pixel GetPixel(Bitmap *, int, int);
/* ========================================================================= */
-/* 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)
+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()
+{
+#if defined(TARGET_X11_NATIVE)
+ 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 */
+}
void InitFontInfo(Bitmap *bitmap_initial,
Bitmap *bitmap_big, Bitmap *bitmap_medium,
font.bitmap_medium = bitmap_medium;
font.bitmap_small = bitmap_small;
font.bitmap_tile = bitmap_tile;
+
+ InitFontClipmasks();
}
int getFontWidth(int font_size, int font_type)
{
ClearRectangle(window, 0, ypos, video.width, FONT2_YSIZE);
DrawTextExt(window, (video.width - strlen(text) * FONT2_XSIZE)/2,
- ypos, text, FS_INITIAL, 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;
}
void DrawTextExt(DrawBuffer *bitmap, int x, int y, char *text,
- int font_size, int font_type)
+ int font_size, int font_type, int mask_mode)
{
Bitmap *font_bitmap;
int font_width, font_height, font_starty;
}
}
- if (print_inverse)
+ if (print_inverse) /* special mode for text gadgets */
{
- BlitBitmap(font_bitmap, bitmap,
- FONT_CHARS_PER_LINE * font_width,
+ /* 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
+ else if (mask_mode == FONT_MASKED)
{
-#if 1
- BlitBitmap(font_bitmap, bitmap, src_x, src_y,
+ /* 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);
-#else
- SetClipOrigin(font_bitmap, font_bitmap->stored_clip_gc,
- dest_x - src_x, dest_y - src_y);
+
+ /* 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);
+ }
+
BlitBitmapMasked(font_bitmap, bitmap, src_x, src_y,
font_width, font_height, dest_x, dest_y);
-#endif
+ }
+ else /* normal, non-masked font blitting */
+ {
+ BlitBitmap(font_bitmap, bitmap, src_x, src_y,
+ font_width, font_height, dest_x, dest_y);
}
}
#define FONT_CHARS_PER_LINE 16
#define FONT_LINES_PER_FONT 4
+#define FONT_OPAQUE 0
+#define FONT_MASKED 1
+
/* text output definitions */
#define MAX_OUTPUT_LINESIZE 256
/* font structure definitions */
-struct FontInfo
-{
- Bitmap *bitmap_initial;
- Bitmap *bitmap_big;
- Bitmap *bitmap_medium;
- Bitmap *bitmap_small;
- Bitmap *bitmap_tile;
-};
-
void InitFontInfo(Bitmap *, Bitmap *, Bitmap *, Bitmap *, Bitmap *);
int getFontWidth(int, int);
void DrawTextF(int, int, int, char *, ...);
void DrawTextFCentered(int, int, char *, ...);
void DrawText(int, int, char *, int, int);
-void DrawTextExt(DrawBuffer *, int, int, char *, int, int);
+void DrawTextExt(DrawBuffer *, int, int, char *, int, int, int);
#endif /* TEXT_H */
int anim_delay; /* important: delay of 1 means "no delay"! */
int anim_mode;
boolean anim_global_sync;
+
+#if defined(TARGET_X11_NATIVE)
+ Pixmap clip_mask; /* single-graphic-only clip mask for X11 */
+ GC clip_gc; /* single-graphic-only clip gc for X11 */
+#endif
};
extern GC tile_clip_gc;
static struct GadgetInfo *screen_gadget[NUM_SCREEN_GADGETS];
static int setup_mode = SETUP_MODE_MAIN;
-static void drawCursorExt(int pos, int color, int graphic)
+static void drawCursorExt(int xpos, int ypos, int color, int graphic)
{
static int cursor_array[SCR_FIELDY];
- if (graphic)
- cursor_array[pos] = graphic;
-
- graphic = cursor_array[pos];
+ if (xpos == 0)
+ {
+ if (graphic != 0)
+ cursor_array[ypos] = graphic;
+ else
+ graphic = cursor_array[ypos];
+ }
if (color == FC_RED)
graphic = (graphic == IMG_ARROW_BLUE_LEFT ? IMG_ARROW_RED_LEFT :
graphic == IMG_ARROW_BLUE_RIGHT ? IMG_ARROW_RED_RIGHT :
IMG_BALL_RED);
- DrawGraphic(0, MENU_SCREEN_START_YPOS + pos, graphic, 0);
+ ypos += MENU_SCREEN_START_YPOS;
+
+ DrawBackground(SX + xpos * 32, SY + ypos * 32, TILEX, TILEY);
+ DrawGraphicThruMask(xpos, ypos, graphic, 0);
+}
+
+static void initCursor(int ypos, int graphic)
+{
+ drawCursorExt(0, ypos, FC_BLUE, graphic);
}
-static void initCursor(int pos, int graphic)
+static void drawCursor(int ypos, int color)
{
- drawCursorExt(pos, FC_BLUE, graphic);
+ drawCursorExt(0, ypos, color, 0);
}
-static void drawCursor(int pos, int color)
+static void drawCursorXY(int xpos, int ypos, int graphic)
{
- drawCursorExt(pos, color, 0);
+ drawCursorExt(xpos, ypos, -1, graphic);
}
void DrawHeadline()
KeyboardAutoRepeatOn();
ActivateJoystick();
SetDrawDeactivationMask(REDRAW_NONE);
+ SetBackgroundBitmap(new_graphic_info[IMG_MENU_BACKGROUND].bitmap);
audio.sound_deactivated = FALSE;
/* needed if last screen was the playing screen, invoked from level editor */
GetPlayerConfig();
LoadLevel(level_nr);
+ SetBackgroundBitmap(new_graphic_info[IMG_MENU_BACKGROUND].bitmap);
ClearWindow();
+
DrawHeadline();
DrawText(SX + 32, SY + 2*32, name_text, FS_BIG, FC_GREEN);
DrawText(SX + 6*32, SY + 2*32, setup.player_name, FS_BIG, FC_RED);
for(i=0; i<8; i++)
initCursor(i, (i == 1 || i == 6 ? IMG_ARROW_BLUE_RIGHT : IMG_BALL_BLUE));
+#if 0
DrawGraphic(10, 3, IMG_ARROW_BLUE_LEFT, 0);
DrawGraphic(14, 3, IMG_ARROW_BLUE_RIGHT, 0);
+#else
+ drawCursorXY(10, 1, IMG_ARROW_BLUE_LEFT);
+ drawCursorXY(14, 1, IMG_ARROW_BLUE_RIGHT);
+#endif
DrawText(SX + 56, SY + 326, "A Game by Artsoft Entertainment",
FS_SMALL, FC_RED);
level_nr = new_level_nr;
- DrawTextExt(drawto, SX + 11 * 32, SY + 3 * 32,
- int2str(level_nr, 3), FS_BIG, font_color);
- DrawTextExt(window, SX + 11 * 32, SY + 3 * 32,
- int2str(level_nr, 3), FS_BIG, font_color);
+ DrawText(SX + 11 * 32, SY + 3 * 32, int2str(level_nr, 3),
+ FS_BIG, font_color);
LoadLevel(level_nr);
DrawMicroLevel(MICROLEV_XPOS, MICROLEV_YPOS, TRUE);
if (newxpos)
{
xpos = newxpos;
- DrawText(SX + 6*32, SY + ypos*32, setup.player_name, FS_BIG, FC_YELLOW);
- DrawGraphic(xpos + 6, ypos, IMG_BALL_RED, 0);
+ DrawText(SX + 6 * 32, SY + ypos * 32, setup.player_name,
+ FS_BIG, FC_YELLOW);
+ drawCursorXY(xpos + 6, ypos - 2, IMG_BALL_RED);
+
return;
}
setup.player_name[xpos] = ascii;
setup.player_name[xpos + 1] = 0;
xpos++;
- DrawTextExt(drawto, SX + 6*32, SY + ypos*32,
- setup.player_name, FS_BIG, FC_YELLOW);
- DrawTextExt(window, SX + 6*32, SY + ypos*32,
- setup.player_name, FS_BIG, FC_YELLOW);
- DrawGraphic(xpos + 6, ypos, IMG_BALL_RED, 0);
+
+ DrawText(SX + 6 * 32, SY + ypos * 32, setup.player_name,
+ FS_BIG, FC_YELLOW);
+ drawCursorXY(xpos + 6, ypos - 2, IMG_BALL_RED);
}
else if ((key == KSYM_Delete || key == KSYM_BackSpace) && xpos > 0)
{
xpos--;
setup.player_name[xpos] = 0;
- DrawGraphic(xpos + 6, ypos, IMG_BALL_RED, 0);
- DrawGraphic(xpos + 7, ypos, IMG_EMPTY, 0);
+
+ DrawBackground(SX + (xpos + 6) * 32, SY + ypos * 32, 2 * TILEX, TILEY);
+ drawCursorXY(xpos + 6, ypos - 2, IMG_BALL_RED);
}
else if (key == KSYM_Return && xpos > 0)
{
- DrawText(SX + 6*32, SY + ypos*32, setup.player_name, FS_BIG, FC_RED);
- DrawGraphic(xpos + 6, ypos, IMG_EMPTY, 0);
+ DrawText(SX + 6 * 32, SY + ypos * 32, setup.player_name, FS_BIG, FC_RED);
+ DrawBackground(SX + (xpos + 6) * 32, SY + ypos * 32, TILEX, TILEY);
SaveSetup();
game_status = MAINMENU;
char *title_string = NULL;
int offset = (ti->type == TREE_TYPE_LEVEL_DIR ? 0 : 16);
- ClearRectangle(backbuffer, SX, SY, SXSIZE - 32, SYSIZE);
+ DrawBackground(SX, SY, SXSIZE - 32, SYSIZE);
redraw_mask |= REDRAW_FIELD;
title_string =
}
if (first_entry > 0)
- DrawGraphic(0, 1, IMG_ARROW_BLUE_UP, 0);
+ {
+ int ypos = 1;
+
+ DrawBackground(SX, SY + ypos * 32, TILEX, TILEY);
+ DrawGraphicThruMask(0, ypos, IMG_ARROW_BLUE_UP, 0);
+ }
if (first_entry + num_page_entries < num_entries)
- DrawGraphic(0, MAX_MENU_ENTRIES_ON_SCREEN + 1, IMG_ARROW_BLUE_DOWN, 0);
+ {
+ int ypos = MAX_MENU_ENTRIES_ON_SCREEN + 1;
+
+ DrawBackground(SX, SY + ypos * 32, TILEX, TILEY);
+ DrawGraphicThruMask(0, ypos, IMG_ARROW_BLUE_DOWN, 0);
+ }
}
static void drawChooseTreeInfo(int entry_pos, TreeInfo *ti)
node_first = getTreeInfoFirstGroupEntry(ti);
node = getTreeInfoFromPos(node_first, entry_pos);
- ClearRectangle(drawto, SX + 32, SY + 32, SXSIZE - 64, 32);
+ DrawBackground(SX + 32, SY + 32, SXSIZE - 64, 32);
if (node->parent_link)
DrawTextFCentered(40, FC_RED, "leave group \"%s\"", node->class_desc);
initCursor(2, IMG_ARROW_BLUE_RIGHT);
initCursor(13, IMG_ARROW_BLUE_LEFT);
- DrawGraphic(10, MENU_SCREEN_START_YPOS, IMG_ARROW_BLUE_LEFT, 0);
- DrawGraphic(12, MENU_SCREEN_START_YPOS, IMG_ARROW_BLUE_RIGHT, 0);
+ drawCursorXY(10, 0, IMG_ARROW_BLUE_LEFT);
+ drawCursorXY(12, 0, IMG_ARROW_BLUE_RIGHT);
DrawText(SX+32, SY+2*32, "Player:", FS_BIG, FC_GREEN);
DrawText(SX+32, SY+3*32, "Device:", FS_BIG, FC_GREEN);
custom_key = setup.input[player_nr].key;
DrawText(SX+11*32, SY+2*32, int2str(player_nr + 1, 1), FS_BIG, FC_RED);
- DrawGraphic(8, 2, PLAYER_NR_GFX(IMG_PLAYER1, player_nr), 0);
+ DrawGraphicThruMask(8, 2, PLAYER_NR_GFX(IMG_PLAYER1, player_nr), 0);
if (setup.input[player_nr].use_joystick)
{
}
DrawText(SX+32, SY+5*32, "Actual Settings:", FS_BIG, FC_GREEN);
- DrawGraphic(1, 6, IMG_ARROW_BLUE_LEFT, 0);
- DrawGraphic(1, 7, IMG_ARROW_BLUE_RIGHT, 0);
- DrawGraphic(1, 8, IMG_ARROW_BLUE_UP, 0);
- DrawGraphic(1, 9, IMG_ARROW_BLUE_DOWN, 0);
+ drawCursorXY(1, 4, IMG_ARROW_BLUE_LEFT);
+ drawCursorXY(1, 5, IMG_ARROW_BLUE_RIGHT);
+ drawCursorXY(1, 6, IMG_ARROW_BLUE_UP);
+ drawCursorXY(1, 7, IMG_ARROW_BLUE_DOWN);
DrawText(SX+2*32, SY+6*32, ":", FS_BIG, FC_BLUE);
DrawText(SX+2*32, SY+7*32, ":", FS_BIG, FC_BLUE);
DrawText(SX+2*32, SY+8*32, ":", FS_BIG, FC_BLUE);
info1[0] = '\0';
sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
- DrawTextExt(window, SX, SY, text, FS_SMALL, FC_YELLOW);
+ DrawTextExt(window, SX, SY, text, FS_SMALL, FC_YELLOW, FONT_OPAQUE);
}
FlushDisplay();
BackToFront();
}
+void DrawBackground(int x, int y, int width, int height)
+{
+ /* some sanity checks */
+ if (x < REAL_SX)
+ {
+ width -= (REAL_SX - x);
+ x = REAL_SX;
+ }
+
+ if (y < REAL_SY)
+ {
+ height -= (REAL_SY - y);
+ y = REAL_SY;
+ }
+
+ if (width > FULL_SXSIZE)
+ width = FULL_SXSIZE;
+
+ if (height > FULL_SYSIZE)
+ height = FULL_SYSIZE;
+
+ if (DrawingOnBackground(x, y) && game_status != PLAYING)
+ BlitBitmap(gfx.background_bitmap, backbuffer, x - REAL_SX, y - REAL_SY,
+ width, height, x, y);
+ else
+ ClearRectangle(backbuffer, x, y, width, height);
+
+ redraw_mask |= REDRAW_FIELD;
+}
+
void ClearWindow()
{
- ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
+ DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
if (setup.soft_scrolling && game_status == PLAYING)
{
ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
SetDrawtoField(DRAW_DIRECT);
}
-
-#if 1
- if (game_status != PLAYING &&
- new_graphic_info[IMG_MENU_BACK].bitmap != NULL)
- BlitBitmap(new_graphic_info[IMG_MENU_BACK].bitmap, backbuffer,
- 0, 0, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
-#endif
-
- redraw_mask |= REDRAW_FIELD;
}
static int getGraphicAnimationPhase(int frames, int delay, int mode)
{
Bitmap *src_bitmap;
int src_x, src_y;
- int graphic;
-
- if (element == EL_EMPTY)
- return;
-
- graphic = el2img(element);
+ int graphic = el2img(element);
getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
{
int x, y;
- ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
+ DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
if (lev_fieldx < STD_LEV_FIELDX)
xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
Ur[lx][ly]);
- else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
+ else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
+ && BorderElement != EL_EMPTY)
DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
BorderElement);
}
{
char label_text[MAX_MICROLABEL_SIZE + 1];
- ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
+ DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
mode == MICROLABEL_CREATED_BY ? "created by" :
text_line[tl] = 0;
DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
- text_line, FS_SMALL, FC_YELLOW);
+ text_line, FS_SMALL, FC_YELLOW, FONT_OPAQUE);
text += tl + (tc == ' ' ? 1 : 0);
}
void BackToFront();
void FadeToFront();
void ClearWindow();
+void DrawBackground(int, int, int, int);
void MarkTileDirty(int, int);
void SetBorderElement();