pingus-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Pingus-Devel] Patch to SDL branch. Fix scaling on different resolutions


From: Aggro
Subject: [Pingus-Devel] Patch to SDL branch. Fix scaling on different resolutions.
Date: Thu, 26 Jul 2007 02:55:42 -0700 (PDT)

This is a patch to the SDL branch, NOT to the trunk
version where Clanlib is used. 

SDL Branch
svn co
svn://svn.berlios.de/pingus/branches/pingus_sdl/ 

Currently background images are not displayed at all
on many locations if resolution is not 800x600. This
causes severe graphic bugs when menus and texts are
drawn on previously visible images, making texts very
hard to read. This patch implements a scale function
and takes it into use on many locations where
background images are drawn. 

Note! This patch also adds new library requirement:
SDL_gfx, which is used for scaling. 

Tested to work on default settings and with parameter:
-g 1024x800

Known bugs: When moving on the worldmap when using
1024x800 resolution, the top of the screen is not
properly cleared. This problem exists on the current
version also and I didn't yet figure out a proper fix
for it. 

-- 



      
____________________________________________________________________________________
Park yourself in front of a world of choices in alternative vehicles. Visit the 
Yahoo! Auto Green Center.
http://autos.yahoo.com/green_center/ 
Index: src/blitter.cpp
===================================================================
--- src/blitter.cpp     (revision 2765)
+++ src/blitter.cpp     (working copy)
@@ -20,6 +20,7 @@
 #include <config.h>
 #include <stdio.h>
 #include <assert.h>
+#include <SDL_rotozoom.h>
 
 #include "string_util.hpp"
 #include "pingus_error.hpp"
@@ -471,139 +472,31 @@
 }
 
 PixelBuffer
-Blitter::scale_surface_to_canvas (PixelBuffer provider, int width, int height)
+Blitter::scale_surface_to_canvas(const CL_Surface& sur, int width, int height)
 {
-  PixelBuffer canvas(width, height, width*4, CL_PixelFormat::rgba8888);
-
-  provider.lock ();
-  canvas.lock ();
-
-  unsigned char* sbuffer = static_cast<unsigned char*>(provider.get_data ());
-  unsigned char* tbuffer = static_cast<unsigned char*>(canvas.get_data ());
-  int pwidth = provider.get_width ();
-  int pheight = provider.get_height ();
-  int pitch = provider.get_pitch();
-
-       if (provider.get_format().get_type() ==  pixelformat_index)
-       {
-               Color color;
-               pout(PINGUS_DEBUG_ACTIONS) << 
-                       "Blitter::scale_surface_to_canvas() - Scaling indexed 
image" << std::endl;
-                 
-               for (int y = 0; y < height; ++y)
-                       for (int x = 0; x < width; ++x)
-                       {
-                               unsigned offset = (y * pheight/height) * pitch 
+ (x * pwidth/width);
-
-                               color = 
provider.get_palette().colors[sbuffer[offset]];
-
-                               // Detrmine alpha channel
-                               if (provider.get_format().has_colorkey()
-                                       && provider.get_format().get_colorkey() 
== sbuffer[offset])
-                                       color.set_alpha(0);
-                               else
-                                       color.set_alpha(255);
-     
-                               canvas.draw_pixel(x, y, color);
-       }
-       }
-  else
-    {
-      switch (provider.get_format().get_depth())
-       {
-       case 24:
-         {
-           // We assume that we have the data in RGB888, which might not be
-           // the case
-             pout(PINGUS_DEBUG_ACTIONS) << 
-               "Blitter::scale_surface_to_canvas() - Scaling 24 bit image" << 
std::endl;
-           for (int y = 0; y < height; ++y)
-             for (int x = 0; x < width; ++x)
-               {
-                 int ti = (y * width + x) * 4;
-                 int si = ((y * pheight / height) * pwidth
-                           + (x * pwidth / width)) * 3;
-
-          if (!CL_Endian::is_system_big())
-          {
-            tbuffer[ti + 0] = 255; // alpha
-            tbuffer[ti + 1] = sbuffer[(si + 0)]; // blue
-            tbuffer[ti + 2] = sbuffer[(si + 1)]; // green
-            tbuffer[ti + 3] = sbuffer[(si + 2)]; // red
-          }
-          else
-          {
-            tbuffer[ti + 3] = 255; // alpha
-            tbuffer[ti + 0] = sbuffer[(si + 0)]; // blue
-            tbuffer[ti + 1] = sbuffer[(si + 1)]; // green
-            tbuffer[ti + 2] = sbuffer[(si + 2)]; // red
-          }
-               }
-         }
-         break;
-       case 32:
-         {
-           // We assume that we have the data in RGBA8888, which might not be
-           // the case
-               pout(PINGUS_DEBUG_ACTIONS) << 
-                       "Blitter::scale_surface_to_canvas() - Scaling 32 bit 
image" << std::endl;
-                       
-           for (int y = 0; y < height; ++y)
-             for (int x = 0; x < width; ++x)
-               {
-                 int ti = (y * width + x) * 4;
-                 int si = ((y * pheight / height) * pwidth
-                           + (x * pwidth / width)) * 4;
-
-          if (!CL_Endian::is_system_big())
-          {
-            tbuffer[ti + 0] = sbuffer[(si + 0)]; // alpha
-            tbuffer[ti + 1] = sbuffer[(si + 1)]; // blue
-            tbuffer[ti + 2] = sbuffer[(si + 2)]; // green
-            tbuffer[ti + 3] = sbuffer[(si + 3)]; // red
-          }
-          else
-          {
-            tbuffer[ti + 3] = sbuffer[(si + 0)]; // alpha
-            tbuffer[ti + 2] = sbuffer[(si + 1)]; // blue
-            tbuffer[ti + 1] = sbuffer[(si + 2)]; // green
-            tbuffer[ti + 0] = sbuffer[(si + 3)]; // red
-          }
-               }
-         }
-         break;
-       default:
-               // Slow but generic, using get_data () would be better, but 
would
-               // require quite a bit of work
-               pout(PINGUS_DEBUG_ACTIONS) << 
-                       "Blitter::scale_surface_to_canvas() - Scaling image 
using default method" 
-                       << std::endl;
-
-               for (int y = 0; y < height; ++y)
-                       for (int x = 0; x < width; ++x)
-                       {
-                               Color color = provider.get_pixel(x * pwidth / 
width,
-                                       y * pheight / height);
-                               // FIXME: ignoring the source alpha due to 
get_pixel
-                               // brokeness... no time to test the patch
-                               canvas.draw_pixel(x, y, color);
-                       }
-               break;
-       }
-    }
-
-  canvas.unlock ();
-  provider.unlock ();
-
-  return canvas; 
+  return Blitter::scale_surface_to_canvas(sur.get_pixeldata(), width, height);
 }
+#endif
 
 PixelBuffer
-Blitter::scale_surface_to_canvas(const CL_Surface& sur, int width, int height)
+Blitter::scale_surface_to_canvas (PixelBuffer provider, int width, int height)
 {
-  return Blitter::scale_surface_to_canvas(sur.get_pixeldata(), width, height);
+  if( provider.get_width()  == width &&
+      provider.get_height() == height )
+  {
+    // No need to change PixelBuffer. Create a copy of it and return it. 
+    PixelBuffer buf( provider );
+    return buf;
+  }
+
+  // zoomSurface doesn't round zoomx and zoomy correctly, so we have to use
+  // old +0.5 trick or we could end up with 1 pixel error in new size
+  double zoomx = (static_cast<double>(width)+0.5) / 
static_cast<double>(provider.get_width()); 
+  double zoomy = (static_cast<double>(height)+0.5) / 
static_cast<double>(provider.get_height());
+  SDL_Surface *result = zoomSurface( provider.get_surface(), zoomx, zoomy, 
SMOOTHING_ON );
+  PixelBuffer buf( result );
+  return buf;
 }
-#endif
 
 /** Flip a surface horizontal */
 PixelBuffer
Index: src/pixel_buffer.cpp
===================================================================
--- src/pixel_buffer.cpp        (revision 2765)
+++ src/pixel_buffer.cpp        (working copy)
@@ -43,6 +43,11 @@
 
 }
 
+PixelBuffer::PixelBuffer(SDL_Surface *surface)
+  : impl(new PixelBufferImpl(surface))
+{
+}
+
 PixelBuffer::PixelBuffer(int width, int height)
   : impl(new PixelBufferImpl())
 {
Index: src/pixel_buffer.hpp
===================================================================
--- src/pixel_buffer.hpp        (revision 2765)
+++ src/pixel_buffer.hpp        (working copy)
@@ -46,6 +46,7 @@
 {
 public:
   PixelBuffer();
+  PixelBuffer(SDL_Surface *surface);
   PixelBuffer(const std::string& name);
   PixelBuffer(int width, int height);
   ~PixelBuffer();
Index: src/worldobjs/surface_background.cpp
===================================================================
--- src/worldobjs/surface_background.cpp        (revision 2765)
+++ src/worldobjs/surface_background.cpp        (working copy)
@@ -65,7 +65,6 @@
   if (color.a > 1.0)
     std::cout << "Background: Warning dim larger than 1.0 are no longer 
supported" << std::endl;
 
-#if 0
   PixelBuffer canvas = Resource::load_pixelbuffer(desc);
 
   // Scaling Code
@@ -102,12 +101,7 @@
         }
     }
 
-  SpriteDescription sprite_desc;
-  sprite_desc.add_frame(canvas);
-  bg_surface = Sprite(sprite_desc);
-#else
-  bg_surface = Resource::load_sprite(desc);
-#endif
+  bg_surface = Sprite(canvas);
 
   timer.stop();
 }
Index: src/SConscript
===================================================================
--- src/SConscript      (revision 2765)
+++ src/SConscript      (working copy)
@@ -43,7 +43,7 @@
 #   clanMikMod-0.8         ">=" 0.8.0')
 
 env.ParseConfig('sdl-config  --cflags --libs')
-env['LIBS'] += ['SDL_image', 'SDL_mixer', 'physfs']
+env['LIBS'] += ['SDL_image', 'SDL_mixer', 'SDL_gfx', 'physfs']
 
 # sdl_env.ParseConfig('sdl-config  --cflags --libs')
 # sdl_env['LIBS'] += ['SDL_image']
Index: src/pingus_menu_manager.cpp
===================================================================
--- src/pingus_menu_manager.cpp (revision 2765)
+++ src/pingus_menu_manager.cpp (working copy)
@@ -37,7 +37,6 @@
        // resolution is not default
        if (w != 800 && h != 600)
        {
-#if 0
                background.add_layer (Blitter::scale_surface_to_canvas(
                        Resource::load_pixelbuffer("core/menu/layer1"), w, 185 
* h / 600), 0, 0, 12, 0);
                background.add_layer (Blitter::scale_surface_to_canvas(
@@ -48,7 +47,6 @@
                        Resource::load_pixelbuffer("core/menu/layer4"), w, 171 
* h / 600), 0, 429 * (float)h / 600, 100, 0);
                background.add_layer (Blitter::scale_surface_to_canvas(
                        Resource::load_pixelbuffer("core/menu/layer5"), 302 * w 
/ 800, 104 * h / 600), 0, 500 * (float)h / 600, 200, 0);
-#endif 
        }
        else
        {
Index: src/result_screen.cpp
===================================================================
--- src/result_screen.cpp       (revision 2765)
+++ src/result_screen.cpp       (working copy)
@@ -152,22 +152,11 @@
 ResultScreenComponent::ResultScreenComponent(Result arg_result)
   : result(arg_result)
 {
-  if (Display::get_width() == 800 && Display::get_height() == 600)
-    {
-      background = Resource::load_sprite("core/menu/startscreenbg");
-    }
-#if 0
-  else
-    {
-      PixelBuffer pb = 
Blitter::scale_surface_to_canvas(Resource::load_pixelbuffer(
-                                                                               
    "core/menu/startscreenbg"), Display::get_width(), Display::get_height());
-      CL_SpriteDescription desc;
-      desc.add_frame(pb);
-      background = CL_Sprite(desc);
-    }
-  background.set_alignment(origin_center);
-#endif
-       
+  PixelBuffer pb = Blitter::scale_surface_to_canvas(Resource::load_pixelbuffer(
+                   "core/menu/startscreenbg"), Display::get_width(), 
Display::get_height());
+  background = Sprite( pb );
+
+
   chalk_pingus.push_back(Resource::load_sprite("core/misc/chalk_pingu1"));
   chalk_pingus.push_back(Resource::load_sprite("core/misc/chalk_pingu2"));
   chalk_pingus.push_back(Resource::load_sprite("core/misc/chalk_pingu3"));
@@ -182,7 +171,7 @@
 void
 ResultScreenComponent::draw(DrawingContext& gc)
 {
-  gc.draw(background, Vector3f(gc.get_width()/2, gc.get_height()/2));
+  gc.draw(background, 0, 0);
 
   gc.print_center(Fonts::chalk_large, gc.get_width()/2, 
                   (float)Display::get_height()/2 - 200,
Index: src/start_screen.cpp
===================================================================
--- src/start_screen.cpp        (revision 2765)
+++ src/start_screen.cpp        (working copy)
@@ -134,28 +134,17 @@
 StartScreenComponent::StartScreenComponent(const PingusLevel& p)
   : plf(p)
 {
-  if (Display::get_width() == 800 && Display::get_height() == 600)
-    {
-      background = Resource::load_sprite("core/menu/startscreenbg");
-    }
-  else
-    {
-#if 0
-      PixelBuffer pb = 
Blitter::scale_surface_to_canvas(Resource::load_pixelbuffer(
-                                                                               
       "core/menu/startscreenbg"), Display::get_width(), Display::get_height());
-      CL_SpriteDescription desc;
-      desc.add_frame(pb);
-      background = CL_Sprite(desc);
-#endif
-    }
-  ////background.set_alignment(origin_center);
+  PixelBuffer pb = Blitter::scale_surface_to_canvas(Resource::load_pixelbuffer(
+                   "core/menu/startscreenbg"), Display::get_width(), 
Display::get_height());
+  background = Sprite( pb );
+
   time_str = GameTime::ticks_to_realtime_string(plf.get_time());
 }
 
 void
 StartScreenComponent::draw(DrawingContext& gc)
 {
-  gc.draw(background, Display::get_width()/2.f, Display::get_height()/2.f);
+  gc.draw(background, 0, 0);
 
   int left_x  = Display::get_width()/2 - 120;
   int right_x = Display::get_width()/2 + 120;

reply via email to

[Prev in Thread] Current Thread [Next in Thread]