Complete.Org: Mailing Lists: Archives: freeciv-dev: February 2004:
[Freeciv-Dev] (PR#7428) remove special-casing for ocean drawing
Home

[Freeciv-Dev] (PR#7428) remove special-casing for ocean drawing

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#7428) remove special-casing for ocean drawing
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 16 Feb 2004 22:59:59 -0800
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=7428 >

Currently fill_tile_sprite_array_iso returns an array called "coasts". 
This is an array of 4 sprites, used for ocean only, to be drawn and 
dithered at special offsets.

This was needed originally because, unlike all the sprites in the 
sprites array, these sprites have a nonzero offset.  However with the 
introduction of the drawn_sprite the sprite array gives an offset for 
each sprite.  Thus we don't need the coasts array; we can just fold this 
into the sprite array.

This simplifies the logic for blending.  A new variable dither_count 
must be passed to fill_tile_sprite_array_iso.  This variable specifies 
the number of sprites to be drawn before doing the blend.  For most 
terrains this is 1; for oceans it is 4.  (I snuck in a check to disable 
blending if it's not needed - basically, don't blend the deep ocean.)


A bug in pixmap_put_drawn_sprite is exposed.  Attached is an diagram to 
explain what this function is supposed to do.  Originally it was buggy, 
and I'm not sure that my fix is correct either.

In the diagram, point A is the drawing origin (canvas_x, canvas_y). 
Point B is the draw offset at (offset_x, offset_y) (with respect to the 
origin); rectangle B has dimension (width, height).  Point C is the 
sprite offset at (s->offset_x, s->offset_y) (with respect to the 
origin); rectangle B has dimension (s->sprite->width, 
s->sprite->height).  Note that point B is at the sprite origin (0,0 in 
sprite coordinates).  The blue area is to be copied from the sprite to 
the canvas.

Note that the relative positions of the two rectangles may be different 
from how it is in the diagram.  You can't assume offset_x < s->offset_x, 
or anything like that.  This makes the correct logic pretty complicated.

jason

Index: client/tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.138
diff -u -r1.138 tilespec.c
--- client/tilespec.c   2004/02/17 04:52:59     1.138
+++ client/tilespec.c   2004/02/17 06:50:18
@@ -1896,10 +1896,8 @@
  5) huts
 ***********************************************************************/
 int fill_tile_sprite_array_iso(struct drawn_sprite *sprs,
-                              struct Sprite **coasts,
-                              struct Sprite **dither,
-                              int x, int y, bool citymode,
-                              bool *solid_bg)
+                              struct Sprite **dither, int *dither_count,
+                              int x, int y, bool citymode, bool *solid_bg)
 {
   enum tile_terrain_type ttype, ttype_near[8];
   enum tile_special_type tspecial, tspecial_near[8];
@@ -1919,13 +1917,48 @@
   if (draw_terrain) {
     if (is_ocean(ttype)) {
       /* painted via coasts. */
+      const enum direction8 dirs[4] = {
+       DIR8_NORTHWEST, /* up */
+       DIR8_SOUTHEAST, /* down */
+       DIR8_SOUTHWEST, /* left */
+       DIR8_NORTHEAST /* right */
+      };
+      const int offsets[4][2] = {
+       {NORMAL_TILE_WIDTH / 4, 0},
+       {NORMAL_TILE_WIDTH / 4, NORMAL_TILE_HEIGHT / 2},
+       {0, NORMAL_TILE_HEIGHT / 4},
+       {NORMAL_TILE_WIDTH / 2, NORMAL_TILE_HEIGHT / 4},
+      };
+
+      *dither_count = 4;
+
+      /* put coasts */
+      for (i = 0; i < 4; i++) {
+       int array_index = ((!is_ocean(ttype_near[dir_ccw(dirs[i])]) ? 1 : 0)
+                          + (!is_ocean(ttype_near[dirs[i]]) ? 2 : 0)
+                          + (!is_ocean(ttype_near[dir_cw(dirs[i])])
+                             ? 4 : 0));
 
+       ADD_SPRITE(sprites.tx.coast_cape_iso[array_index][i],
+                  offsets[i][0], offsets[i][1]);
+      }
+
       for (dir = 0; dir < 4; dir++) {
        if (contains_special(tspecial_near[DIR4_TO_DIR8[dir]], S_RIVER)) {
          ADD_SPRITE_SIMPLE(sprites.tx.river_outlet[dir]);
        }
       }
+
+      if (draw_specials) {
+       if (contains_special(tspecial, S_SPECIAL_1)) {
+         ADD_SPRITE_SIMPLE(sprites.terrain[ttype]->special[0]);
+       } else if (contains_special(tspecial, S_SPECIAL_2)) {
+         ADD_SPRITE_SIMPLE(sprites.terrain[ttype]->special[1]);
+       }
+      }
     } else {
+      *dither_count = 1;
+
       if (sprites.terrain[ttype]->match_type == 0
          || sprites.terrain[ttype]->is_layered) {
        ADD_SPRITE_SIMPLE(sprites.terrain[ttype]->base);
@@ -1958,8 +1991,17 @@
        ADD_SPRITE_SIMPLE(sprites.tx.spec_river[tileno]);
       }
     }
+
+    /* Short-cut past dithering if all adjacent tiles are the same. */
+    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 {
     *solid_bg = TRUE;
+    *dither_count = 0;
 
     /* This call is duplicated because it is normally
      * drawn underneath rivers. */
@@ -1967,36 +2009,7 @@
                                         pcity);
   }
   
-  if (is_ocean(ttype)) {
-    const int dirs[4] = {
-      /* up */
-      DIR8_NORTHWEST,
-      /* down */
-      DIR8_SOUTHEAST,
-      /* left */
-      DIR8_SOUTHWEST,
-      /* right */
-      DIR8_NORTHEAST
-    };
-
-    /* put coasts */
-    for (i = 0; i < 4; i++) {
-      int array_index = ((!is_ocean(ttype_near[dir_ccw(dirs[i])]) ? 1 : 0)
-                        + (!is_ocean(ttype_near[dirs[i]]) ? 2 : 0)
-                        + (!is_ocean(ttype_near[dir_cw(dirs[i])]) ? 4 : 0));
-
-      coasts[i] = sprites.tx.coast_cape_iso[array_index][i];
-    }
-        
-    if (draw_specials) {
-      if (contains_special(tspecial, S_SPECIAL_1)) {
-       ADD_SPRITE_SIMPLE(sprites.terrain[ttype]->special[0]);
-      } else if (contains_special(tspecial, S_SPECIAL_2)) {
-       ADD_SPRITE_SIMPLE(sprites.terrain[ttype]->special[1]);
-      }
-    }
-    
-  } else {
+  if (!is_ocean(ttype)) {
     sprs += fill_road_rail_sprite_array(sprs,
                                        tspecial, tspecial_near, pcity);
 
Index: client/tilespec.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.h,v
retrieving revision 1.50
diff -u -r1.50 tilespec.h
--- client/tilespec.h   2004/02/17 04:52:59     1.50
+++ client/tilespec.h   2004/02/17 06:50:18
@@ -53,10 +53,8 @@
 /* Gfx support */
 
 int fill_tile_sprite_array_iso(struct drawn_sprite *sprs,
-                              struct Sprite **coasts,
-                              struct Sprite **dither,
-                              int x, int y, bool citymode,
-                              bool *solid_bg);
+                              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,
                           struct player **pplayer);
Index: client/gui-gtk/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/mapview.c,v
retrieving revision 1.193
diff -u -r1.193 mapview.c
--- client/gui-gtk/mapview.c    2004/02/13 09:24:41     1.193
+++ client/gui-gtk/mapview.c    2004/02/17 06:50:18
@@ -1304,7 +1304,7 @@
   pixmap_put_overlay_tile_draw(pixmap, canvas_x + ox, canvas_y + oy,
                               pdsprite->sprite,
                               offset_x - ox, offset_y - oy,
-                              width - ox, height - oy,
+                              width, height,
                               fog);
 }
 
@@ -1436,19 +1436,18 @@
                                enum draw_type draw)
 {
   struct drawn_sprite tile_sprs[80];
-  struct Sprite *coasts[4];
   struct Sprite *dither[4];
   struct city *pcity;
   struct unit *punit, *pfocus;
   enum tile_special_type special;
-  int count, i = 0;
+  int count, i = 0, dither_count;
   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, coasts, dither,
+  count = fill_tile_sprite_array_iso(tile_sprs, dither, &dither_count,
                                     x, y, citymode, &solid_bg);
 
   if (count == -1) { /* tile is unknown */
@@ -1492,57 +1491,15 @@
     }
   }
 
-  if (draw_terrain) {
-    if (is_ocean(map_get_terrain(x, y))) { /* coasts */
-      int dx, dy;
-      /* top */
-      dx = offset_x-NORMAL_TILE_WIDTH/4;
-      pixmap_put_overlay_tile_draw(pm, canvas_x + NORMAL_TILE_WIDTH/4,
-                                  canvas_y, coasts[0],
-                                  MAX(0, dx),
-                                  offset_y,
-                                  MAX(0, width-MAX(0, -dx)),
-                                  height,
-                                  fog);
-      /* bottom */
-      dx = offset_x-NORMAL_TILE_WIDTH/4;
-      dy = offset_y-NORMAL_TILE_HEIGHT/2;
-      pixmap_put_overlay_tile_draw(pm, canvas_x + NORMAL_TILE_WIDTH/4,
-                                  canvas_y + NORMAL_TILE_HEIGHT/2, coasts[1],
-                                  MAX(0, dx),
-                                  MAX(0, dy),
-                                  MAX(0, width-MAX(0, -dx)),
-                                  MAX(0, height-MAX(0, -dy)),
-                                  fog);
-      /* left */
-      dy = offset_y-NORMAL_TILE_HEIGHT/4;
-      pixmap_put_overlay_tile_draw(pm, canvas_x,
-                                  canvas_y + NORMAL_TILE_HEIGHT/4, coasts[2],
-                                  offset_x,
-                                  MAX(0, dy),
-                                  width,
-                                  MAX(0, height-MAX(0, -dy)),
-                                  fog);
-      /* right */
-      dx = offset_x-NORMAL_TILE_WIDTH/2;
-      dy = offset_y-NORMAL_TILE_HEIGHT/4;
-      pixmap_put_overlay_tile_draw(pm, canvas_x + NORMAL_TILE_WIDTH/2,
-                                  canvas_y + NORMAL_TILE_HEIGHT/4, coasts[3],
-                                  MAX(0, dx),
-                                  MAX(0, dy),
-                                  MAX(0, width-MAX(0, -dx)),
-                                  MAX(0, height-MAX(0, -dy)),
-                                  fog);
-    } else {
-      pixmap_put_drawn_sprite(pm, canvas_x, canvas_y, &tile_sprs[0],
+  /*** 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);
-      i++;
     }
 
-    /*** Dither base terrain ***/
-    if (draw_terrain)
-      dither_tile(pm, dither, canvas_x, canvas_y,
-                 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 ***/
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.93
diff -u -r1.93 mapview.c
--- client/gui-gtk-2.0/mapview.c        2004/02/13 09:24:41     1.93
+++ client/gui-gtk-2.0/mapview.c        2004/02/17 06:50:18
@@ -1381,7 +1381,7 @@
   pixmap_put_overlay_tile_draw(pixmap, canvas_x + ox, canvas_y + oy,
                               pdsprite->sprite,
                               offset_x - ox, offset_y - oy,
-                              width - ox, height - oy,
+                              width, height,
                               fog);
 }
 
@@ -1513,19 +1513,18 @@
                                enum draw_type draw)
 {
   struct drawn_sprite tile_sprs[80];
-  struct Sprite *coasts[4];
   struct Sprite *dither[4];
   struct city *pcity;
   struct unit *punit, *pfocus;
   enum tile_special_type special;
-  int count, i = 0;
+  int count, i = 0, dither_count;
   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, coasts, dither,
+  count = fill_tile_sprite_array_iso(tile_sprs, dither, &dither_count,
                                     x, y, citymode, &solid_bg);
 
   if (count == -1) { /* tile is unknown */
@@ -1569,57 +1568,15 @@
     }
   }
 
-  if (draw_terrain) {
-    if (is_ocean(map_get_terrain(x, y))) { /* coasts */
-      int dx, dy;
-      /* top */
-      dx = offset_x-NORMAL_TILE_WIDTH/4;
-      pixmap_put_overlay_tile_draw(pm, canvas_x + NORMAL_TILE_WIDTH/4,
-                                  canvas_y, coasts[0],
-                                  MAX(0, dx),
-                                  offset_y,
-                                  MAX(0, width-MAX(0, -dx)),
-                                  height,
-                                  fog);
-      /* bottom */
-      dx = offset_x-NORMAL_TILE_WIDTH/4;
-      dy = offset_y-NORMAL_TILE_HEIGHT/2;
-      pixmap_put_overlay_tile_draw(pm, canvas_x + NORMAL_TILE_WIDTH/4,
-                                  canvas_y + NORMAL_TILE_HEIGHT/2, coasts[1],
-                                  MAX(0, dx),
-                                  MAX(0, dy),
-                                  MAX(0, width-MAX(0, -dx)),
-                                  MAX(0, height-MAX(0, -dy)),
-                                  fog);
-      /* left */
-      dy = offset_y-NORMAL_TILE_HEIGHT/4;
-      pixmap_put_overlay_tile_draw(pm, canvas_x,
-                                  canvas_y + NORMAL_TILE_HEIGHT/4, coasts[2],
-                                  offset_x,
-                                  MAX(0, dy),
-                                  width,
-                                  MAX(0, height-MAX(0, -dy)),
-                                  fog);
-      /* right */
-      dx = offset_x-NORMAL_TILE_WIDTH/2;
-      dy = offset_y-NORMAL_TILE_HEIGHT/4;
-      pixmap_put_overlay_tile_draw(pm, canvas_x + NORMAL_TILE_WIDTH/2,
-                                  canvas_y + NORMAL_TILE_HEIGHT/4, coasts[3],
-                                  MAX(0, dx),
-                                  MAX(0, dy),
-                                  MAX(0, width-MAX(0, -dx)),
-                                  MAX(0, height-MAX(0, -dy)),
-                                  fog);
-    } else {
-      pixmap_put_drawn_sprite(pm, canvas_x, canvas_y, &tile_sprs[0],
+  /*** 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);
-      i++;
     }
 
-    /*** Dither base terrain ***/
-    if (draw_terrain)
-      dither_tile(pm, dither, canvas_x, canvas_y,
-                 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 ***/
Index: client/gui-win32/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-win32/mapview.c,v
retrieving revision 1.87
diff -u -r1.87 mapview.c
--- client/gui-win32/mapview.c  2004/02/03 20:16:08     1.87
+++ client/gui-win32/mapview.c  2004/02/17 06:50:18
@@ -1283,7 +1283,7 @@
   pixmap_put_overlay_tile_draw(hdc, canvas_x + ox, canvas_y + oy,
                                pdsprite->sprite,
                                offset_x - ox, offset_y - oy,
-                               width - ox, height - oy,
+                               width, height,
                                fog);
   
 }
@@ -1325,19 +1325,18 @@
                                 enum draw_type draw)
 {
   struct drawn_sprite tile_sprs[80];
-  struct Sprite *coasts[4];
   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;
+  int count, i = 0, dither_count;
   bool fog, solid_bg, is_real;
 
   if (!width || !(height || height_unit))
     return;
 
-  count = fill_tile_sprite_array_iso(tile_sprs, coasts, dither,
+  count = fill_tile_sprite_array_iso(tile_sprs, dither, &dither_count
                                      x, y, citymode, &solid_bg);
 
   if (count == -1) { /* tile is unknown */
@@ -1371,60 +1370,20 @@
     SelectObject(hdc,oldpen);
     SelectObject(hdc,oldbrush);
   }
-  if (draw_terrain) {
-    if (is_ocean(map_get_terrain(x, y))) { /* coasts */
-      int dx, dy;
-      /* top */
-      dx = offset_x-NORMAL_TILE_WIDTH/4;
-      pixmap_put_overlay_tile_draw(hdc, canvas_x + NORMAL_TILE_WIDTH/4,
-                                   canvas_y, coasts[0],
-                                   MAX(0, dx),
-                                   offset_y,
-                                   MAX(0, width-MAX(0, -dx)),
-                                   height,
-                                   fog);
-      /* bottom */
-      dx = offset_x-NORMAL_TILE_WIDTH/4;
-      dy = offset_y-NORMAL_TILE_HEIGHT/2;
-      pixmap_put_overlay_tile_draw(hdc, canvas_x + NORMAL_TILE_WIDTH/4,
-                                   canvas_y + NORMAL_TILE_HEIGHT/2, coasts[1],
-                                   MAX(0, dx),
-                                   MAX(0, dy),
-                                   MAX(0, width-MAX(0, -dx)),
-                                   MAX(0, height-MAX(0, -dy)),
-                                   fog);
-      /* left */
-      dy = offset_y-NORMAL_TILE_HEIGHT/4;
-      pixmap_put_overlay_tile_draw(hdc, canvas_x,
-                                   canvas_y + NORMAL_TILE_HEIGHT/4, coasts[2],
-                                   offset_x,
-                                   MAX(0, dy),
-                                   width,
-                                   MAX(0, height-MAX(0, -dy)),
-                                   fog);
-      /* right */
-      dx = offset_x-NORMAL_TILE_WIDTH/2;
-      dy = offset_y-NORMAL_TILE_HEIGHT/4;
-      pixmap_put_overlay_tile_draw(hdc, canvas_x + NORMAL_TILE_WIDTH/2,
-                                   canvas_y + NORMAL_TILE_HEIGHT/4, coasts[3],
-                                   MAX(0, dx),
-                                   MAX(0, dy),
-                                   MAX(0, width-MAX(0, -dx)),
-                                   MAX(0, height-MAX(0, -dy)),
-                                   fog);
 
-    } else {
+  /*** 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[0],
-                                   offset_x, offset_y, width, height, fog);
+                             offset_x, offset_y, width, height, fog);
       i++;
     }
-    if (draw_terrain) {
-      dither_tile(hdc, dither, canvas_x, canvas_y,
+
+    dither_tile(hdc, dither, canvas_x, canvas_y,
                   offset_x, offset_y, width, height, fog);
-      if (fog)
-       draw_fog_part(hdc,canvas_x+offset_x,canvas_y+offset_y,
-                     width,height,offset_x,offset_y);
-    }
+
+    draw_fog_part(hdc,canvas_x+offset_x,canvas_y+offset_y,
+                 width,height,offset_x,offset_y);
   }
   
   /*** Rest of terrain and specials ***/

PNG image


[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#7428) remove special-casing for ocean drawing, Jason Short <=