Commits

Marcus von Appen  committed 91539ff Merge

Merged in farlerrr/py-sdl2 (pull request #29)

Add logical_size property to sdl2.ext.Renderer

  • Participants
  • Parent commits 02a4bc4, 18ba763

Comments (0)

Files changed (3)

File doc/modules/sdl2ext_sprite.rst

       requires a :class:`sdl2.ext.FontManager` to be in *kwargs* or
       :attr:`default_args`.
 
-.. class:: Renderer(target : obj[, index=-1[, flags=sdl2.SDL_RENDERER_ACCELERATED]])
+.. class:: Renderer(target : obj[, logical_size=None[, index=-1[, flags=sdl2.SDL_RENDERER_ACCELERATED]])
 
    A rendering context for windows and sprites that can use hardware or
    software-accelerated graphics drivers.
 
       The target for which the :class:`Renderer` was created.
 
+   .. attribute:: logical_size
+
+      The logical size of the renderer.
+
+      Setting this allows you to draw as if your renderer had this size, even
+      though the target may be larger or smaller. When drawing, the renderer will
+      automatically scale your contents to the target, creating letter-boxing or
+      sidebars if necessary.
+
+      To reset your logical size back to the target's, set it to ``(0, 0)``.
+
+      Setting this to a lower value may be useful for low-resolution effects.
+
+      Setting this to a larger value may be useful for antialiasing.
+
    .. attribute:: color
 
       The :class:`sdl2.ext.Color` to use for draw and fill operations.

File sdl2/ext/sprite.py

 
 class Renderer(object):
     """SDL2-based renderer for windows and sprites."""
-    def __init__(self, target, index=-1,
+    def __init__(self, target, index=-1, logical_size=None,
                  flags=render.SDL_RENDERER_ACCELERATED):
         """Creates a new Renderer for the given target.
 
         else:
             raise TypeError("unsupported target type")
 
+        if logical_size is not None:
+            self.logical_size = logical_size
+
     def __del__(self):
         if self.renderer:
             render.SDL_DestroyRenderer(self.renderer)
         self.rendertarget = None
 
     @property
+    def logical_size(self):
+        """The logical pixel size of the Renderer"""
+        w, h = c_int(), c_int()
+        render.SDL_RenderGetLogicalSize(self.renderer, byref(w), byref(h))
+        return w.value, h.value
+
+    @logical_size.setter
+    def logical_size(self, size):
+        """The logical pixel size of the Renderer"""
+        width, height = size
+        ret = render.SDL_RenderSetLogicalSize(self.renderer, width, height)
+        if ret != 0:
+            raise SDLError()
+
+    @property
     def color(self):
         """The drawing color of the Renderer."""
         r, g, b, a = Uint8(), Uint8(), Uint8(), Uint8()

File sdl2/test/render_test.py

 import unittest
 from ctypes import byref, POINTER, c_int
 from .. import SDL_Init, SDL_Quit, SDL_INIT_EVERYTHING
+import itertools
 from ..stdinc import Uint8, Uint32, SDL_TRUE, SDL_FALSE
 from .. import render, video, surface, pixels, blendmode, rect
 from ..ext.pixelaccess import PixelView
     def test_SDL_RenderGetSetScale(self):
         pass
 
-    @unittest.skip("not implemented")
     def test_SDL_RenderGetSetLogicalSize(self):
-        pass
+        w, h = 100, 100
+
+        sf = surface.SDL_CreateRGBSurface(0, w, h, 32,
+                                          0xFF000000,
+                                          0x00FF0000,
+                                          0x0000FF00,
+                                          0x000000FF)
+
+        renderer = render.SDL_CreateSoftwareRenderer(sf)
+        view = PixelView(sf.contents)
+
+        magenta = 255, 0, 255, 255
+        green = 0, 255, 0, 255
+
+        magenta_int = sum(c << (i * 8) for i, c in enumerate(reversed(magenta)))
+        green_int = sum(c << (i * 8) for i, c in enumerate(reversed(green)))
+
+        def clear_green():
+            ret = render.SDL_SetRenderDrawColor(renderer, green[0], green[1], green[2], green[3])
+            self.assertEqual(ret, 0)
+            ret = render.SDL_RenderClear(renderer)
+            self.assertEqual(ret, 0)
+
+        def draw_magenta_pixel(x, y):
+            ret = render.SDL_SetRenderDrawColor(renderer, magenta[0], magenta[1], magenta[2], magenta[3])
+            self.assertEqual(ret, 0)
+
+            ret = render.SDL_RenderDrawPoint(renderer, x, y)
+            self.assertEqual(ret, 0)
+
+        # Test 1
+        # If we set the logical renderer size to 1 x 1, drawing a point at 0, 0 should have the same effect
+        # as filling the entire (square) window with magenta - no green should show through.
+        got_width, got_height = c_int(), c_int()
+
+        ret = render.SDL_RenderSetLogicalSize(renderer, 1, 1)
+        self.assertEqual(ret, 0)
+
+        render.SDL_RenderGetLogicalSize(renderer, byref(got_width), byref(got_height))
+        self.assertEqual(got_width.value, 1)
+        self.assertEqual(got_height.value, 1)
+
+        clear_green()
+        draw_magenta_pixel(0, 0)
+
+        for x, y in itertools.product(range(w), range(h)):
+            self.assertEqual(hex(view[y][x]), hex(magenta_int), 'No pixel should be green')
+
+        # Test 2
+        # Reset the logical size to the original target by using 0, 0
+        # only the first and last pixel should be magenta. The rest should be green.
+        got_width, got_height = c_int(), c_int()
+
+        ret = render.SDL_RenderSetLogicalSize(renderer, 0, 0)
+        self.assertEqual(ret, 0)
+
+        render.SDL_RenderGetLogicalSize(renderer, byref(got_width), byref(got_height))
+        self.assertEqual(got_width.value, 0)
+        self.assertEqual(got_height.value, 0)
+
+        clear_green()
+
+        draw_magenta_pixel(0, 0)
+        draw_magenta_pixel(w - 1, h - 1)
+
+        for x, y in itertools.product(range(w), range(h)):
+            if (x, y) == (0, 0) or (x, y) == (w - 1, h - 1):
+                self.assertEqual(hex(view[y][x]), hex(magenta_int), 'First and last pixel should be magenta')
+            else:
+                self.assertEqual(hex(view[y][x]), hex(green_int), 'All other pixels should be green')
+
+        # Test 3
+        # Set the logical size to 1/10, making a logical pixel draw be 10 x 10 real pixel blocks.
+        got_width, got_height = c_int(), c_int()
+
+        ret = render.SDL_RenderSetLogicalSize(renderer, w//10, h//10)
+        self.assertEqual(ret, 0)
+
+        render.SDL_RenderGetLogicalSize(renderer, byref(got_width), byref(got_height))
+        self.assertEqual(got_width.value, w//10)
+        self.assertEqual(got_height.value, h//10)
+
+        clear_green()
+
+        draw_magenta_pixel(0, 0)
+        for x, y in itertools.product(range(w), range(h)):
+            if x < 10 and y < 10:
+                self.assertEqual(hex(view[y][x]), hex(magenta_int), 'Top-left 10 x 10 pixel block should be magenta')
+            else:
+                self.assertEqual(hex(view[y][x]), hex(green_int), 'All other pixels should be green')
+
+        render.SDL_DestroyRenderer(renderer)
 
     @unittest.skip("not implemented")
     def test_SDL_RenderGetSetClipRect(self):