[Freeciv-Dev] (PR#7612) crop_sprite with a mask
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://rt.freeciv.org/Ticket/Display.html?id=7612 >
This patch does two things:
- Crop_sprite takes an additional set of parameters. This allows the
sprite to be cropped with an extra mask. In effect the new mask becomes
the intersection of the old and new mask.
- Blended (aka dithered) tiles are drawn differently. Currently we take
the terrain we're going to blend with, and draw its sprite using a
clipping mask. So we use 2 masks in the draw stage. Some GUIs (win32,
sdl) have problems with this. With the new method, when the tileset is
loaded the blending sprites are cropped out into separate sprites: four
for each terrain. Then later instead of having special dither code in
the GUI we need only add these sprites to the list of drawn_sprites.
The main reason for adding the new functionality to crop_sprite is to
use this algorithm to break apart cell sprites (like those used in
civ3-style drawing). However changing the blended-tile drawing does
have advantages. It cuts out a couple hundred lines of code, and makes
the GUI code simpler. It may be faster for some GUIs. It will make
things easier for gui-sdl (I think), and more correct for gui-win32.
However we do need some hacks to work around the special cases:
- The blending is done between the first (flat) and second (3d) layer of
drawing. However the matched sprites may be either 1st or 2nd layer
code. Thus we have two separate cases for where the blending must be
done. (This problem will go away when layering is done properly and
it's possible to have 1st and 2nd layer be matched separately).
- Ocean isn't blended with itself, obviously (no terrain type is blended
with itself). When blending with non-ocean, we don't use the
traditional ocean sprite - we use a separate coastal sprite. By
renaming this sprite t.ocean1 this works out. However if we had
different _types_ of ocean that we wanted to blend with each other then
we'd have problems!
- Unknown terrain is blended. However since it's not drawn anywhere
else (it's all special-cased) the drawing data for T_UNKNOWN is never
set up. The hack around this is to setup the T_UNKNOWN drawing data,
but this requires more special cases since none of the usual sprites are
available. In the future I think this should be "fixed" and unknown
terrain should be drawn like other terrain. (This wouldn't be very
hard; however, in non-iso view there is no t.unknown sprite.)
jason
Index: client/tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.146
diff -u -r1.146 tilespec.c
--- client/tilespec.c 27 Feb 2004 18:31:39 -0000 1.146
+++ client/tilespec.c 6 Mar 2004 02:20:01 -0000
@@ -360,6 +360,7 @@
for (id = T_FIRST; id < T_COUNT; id++) {
tilespec_setup_tile_type(id);
}
+ tilespec_setup_tile_type(T_UNKNOWN);
unit_type_iterate(id) {
tilespec_setup_unit_type(id);
} unit_type_iterate_end;
@@ -850,7 +851,6 @@
if (is_isometric) {
SET_SPRITE(black_tile, "t.black_tile");
SET_SPRITE(dither_tile, "t.dither_tile");
- SET_SPRITE(coast_color, "t.coast_color");
}
/* Load the citizen sprite graphics. */
@@ -1059,6 +1059,8 @@
SET_SPRITE(tx.river_outlet[i], buffer);
}
+ tilespec_setup_tile_type(T_UNKNOWN);
+
sprites.city.tile_wall = NULL; /* no place to initialize this variable */
sprites.city.tile = NULL; /* no place to initialize this variable */
}
@@ -1165,6 +1167,12 @@
struct terrain_drawing_data *draw;
char buffer1[MAX_LEN_NAME+20];
int i;
+
+ if (terrain == T_UNKNOWN) {
+ /* Special hack for unknown terrain. */
+ sz_strlcpy(tt->terrain_name, "Unknown");
+ sz_strlcpy(tt->graphic_str, "unknown");
+ }
if(tt->terrain_name[0] == '\0') {
return;
@@ -1180,6 +1188,11 @@
}
}
+ if (terrain == T_UNKNOWN && !draw->is_blended) {
+ /* Don't need to do anything. */
+ return;
+ }
+
/* Currently ocean terrains have special handling. Although a match type
* may be specified it is ignored. This is a hack. */
if (draw->match_type == 0 || draw->is_layered) {
@@ -1198,7 +1211,7 @@
for (i = 0; i < NUM_DIRECTION_NSEW; i++) {
my_snprintf(buffer1, sizeof(buffer1),
"t.%s_%s", draw->name, nsew_str(i));
- draw->blend[i] = lookup_sprite_tag_alt(buffer1, "", TRUE,
+ draw->match[i] = lookup_sprite_tag_alt(buffer1, "", TRUE,
"tile_type",
tt->terrain_name);
}
@@ -1215,11 +1228,30 @@
tt->terrain_name);
}
}
+ my_snprintf(buffer1, sizeof(buffer1), "t.%s1", draw->name);
+ draw->base = lookup_sprite_tag_alt(buffer1, "", FALSE, "tile_type",
+ tt->terrain_name);
break;
}
if (!draw->base) {
- draw->base = draw->blend[0];
+ draw->base = draw->match[0];
+ }
+ }
+
+ if (draw->is_blended && is_isometric) {
+ /* Set up blending sprites. This only works in iso-view! */
+ const int W = NORMAL_TILE_WIDTH, H = NORMAL_TILE_HEIGHT;
+ const int offsets[4][2] = {
+ {W / 2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}
+ };
+ enum direction4 dir;
+
+ for (dir = 0; dir < 4; dir++) {
+ draw->blend[dir] = crop_sprite(draw->base,
+ offsets[dir][0], offsets[dir][1],
+ W / 2, H / 2,
+ sprites.dither_tile, 0, 0);
}
}
@@ -1576,25 +1608,6 @@
return sprs - save_sprs;
}
-/**********************************************************************
-Only used for isometric view.
-***********************************************************************/
-static struct Sprite *get_dither(int ttype, int ttype_other)
-{
- if (ttype_other == T_UNKNOWN)
- return sprites.black_tile;
-
- if (!sprites.terrain[ttype]->is_blended) {
- return NULL;
- }
-
- if (is_ocean(ttype_other)) {
- return sprites.coast_color;
- }
-
- return sprites.terrain[ttype_other]->base;
-}
-
/**************************************************************************
Add any corner road sprites to the sprite array.
**************************************************************************/
@@ -1882,21 +1895,64 @@
return sprs - saved_sprs;
}
+static int fill_blending_sprite_array(struct drawn_sprite *sprs,
+ int map_x, int map_y,
+ enum tile_terrain_type *ttype_near)
+{
+ struct drawn_sprite *saved_sprs = sprs;
+
+ if (is_isometric) {
+ enum tile_terrain_type ttype = map_get_terrain(map_x, map_y);
+ enum direction4 dir;
+ const int W = NORMAL_TILE_WIDTH, H = NORMAL_TILE_HEIGHT;
+ const int offsets[4][2] = {
+ {W/2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}
+ };
+
+ /*
+ * We want to mark unknown tiles so that an unreal tile will be
+ * given the same marking as our current tile - that way we won't
+ * get the "unknown" dither along the edge of the map.
+ */
+ for (dir = 0; dir < 4; dir++) {
+ int x1, y1, other;
+
+ if (!MAPSTEP(x1, y1, map_x, map_y, DIR4_TO_DIR8[dir])) {
+ continue;
+ }
+
+ if (tile_get_known(x1, y1) == TILE_UNKNOWN) {
+ other = T_UNKNOWN;
+ } else {
+ other = ttype_near[DIR4_TO_DIR8[dir]];
+ }
+
+ if (other == ttype || !sprites.terrain[other]->is_blended) {
+ continue;
+ }
+
+ ADD_SPRITE(sprites.terrain[other]->blend[dir],
+ offsets[dir][0], offsets[dir][1]);
+ }
+ }
+
+ return sprs - saved_sprs;
+}
+
/****************************************************************************
Add sprites for the base terrain to the sprite list. This doesn't
include specials or rivers.
****************************************************************************/
static int fill_terrain_sprite_array(struct drawn_sprite *sprs,
- struct tile *ptile,
- enum tile_terrain_type *ttype_near,
- int *dither_count)
+ int map_x, int map_y,
+ enum tile_terrain_type *ttype_near)
{
struct drawn_sprite *saved_sprs = sprs;
struct Sprite *sprite;
+ struct tile *ptile = map_get_tile(map_x, map_y);
enum tile_terrain_type ttype = ptile->terrain;
if (!draw_terrain) {
- *dither_count = 0;
return 0;
}
@@ -1909,7 +1965,10 @@
if (sprites.terrain[ttype]->match_type == 0
|| sprites.terrain[ttype]->is_layered) {
ADD_SPRITE_SIMPLE(sprites.terrain[ttype]->base);
- *dither_count = 1;
+ }
+
+ if (sprites.terrain[ttype]->is_layered) {
+ sprs += fill_blending_sprite_array(sprs, map_x, map_y, ttype_near);
}
if (sprites.terrain[ttype]->match_type != 0) {
@@ -1923,10 +1982,7 @@
tileno = INDEX_NSEW(MATCH(DIR8_NORTH), MATCH(DIR8_SOUTH),
MATCH(DIR8_EAST), MATCH(DIR8_WEST));
- ADD_SPRITE_SIMPLE(sprites.terrain[ttype]->blend[tileno]);
- if (!sprites.terrain[ttype]->is_layered) {
- *dither_count = 1;
- }
+ ADD_SPRITE_SIMPLE(sprites.terrain[ttype]->match[tileno]);
} else if (sprites.terrain[ttype]->cell_type == CELL_RECT) {
/* Divide the tile up into four rectangular cells. Now each of these
* cells covers one corner, and each is adjacent to 3 different
@@ -1958,18 +2014,6 @@
ADD_SPRITE(sprites.terrain[ttype]->cells[array_index][i], x, y);
}
-
- /* Short-cut past dithering if all adjacent tiles are the same. */
- if (!sprites.terrain[ttype]->is_layered) {
- if (ttype_near[DIR8_NORTH] == ttype
- && ttype_near[DIR8_SOUTH] == ttype
- && ttype_near[DIR8_EAST] == ttype
- && ttype_near[DIR8_WEST] == ttype) {
- *dither_count = 0;
- } else {
- *dither_count = 4;
- }
- }
}
#undef MATCH
}
@@ -1993,6 +2037,10 @@
}
}
+ if (!sprites.terrain[ttype]->is_layered) {
+ sprs += fill_blending_sprite_array(sprs, map_x, map_y, ttype_near);
+ }
+
return sprs - saved_sprs;
}
@@ -2012,7 +2060,6 @@
5) huts
***********************************************************************/
int fill_tile_sprite_array_iso(struct drawn_sprite *sprs,
- struct Sprite **dither, int *dither_count,
int x, int y, bool citymode, bool *solid_bg)
{
enum tile_terrain_type ttype, ttype_near[8];
@@ -2023,14 +2070,13 @@
struct drawn_sprite *save_sprs = sprs;
*solid_bg = FALSE;
- *dither_count = 0;
if (tile_get_known(x, y) == TILE_UNKNOWN)
return -1;
build_tile_data(x, y, &ttype, &tspecial, ttype_near, tspecial_near);
- sprs += fill_terrain_sprite_array(sprs, ptile, ttype_near, dither_count);
+ sprs += fill_terrain_sprite_array(sprs, x, y, ttype_near);
if (is_ocean(ttype) && draw_terrain) {
for (dir = 0; dir < 4; dir++) {
@@ -2095,23 +2141,6 @@
}
#endif
}
-
- if (dither) {
- /*
- * We want to mark unknown tiles so that an unreal tile will be
- * given the same marking as our current tile - that way we won't
- * get the "unknown" dither along the edge of the map.
- */
- for (dir = 0; dir < 4; dir++) {
- int x1, y1, other;
-
- if (MAPSTEP(x1, y1, x, y, DIR4_TO_DIR8[dir]))
- other = (tile_get_known(x1, y1) != TILE_UNKNOWN) ?
ttype_near[DIR4_TO_DIR8[dir]]:T_UNKNOWN;
- else
- other = ttype_near[dir];
- dither[dir] = get_dither(ttype, other);
- }
- }
return sprs - save_sprs;
}
@@ -2139,7 +2168,7 @@
{
enum tile_terrain_type ttype, ttype_near[8];
enum tile_special_type tspecial, tspecial_near[8];
- int dir, tileno, dither_count;
+ int dir, tileno;
struct tile *ptile;
struct city *pcity;
struct unit *pfocus;
@@ -2180,7 +2209,7 @@
build_tile_data(abs_x0, abs_y0,
&ttype, &tspecial, ttype_near, tspecial_near);
- sprs += fill_terrain_sprite_array(sprs, ptile, ttype_near, &dither_count);
+ sprs += fill_terrain_sprite_array(sprs, abs_x0, abs_y0, ttype_near);
if (!draw_terrain) {
*solid_bg = TRUE;
@@ -2604,7 +2633,8 @@
assert(ss->ref_count == 0);
ensure_big_sprite(ss->sf);
ss->sprite =
- crop_sprite(ss->sf->big_sprite, ss->x, ss->y, ss->width, ss->height);
+ crop_sprite(ss->sf->big_sprite, ss->x, ss->y, ss->width, ss->height,
+ NULL, -1, -1);
}
/* Track the reference count so we know when to free the sprite. */
Index: client/tilespec.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.h,v
retrieving revision 1.55
diff -u -r1.55 tilespec.h
--- client/tilespec.h 27 Feb 2004 18:31:39 -0000 1.55
+++ client/tilespec.h 6 Mar 2004 02:20:01 -0000
@@ -53,7 +53,6 @@
/* Gfx support */
int fill_tile_sprite_array_iso(struct drawn_sprite *sprs,
- struct Sprite **dither, int *dither_count,
int x, int y, bool citymode, bool *solid_bg);
int fill_tile_sprite_array(struct drawn_sprite *sprs, int abs_x0, int abs_y0,
bool citymode, bool *solid_bg,
@@ -109,8 +108,9 @@
enum cell_type cell_type;
struct Sprite *base;
- struct Sprite *blend[NUM_DIRECTION_NSEW];
+ struct Sprite *match[NUM_DIRECTION_NSEW];
struct Sprite *cells[8][4]; /* 4 = up down left right */
+ struct Sprite *blend[4]; /* indexed by a direction4 */
struct Sprite *special[2];
struct Sprite *mine;
};
@@ -124,8 +124,7 @@
*right_arrow,
*black_tile, /* only used for isometric view */
- *dither_tile, /* only used for isometric view */
- *coast_color; /* only used for isometric view */
+ *dither_tile; /* only used for isometric view */
struct {
/* Each citizen type has up to MAX_NUM_CITIZEN_SPRITES different
Index: client/gui-gtk/graphics.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/graphics.c,v
retrieving revision 1.52
diff -u -r1.52 graphics.c
--- client/gui-gtk/graphics.c 24 Feb 2004 05:20:25 -0000 1.52
+++ client/gui-gtk/graphics.c 6 Mar 2004 02:20:01 -0000
@@ -167,9 +167,11 @@
***************************************************************************/
struct Sprite *crop_sprite(struct Sprite *source,
int x, int y,
- int width, int height)
+ int width, int height,
+ struct Sprite *mask,
+ int mask_offset_x, int mask_offset_y)
{
- GdkPixmap *mypixmap, *mask = NULL;
+ GdkPixmap *mypixmap, *mymask = NULL;
mypixmap = gdk_pixmap_new(root_window, width, height, -1);
@@ -177,14 +179,30 @@
width, height);
if (source->has_mask) {
- mask = gdk_pixmap_new(mask_bitmap, width, height, 1);
- gdk_draw_rectangle(mask, mask_bg_gc, TRUE, 0, 0, -1, -1 );
+ mymask = gdk_pixmap_new(mask_bitmap, width, height, 1);
+ gdk_draw_rectangle(mymask, mask_bg_gc, TRUE, 0, 0, -1, -1 );
- gdk_draw_pixmap(mask, mask_fg_gc, source->mask,
+ gdk_draw_pixmap(mymask, mask_fg_gc, source->mask,
x, y, 0, 0, width, height);
}
- return ctor_sprite_mask(mypixmap, mask, width, height);
+ if (mask) {
+ if (mymask) {
+ gdk_gc_set_function(mask_fg_gc, GDK_AND);
+ gdk_draw_pixmap(mymask, mask_fg_gc, mask->mask,
+ x - mask_offset_x, y - mask_offset_y,
+ 0, 0, width, height);
+ gdk_gc_set_function(mask_fg_gc, GDK_OR);
+ } else {
+ mymask = gdk_pixmap_new(NULL, width, height, 1);
+ gdk_draw_rectangle(mymask, mask_bg_gc, TRUE, 0, 0, -1, -1);
+
+ gdk_draw_pixmap(mymask, mask_fg_gc, source->mask,
+ x, y, 0, 0, width, height);
+ }
+ }
+
+ return ctor_sprite_mask(mypixmap, mymask, width, height);
}
/****************************************************************************
@@ -629,5 +647,5 @@
sprite_get_bounding_box(s, &x1, &y1, &x2, &y2);
- return crop_sprite(s, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
+ return crop_sprite(s, x1, y1, x2 - x1 + 1, y2 - y1 + 1, NULL, -1, -1);
}
Index: client/gui-gtk/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/mapview.c,v
retrieving revision 1.201
diff -u -r1.201 mapview.c
--- client/gui-gtk/mapview.c 5 Mar 2004 18:16:01 -0000 1.201
+++ client/gui-gtk/mapview.c 6 Mar 2004 02:20:02 -0000
@@ -1206,81 +1206,6 @@
}
/**************************************************************************
-Blend the tile with neighboring tiles.
-Only used for isometric view.
-**************************************************************************/
-static void dither_tile(GdkDrawable *pixmap, struct Sprite **dither,
- int canvas_x, int canvas_y,
- int offset_x, int offset_y,
- int width, int height, bool fog)
-{
- if (!width || !height)
- return;
-
- gdk_gc_set_clip_mask(civ_gc, sprites.dither_tile->mask);
- gdk_gc_set_clip_origin(civ_gc, canvas_x, canvas_y);
- assert(offset_x == 0 || offset_x == NORMAL_TILE_WIDTH/2);
- assert(offset_y == 0 || offset_y == NORMAL_TILE_HEIGHT/2);
- assert(width == NORMAL_TILE_WIDTH || width == NORMAL_TILE_WIDTH/2);
- assert(height == NORMAL_TILE_HEIGHT || height == NORMAL_TILE_HEIGHT/2);
-
- /* north */
- if (dither[0]
- && (offset_x != 0 || width == NORMAL_TILE_WIDTH)
- && (offset_y == 0)) {
- gdk_draw_pixmap(pixmap, civ_gc, dither[0]->pixmap,
- NORMAL_TILE_WIDTH/2, 0,
- canvas_x + NORMAL_TILE_WIDTH/2, canvas_y,
- NORMAL_TILE_WIDTH/2, NORMAL_TILE_HEIGHT/2);
- }
-
- /* south */
- if (dither[1] && offset_x == 0
- && (offset_y == NORMAL_TILE_HEIGHT/2 || height == NORMAL_TILE_HEIGHT)) {
- gdk_draw_pixmap(pixmap, civ_gc, dither[1]->pixmap,
- 0, NORMAL_TILE_HEIGHT/2,
- canvas_x,
- canvas_y + NORMAL_TILE_HEIGHT/2,
- NORMAL_TILE_WIDTH/2, NORMAL_TILE_HEIGHT/2);
- }
-
- /* east */
- if (dither[2]
- && (offset_x != 0 || width == NORMAL_TILE_WIDTH)
- && (offset_y != 0 || height == NORMAL_TILE_HEIGHT)) {
- gdk_draw_pixmap(pixmap, civ_gc, dither[2]->pixmap,
- NORMAL_TILE_WIDTH/2, NORMAL_TILE_HEIGHT/2,
- canvas_x + NORMAL_TILE_WIDTH/2,
- canvas_y + NORMAL_TILE_HEIGHT/2,
- NORMAL_TILE_WIDTH/2, NORMAL_TILE_HEIGHT/2);
- }
-
- /* west */
- if (dither[3] && offset_x == 0 && offset_y == 0) {
- gdk_draw_pixmap(pixmap, civ_gc, dither[3]->pixmap,
- 0, 0,
- canvas_x,
- canvas_y,
- NORMAL_TILE_WIDTH/2, NORMAL_TILE_HEIGHT/2);
- }
-
- gdk_gc_set_clip_mask(civ_gc, NULL);
-
- if (fog) {
- gdk_gc_set_clip_origin(fill_tile_gc, canvas_x, canvas_y);
- gdk_gc_set_clip_mask(fill_tile_gc, sprites.dither_tile->mask);
- gdk_gc_set_foreground(fill_tile_gc, colors_standard[COLOR_STD_BLACK]);
- gdk_gc_set_stipple(fill_tile_gc, black50);
-
- gdk_draw_rectangle(pixmap, fill_tile_gc, TRUE,
- canvas_x+offset_x, canvas_y+offset_y,
- MIN(width, MAX(0, NORMAL_TILE_WIDTH-offset_x)),
- MIN(height, MAX(0, NORMAL_TILE_HEIGHT-offset_y)));
- gdk_gc_set_clip_mask(fill_tile_gc, NULL);
- }
-}
-
-/**************************************************************************
Only used for isometric view.
**************************************************************************/
static void pixmap_put_tile_iso(GdkDrawable *pm, int x, int y,
@@ -1291,18 +1216,17 @@
enum draw_type draw)
{
struct drawn_sprite tile_sprs[80];
- struct Sprite *dither[4];
struct city *pcity;
struct unit *punit, *pfocus;
enum tile_special_type special;
- int count, i = 0, dither_count;
+ int count, i;
bool solid_bg, fog, tile_hilited;
struct canvas_store canvas_store = {pm};
if (!width || !(height || height_unit))
return;
- count = fill_tile_sprite_array_iso(tile_sprs, dither, &dither_count,
+ count = fill_tile_sprite_array_iso(tile_sprs,
x, y, citymode, &solid_bg);
if (count == -1) { /* tile is unknown */
@@ -1346,19 +1270,8 @@
}
}
- /*** Draw and dither base terrain ***/
- if (dither_count > 0) {
- for (i = 0; i < dither_count; i++) {
- pixmap_put_drawn_sprite(pm, canvas_x, canvas_y, &tile_sprs[i],
- offset_x, offset_y, width, height, fog);
- }
-
- dither_tile(pm, dither, canvas_x, canvas_y,
- offset_x, offset_y, width, height, fog);
- }
-
- /*** Rest of terrain and specials ***/
- for (; i<count; i++) {
+ /*** Draw terrain and specials ***/
+ for (i = 0; i < count; i++) {
if (tile_sprs[i].sprite)
pixmap_put_drawn_sprite(pm, canvas_x, canvas_y, &tile_sprs[i],
offset_x, offset_y, width, height, fog);
Index: client/gui-gtk/plrdlg.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/plrdlg.c,v
retrieving revision 1.51
diff -u -r1.51 plrdlg.c
--- client/gui-gtk/plrdlg.c 31 Jan 2004 17:52:40 -0000 1.51
+++ client/gui-gtk/plrdlg.c 6 Mar 2004 02:20:02 -0000
@@ -382,7 +382,7 @@
assert(flag_w >= MIN_DIMENSION && flag_h >= MIN_DIMENSION);
/* croping */
- croped = crop_sprite(flag, start_x, start_y, flag_w, flag_h);
+ croped = crop_sprite(flag, start_x, start_y, flag_w, flag_h, NULL, -1, -1);
/* scaling */
newflag_h = GTK_CLIST(players_list)->row_height;
Index: client/gui-gtk-2.0/graphics.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/graphics.c,v
retrieving revision 1.23
diff -u -r1.23 graphics.c
--- client/gui-gtk-2.0/graphics.c 24 Feb 2004 05:20:25 -0000 1.23
+++ client/gui-gtk-2.0/graphics.c 6 Mar 2004 02:20:02 -0000
@@ -168,9 +168,11 @@
***************************************************************************/
struct Sprite *crop_sprite(struct Sprite *source,
int x, int y,
- int width, int height)
+ int width, int height,
+ struct Sprite *mask,
+ int mask_offset_x, int mask_offset_y)
{
- GdkPixmap *mypixmap, *mask = NULL;
+ GdkPixmap *mypixmap, *mymask = NULL;
mypixmap = gdk_pixmap_new(root_window, width, height, -1);
@@ -178,14 +180,30 @@
width, height);
if (source->has_mask) {
- mask = gdk_pixmap_new(NULL, width, height, 1);
- gdk_draw_rectangle(mask, mask_bg_gc, TRUE, 0, 0, -1, -1);
+ mymask = gdk_pixmap_new(NULL, width, height, 1);
+ gdk_draw_rectangle(mymask, mask_bg_gc, TRUE, 0, 0, -1, -1);
- gdk_draw_drawable(mask, mask_fg_gc, source->mask,
+ gdk_draw_drawable(mymask, mask_fg_gc, source->mask,
x, y, 0, 0, width, height);
}
- return ctor_sprite_mask(mypixmap, mask, width, height);
+ if (mask) {
+ if (mymask) {
+ gdk_gc_set_function(mask_fg_gc, GDK_AND);
+ gdk_draw_drawable(mymask, mask_fg_gc, mask->mask,
+ x - mask_offset_x, y - mask_offset_y,
+ 0, 0, width, height);
+ gdk_gc_set_function(mask_fg_gc, GDK_OR);
+ } else {
+ mymask = gdk_pixmap_new(NULL, width, height, 1);
+ gdk_draw_rectangle(mymask, mask_bg_gc, TRUE, 0, 0, -1, -1);
+
+ gdk_draw_drawable(mymask, mask_fg_gc, source->mask,
+ x, y, 0, 0, width, height);
+ }
+ }
+
+ return ctor_sprite_mask(mypixmap, mymask, width, height);
}
/****************************************************************************
@@ -516,7 +534,7 @@
sprite_get_bounding_box(s, &x1, &y1, &x2, &y2);
- return crop_sprite(s, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
+ return crop_sprite(s, x1, y1, x2 - x1 + 1, y2 - y1 + 1, NULL, -1, -1);
}
/*********************************************************************
Index: client/gui-gtk-2.0/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/mapview.c,v
retrieving revision 1.101
diff -u -r1.101 mapview.c
--- client/gui-gtk-2.0/mapview.c 5 Mar 2004 18:16:01 -0000 1.101
+++ client/gui-gtk-2.0/mapview.c 6 Mar 2004 02:20:03 -0000
@@ -1287,81 +1287,6 @@
}
/**************************************************************************
-Blend the tile with neighboring tiles.
-Only used for isometric view.
-**************************************************************************/
-static void dither_tile(GdkDrawable *pixmap, struct Sprite **dither,
- int canvas_x, int canvas_y,
- int offset_x, int offset_y,
- int width, int height, bool fog)
-{
- if (!width || !height)
- return;
-
- gdk_gc_set_clip_mask(civ_gc, sprites.dither_tile->mask);
- gdk_gc_set_clip_origin(civ_gc, canvas_x, canvas_y);
- assert(offset_x == 0 || offset_x == NORMAL_TILE_WIDTH/2);
- assert(offset_y == 0 || offset_y == NORMAL_TILE_HEIGHT/2);
- assert(width == NORMAL_TILE_WIDTH || width == NORMAL_TILE_WIDTH/2);
- assert(height == NORMAL_TILE_HEIGHT || height == NORMAL_TILE_HEIGHT/2);
-
- /* north */
- if (dither[0]
- && (offset_x != 0 || width == NORMAL_TILE_WIDTH)
- && (offset_y == 0)) {
- gdk_draw_drawable(pixmap, civ_gc, dither[0]->pixmap,
- NORMAL_TILE_WIDTH/2, 0,
- canvas_x + NORMAL_TILE_WIDTH/2, canvas_y,
- NORMAL_TILE_WIDTH/2, NORMAL_TILE_HEIGHT/2);
- }
-
- /* south */
- if (dither[1] && offset_x == 0
- && (offset_y == NORMAL_TILE_HEIGHT/2 || height == NORMAL_TILE_HEIGHT)) {
- gdk_draw_drawable(pixmap, civ_gc, dither[1]->pixmap,
- 0, NORMAL_TILE_HEIGHT/2,
- canvas_x,
- canvas_y + NORMAL_TILE_HEIGHT/2,
- NORMAL_TILE_WIDTH/2, NORMAL_TILE_HEIGHT/2);
- }
-
- /* east */
- if (dither[2]
- && (offset_x != 0 || width == NORMAL_TILE_WIDTH)
- && (offset_y != 0 || height == NORMAL_TILE_HEIGHT)) {
- gdk_draw_drawable(pixmap, civ_gc, dither[2]->pixmap,
- NORMAL_TILE_WIDTH/2, NORMAL_TILE_HEIGHT/2,
- canvas_x + NORMAL_TILE_WIDTH/2,
- canvas_y + NORMAL_TILE_HEIGHT/2,
- NORMAL_TILE_WIDTH/2, NORMAL_TILE_HEIGHT/2);
- }
-
- /* west */
- if (dither[3] && offset_x == 0 && offset_y == 0) {
- gdk_draw_drawable(pixmap, civ_gc, dither[3]->pixmap,
- 0, 0,
- canvas_x,
- canvas_y,
- NORMAL_TILE_WIDTH/2, NORMAL_TILE_HEIGHT/2);
- }
-
- gdk_gc_set_clip_mask(civ_gc, NULL);
-
- if (fog) {
- gdk_gc_set_clip_origin(fill_tile_gc, canvas_x, canvas_y);
- gdk_gc_set_clip_mask(fill_tile_gc, sprites.dither_tile->mask);
- gdk_gc_set_foreground(fill_tile_gc, colors_standard[COLOR_STD_BLACK]);
- gdk_gc_set_stipple(fill_tile_gc, black50);
-
- gdk_draw_rectangle(pixmap, fill_tile_gc, TRUE,
- canvas_x+offset_x, canvas_y+offset_y,
- MIN(width, MAX(0, NORMAL_TILE_WIDTH-offset_x)),
- MIN(height, MAX(0, NORMAL_TILE_HEIGHT-offset_y)));
- gdk_gc_set_clip_mask(fill_tile_gc, NULL);
- }
-}
-
-/**************************************************************************
Only used for isometric view.
**************************************************************************/
static void pixmap_put_tile_iso(GdkDrawable *pm, int x, int y,
@@ -1372,18 +1297,17 @@
enum draw_type draw)
{
struct drawn_sprite tile_sprs[80];
- struct Sprite *dither[4];
struct city *pcity;
struct unit *punit, *pfocus;
enum tile_special_type special;
- int count, i = 0, dither_count;
+ int count, i;
bool solid_bg, fog, tile_hilited;
struct canvas_store canvas_store = {pm};
if (!width || !(height || height_unit))
return;
- count = fill_tile_sprite_array_iso(tile_sprs, dither, &dither_count,
+ count = fill_tile_sprite_array_iso(tile_sprs,
x, y, citymode, &solid_bg);
if (count == -1) { /* tile is unknown */
@@ -1427,19 +1351,8 @@
}
}
- /*** Draw and dither base terrain ***/
- if (dither_count > 0) {
- for (i = 0; i < dither_count; i++) {
- pixmap_put_drawn_sprite(pm, canvas_x, canvas_y, &tile_sprs[i],
- offset_x, offset_y, width, height, fog);
- }
-
- dither_tile(pm, dither, canvas_x, canvas_y,
- offset_x, offset_y, width, height, fog);
- }
-
- /*** Rest of terrain and specials ***/
- for (; i<count; i++) {
+ /*** Draw terrain and specials ***/
+ for (i = 0; i < count; i++) {
if (tile_sprs[i].sprite)
pixmap_put_drawn_sprite(pm, canvas_x, canvas_y, &tile_sprs[i],
offset_x, offset_y, width, height, fog);
Index: client/gui-win32/graphics.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-win32/graphics.c,v
retrieving revision 1.16
diff -u -r1.16 graphics.c
--- client/gui-win32/graphics.c 24 Feb 2004 05:20:25 -0000 1.16
+++ client/gui-win32/graphics.c 6 Mar 2004 02:20:03 -0000
@@ -160,9 +160,10 @@
/**************************************************************************
**************************************************************************/
-struct Sprite *
-crop_sprite(struct Sprite *source,
- int x, int y, int width, int height)
+struct Sprite *crop_sprite(struct Sprite *source,
+ int x, int y, int width, int height,
+ struct Sprite *mask,
+ int mask_offset_x, int mask_offset_y)
{
SPRITE *mysprite;
HDC hdc;
@@ -235,8 +236,17 @@
ReleaseDC(root_window,hdc);
if (smallmask) DeleteObject(smallmask);
DeleteObject(smallbitmap);
-
-
+
+ if (mask && mask->has_mask) {
+ bigmask = BITMAP2HBITMAP(&mask->mask);
+ SelectObject(hdcbig, bigmask);
+ SelectObject(hdcsmall, smallmask);
+ BitBlt(hdcsmall, 0, 0, width, height, hdcbig,
+ x - mask_offset_x, y - mask_offset_y, SRCAND);
+ SelectObject(hdcbig, bigbitmap);
+ DeleteObject(bigmask);
+ }
+
return mysprite;
}
@@ -448,11 +458,11 @@
/**************************************************************************
**************************************************************************/
-void draw_sprite_part_with_mask(struct Sprite *sprite,
- struct Sprite *sprite_mask,
- HDC hdc,
- int x, int y,int w, int h,
- int xsrc, int ysrc)
+static void draw_sprite_part_with_mask(struct Sprite *sprite,
+ struct Sprite *sprite_mask,
+ HDC hdc,
+ int x, int y,int w, int h,
+ int xsrc, int ysrc)
{
HDC hdccomp;
HDC hdcmask;
Index: client/gui-win32/graphics.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-win32/graphics.h,v
retrieving revision 1.6
diff -u -r1.6 graphics.h
--- client/gui-win32/graphics.h 20 Feb 2003 23:14:33 -0000 1.6
+++ client/gui-win32/graphics.h 6 Mar 2004 02:20:03 -0000
@@ -45,11 +45,6 @@
void draw_sprite(struct Sprite *sprite,HDC hdc,int x, int y);
void draw_sprite_part(struct Sprite *sprite,HDC hdc,
int x, int y, int w, int h,int xsrc,int ysrc);
-void draw_sprite_part_with_mask(struct Sprite *sprite,
- struct Sprite *sprite_mask,
- HDC hdc,
- int x, int y, int w, int h,
- int xsrc, int ysrc);
void init_fog_bmp(void);
void draw_fog_part(HDC hdc,int x, int y,int w, int h,
int xsrc, int ysrc);
Index: client/gui-win32/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-win32/mapview.c,v
retrieving revision 1.98
diff -u -r1.98 mapview.c
--- client/gui-win32/mapview.c 5 Mar 2004 18:16:01 -0000 1.98
+++ client/gui-win32/mapview.c 6 Mar 2004 02:20:03 -0000
@@ -919,72 +919,6 @@
}
/**************************************************************************
-
-**************************************************************************/
-static void dither_tile(HDC hdc, struct Sprite **dither,
- int canvas_x, int canvas_y,
- int offset_x, int offset_y,
- int width, int height, bool fog)
-{
- if (!width || !height)
- return;
-
- assert(offset_x == 0 || offset_x == NORMAL_TILE_WIDTH/2);
- assert(offset_y == 0 || offset_y == NORMAL_TILE_HEIGHT/2);
- assert(width == NORMAL_TILE_WIDTH || width == NORMAL_TILE_WIDTH/2);
- assert(height == NORMAL_TILE_HEIGHT || height == NORMAL_TILE_HEIGHT/2);
-
- /* north */
- if (dither[0]
- && (offset_x != 0 || width == NORMAL_TILE_WIDTH)
- && (offset_y == 0)) {
- draw_sprite_part_with_mask(dither[0],sprites.dither_tile,hdc,
- canvas_x + NORMAL_TILE_WIDTH/2, canvas_y,
- NORMAL_TILE_WIDTH/2, NORMAL_TILE_HEIGHT/2,
- NORMAL_TILE_WIDTH/2, 0);
- }
-
- /* south */
- if (dither[1] && offset_x == 0
- && (offset_y == NORMAL_TILE_HEIGHT/2 || height == NORMAL_TILE_HEIGHT)) {
- draw_sprite_part_with_mask(dither[1],sprites.dither_tile,hdc,
- canvas_x,
- canvas_y + NORMAL_TILE_HEIGHT/2,
- NORMAL_TILE_WIDTH/2, NORMAL_TILE_HEIGHT/2,
- 0, NORMAL_TILE_HEIGHT/2);
- }
-
- /* east */
- if (dither[2]
- && (offset_x != 0 || width == NORMAL_TILE_WIDTH)
- && (offset_y != 0 || height == NORMAL_TILE_HEIGHT)) {
- draw_sprite_part_with_mask(dither[2],sprites.dither_tile,hdc,
- canvas_x + NORMAL_TILE_WIDTH/2,
- canvas_y + NORMAL_TILE_HEIGHT/2,
- NORMAL_TILE_WIDTH/2, NORMAL_TILE_HEIGHT/2,
- NORMAL_TILE_WIDTH/2, NORMAL_TILE_HEIGHT/2);
- }
-
- /* west */
- if (dither[3] && offset_x == 0 && offset_y == 0) {
- draw_sprite_part_with_mask(dither[3],sprites.dither_tile,hdc,
- canvas_x,
- canvas_y,
- NORMAL_TILE_WIDTH/2, NORMAL_TILE_HEIGHT/2,
- 0,0);
- }
-
-
- if (fog) {
- draw_fog_part(hdc,canvas_x+offset_x, canvas_y+offset_y,
- MIN(width, MAX(0, NORMAL_TILE_WIDTH-offset_x)),
- MIN(height, MAX(0, NORMAL_TILE_HEIGHT-offset_y)),
- offset_x,offset_y);
- }
-
-}
-
-/**************************************************************************
draw a line from src_x,src_y -> dest_x,dest_y on both map_canvas and
map_canvas_store
FIXME: We currently always draw the line.
@@ -1260,19 +1194,17 @@
enum draw_type draw)
{
struct drawn_sprite tile_sprs[80];
- struct Sprite *dither[4];
struct city *pcity;
struct unit *punit, *pfocus;
struct canvas_store canvas_store={hdc,NULL};
enum tile_special_type special;
- int count, i = 0, dither_count;
+ int count, i;
bool fog, solid_bg, is_real;
if (!width || !(height || height_unit))
return;
- count = fill_tile_sprite_array_iso(tile_sprs, dither, &dither_count,
- x, y, citymode, &solid_bg);
+ count = fill_tile_sprite_array_iso(tile_sprs, x, y, citymode, &solid_bg);
if (count == -1) { /* tile is unknown */
pixmap_put_black_tile_iso(hdc, canvas_x, canvas_y,
@@ -1306,19 +1238,8 @@
SelectObject(hdc,oldbrush);
}
- /*** Draw and dither base terrain ***/
- if (dither_count > 0) {
- for (i = 0; i < dither_count; i++) {
- pixmap_put_drawn_sprite(hdc, canvas_x, canvas_y, &tile_sprs[i],
- offset_x, offset_y, width, height, fog);
- }
-
- dither_tile(hdc, dither, canvas_x, canvas_y,
- offset_x, offset_y, width, height, fog);
- }
-
- /*** Rest of terrain and specials ***/
- for (; i<count; i++) {
+ /*** Draw terrain and specials ***/
+ for (i = 0; i < count; i++) {
if (tile_sprs[i].sprite)
pixmap_put_drawn_sprite(hdc, canvas_x, canvas_y, &tile_sprs[i],
offset_x, offset_y, width, height, fog);
Index: client/gui-xaw/graphics.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/graphics.c,v
retrieving revision 1.51
diff -u -r1.51 graphics.c
--- client/gui-xaw/graphics.c 24 Feb 2004 05:20:25 -0000 1.51
+++ client/gui-xaw/graphics.c 6 Mar 2004 02:20:03 -0000
@@ -165,9 +165,12 @@
return newly allocated sprite cropped from source
***************************************************************************/
struct Sprite *crop_sprite(struct Sprite *source,
- int x, int y, int width, int height)
+ int x, int y, int width, int height,
+ struct Sprite *mask,
+ int mask_offset_x, int mask_offset_y)
{
- Pixmap mypixmap;
+ Pixmap mypixmap, mymask;
+ GC plane_gc;
mypixmap = XCreatePixmap(display, root_window,
width, height, display_depth);
@@ -175,16 +178,33 @@
x, y, width, height, 0, 0);
if (source->has_mask) {
- GC plane_gc;
- Pixmap mask;
+ mymask = XCreatePixmap(display, root_window, width, height, 1);
- mask = XCreatePixmap(display, root_window, width, height, 1);
+ plane_gc = XCreateGC(display, mymask, 0, NULL);
+ XCopyArea(display, source->mask, mymask, plane_gc,
+ x, y, width, height, 0, 0);
+ XFreeGC(display, plane_gc);
+
+ if (mask) {
+ XGCValues values;
+
+ values.function = GXand;
+
+ plane_gc = XCreateGC(display, mymask, GCFunction, &values);
+ XCopyArea(display, mask->mask, mymask, plane_gc,
+ x - mask_offset_x, y - mask_offset_y, width, height, 0, 0);
+ XFreeGC(display, plane_gc);
+ }
+
+ return ctor_sprite_mask(mypixmap, mymask, width, height);
+ } else if (mask) {
+ mymask = XCreatePixmap(display, root_window, width, height, 1);
- plane_gc = XCreateGC(display, mask, 0, NULL);
- XCopyArea(display, source->mask, mask, plane_gc,
+ plane_gc = XCreateGC(display, mymask, 0, NULL);
+ XCopyArea(display, source->mask, mymask, plane_gc,
x, y, width, height, 0, 0);
XFreeGC(display, plane_gc);
- return ctor_sprite_mask(mypixmap, mask, width, height);
+ return ctor_sprite_mask(mypixmap, mymask, width, height);
} else {
return ctor_sprite(mypixmap, width, height);
}
Index: client/include/graphics_g.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/include/graphics_g.h,v
retrieving revision 1.9
diff -u -r1.9 graphics_g.h
--- client/include/graphics_g.h 24 Feb 2004 05:20:25 -0000 1.9
+++ client/include/graphics_g.h 6 Mar 2004 02:20:03 -0000
@@ -29,7 +29,9 @@
struct Sprite *load_gfxfile(const char *filename);
struct Sprite *crop_sprite(struct Sprite *source,
- int x, int y, int width, int height);
+ int x, int y, int width, int height,
+ struct Sprite *mask,
+ int mask_offset_x, int mask_offset_y);
void get_sprite_dimensions(struct Sprite *sprite, int *width, int *height);
void free_sprite(struct Sprite *s);
Index: data/isotrident.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/isotrident.tilespec,v
retrieving revision 1.12
diff -u -r1.12 isotrident.tilespec
--- data/isotrident.tilespec 27 Feb 2004 18:31:39 -0000 1.12
+++ data/isotrident.tilespec 6 Mar 2004 02:20:03 -0000
@@ -102,7 +102,7 @@
; ocean has special handling
[terrain_ocean]
-is_blended = 0
+is_blended = 1
is_layered = 0
match_type = 6
cell_type = "rect"
Index: data/trident.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/trident.tilespec,v
retrieving revision 1.18
diff -u -r1.18 trident.tilespec
--- data/trident.tilespec 27 Feb 2004 00:14:00 -0000 1.18
+++ data/trident.tilespec 6 Mar 2004 02:20:03 -0000
@@ -122,7 +122,7 @@
[terrain_unknown]
is_blended = 0
is_layered = 0
-match_type = 11
+match_type = 0
[terrain_t_river]
is_blended = 0
Index: data/isotrident/terrain1.spec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/isotrident/terrain1.spec,v
retrieving revision 1.2
diff -u -r1.2 terrain1.spec
--- data/isotrident/terrain1.spec 17 Feb 2004 04:53:00 -0000 1.2
+++ data/isotrident/terrain1.spec 6 Mar 2004 02:20:04 -0000
@@ -53,8 +53,6 @@
9, 0, "t.jungle1"
- 10, 0, "t.ocean1"
-
; Terrain special resources:
0, 2, "ts.oasis"
@@ -135,7 +133,8 @@
0, 0, "t.dither_tile"
0, 1, "tx.fog"
0, 2, "t.black_tile"
- 0, 3, "t.coast_color"
+ 0, 2, "t.unknown1"
+ 0, 3, "t.ocean1"
0, 4, "user.attention"
}
- [Freeciv-Dev] (PR#7612) crop_sprite with a mask,
Jason Short <=
|
|