gosu 2.0.0.pre6 → 2.0.0.pre7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/dependencies/SDL/include/SDL_assert.h +2 -0
- data/dependencies/SDL/include/SDL_hints.h +11 -0
- data/dependencies/SDL/include/SDL_render.h +1 -1
- data/dependencies/SDL/include/SDL_revision.h +2 -2
- data/dependencies/SDL/include/SDL_version.h +1 -1
- data/dependencies/SDL/lib/x64/libSDL2.dll.a +0 -0
- data/dependencies/SDL/lib/x86/libSDL2.dll.a +0 -0
- data/ext/gosu-ffi/gosu-ffi.def +1 -0
- data/ffi/Gosu_FFI_internal.h +2 -2
- data/ffi/Gosu_Image.cpp +26 -14
- data/ffi/Gosu_Image.h +8 -2
- data/include/Gosu/Image.hpp +1 -1
- data/lib/SDL2.dll +0 -0
- data/lib/gosu/ffi.rb +2 -1
- data/lib/gosu/image.rb +31 -19
- data/lib64/SDL2.dll +0 -0
- data/src/BinPacker.cpp +1 -1
- data/src/ClipRectStack.cpp +38 -0
- data/src/ClipRectStack.hpp +17 -83
- data/src/DrawOp.hpp +0 -5
- data/src/DrawOpQueue.hpp +24 -30
- data/src/GosuGLView.cpp +1 -7
- data/src/Graphics.cpp +8 -5
- data/src/GraphicsImpl.hpp +0 -23
- data/src/RenderState.hpp +25 -38
- metadata +4 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: de41d69b5cfd72bea1af496ef95e39cf80d89268d640548c73aeb421d9b05428
         | 
| 4 | 
            +
              data.tar.gz: d2196d8e0a7f65e9c0d77fdfe5c56026570a807a15b4c46a7066c16bc296fcb0
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: c809f58dd0e31ec02bd3c596e2dab1de6795d70eee53aa5226389815f8b37089289055222ed3f1a4eed3a1f2e4952e452a42042a14385e97737007adbf1dff78
         | 
| 7 | 
            +
              data.tar.gz: 744c254d6ad35c6ceb9acbda0ac26d1d6f4531df389b38c13afea1775bf271be65941076fdc40d707c55a1c1a8a6ac3ae6ed95231c0a7de5bd11dc041bc0cce8
         | 
| @@ -55,6 +55,8 @@ assert can have unique static variables associated with it. | |
| 55 55 | 
             
                #define SDL_TriggerBreakpoint() __builtin_debugtrap()
         | 
| 56 56 | 
             
            #elif ( (!defined(__NACL__)) && ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))) )
         | 
| 57 57 | 
             
                #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" )
         | 
| 58 | 
            +
            #elif (defined(__GNUC__) || defined(__clang__)) && defined(__riscv)
         | 
| 59 | 
            +
                #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "ebreak\n\t" )
         | 
| 58 60 | 
             
            #elif ( defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__)) )  /* this might work on other ARM targets, but this is a known quantity... */
         | 
| 59 61 | 
             
                #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #22\n\t" )
         | 
| 60 62 | 
             
            #elif defined(__APPLE__) && defined(__arm__)
         | 
| @@ -1474,6 +1474,17 @@ extern "C" { | |
| 1474 1474 | 
             
             */
         | 
| 1475 1475 | 
             
            #define SDL_HINT_RENDER_VSYNC               "SDL_RENDER_VSYNC"
         | 
| 1476 1476 |  | 
| 1477 | 
            +
            /**
         | 
| 1478 | 
            +
             *  \brief  A variable controlling whether the Metal render driver select low power device over default one
         | 
| 1479 | 
            +
             *
         | 
| 1480 | 
            +
             *  This variable can be set to the following values:
         | 
| 1481 | 
            +
             *    "0"       - Use the prefered OS device
         | 
| 1482 | 
            +
             *    "1"       - Select a low power one
         | 
| 1483 | 
            +
             *
         | 
| 1484 | 
            +
             *  By default the prefered OS device is used.
         | 
| 1485 | 
            +
             */
         | 
| 1486 | 
            +
            #define SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE "SDL_RENDER_METAL_PREFER_LOW_POWER_DEVICE"
         | 
| 1487 | 
            +
             | 
| 1477 1488 | 
             
            /**
         | 
| 1478 1489 | 
             
             *  \brief  A variable controlling if VSYNC is automatically disable if doesn't reach the enough FPS
         | 
| 1479 1490 | 
             
             *
         | 
| @@ -1890,7 +1890,7 @@ extern DECLSPEC void *SDLCALL SDL_RenderGetMetalLayer(SDL_Renderer * renderer); | |
| 1890 1890 | 
             
             * Note that as of SDL 2.0.18, this will return NULL if Metal refuses to give
         | 
| 1891 1891 | 
             
             * SDL a drawable to render to, which might happen if the window is
         | 
| 1892 1892 | 
             
             * hidden/minimized/offscreen. This doesn't apply to command encoders for
         | 
| 1893 | 
            -
             * render targets, just the window's  | 
| 1893 | 
            +
             * render targets, just the window's backbuffer. Check your return values!
         | 
| 1894 1894 | 
             
             *
         | 
| 1895 1895 | 
             
             * \param renderer The renderer to query
         | 
| 1896 1896 | 
             
             * \returns an `id<MTLRenderCommandEncoder>` on success, or NULL if the
         | 
| @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            /* Generated by updaterev.sh, do not edit */
         | 
| 2 2 | 
             
            #ifdef SDL_VENDOR_INFO
         | 
| 3 | 
            -
            #define SDL_REVISION "SDL-release-2.28. | 
| 3 | 
            +
            #define SDL_REVISION "SDL-release-2.28.3-0-g8a5ba43d0 (" SDL_VENDOR_INFO ")"
         | 
| 4 4 | 
             
            #else
         | 
| 5 | 
            -
            #define SDL_REVISION "SDL-release-2.28. | 
| 5 | 
            +
            #define SDL_REVISION "SDL-release-2.28.3-0-g8a5ba43d0"
         | 
| 6 6 | 
             
            #endif
         | 
| 7 7 | 
             
            #define SDL_REVISION_NUMBER 0
         | 
| Binary file | 
| Binary file | 
    
        data/ext/gosu-ffi/gosu-ffi.def
    CHANGED
    
    
    
        data/ffi/Gosu_FFI_internal.h
    CHANGED
    
    | @@ -26,7 +26,7 @@ auto Gosu_translate_exceptions(Functor functor) | |
| 26 26 | 
             
                }
         | 
| 27 27 | 
             
            }
         | 
| 28 28 |  | 
| 29 | 
            -
            // C-compatible wrapper structs for Gosu classes
         | 
| 29 | 
            +
            // C-compatible wrapper structs for Gosu classes. (No inheritance because of missing virtual dtors.)
         | 
| 30 30 |  | 
| 31 31 | 
             
            struct Gosu_Channel
         | 
| 32 32 | 
             
            {
         | 
| @@ -48,7 +48,7 @@ struct Gosu_Sample | |
| 48 48 | 
             
                Gosu::Sample sample;
         | 
| 49 49 | 
             
            };
         | 
| 50 50 |  | 
| 51 | 
            -
            // Use inheritance where composition is not feasible
         | 
| 51 | 
            +
            // Use inheritance where composition is not feasible (because we want to compare pointers).
         | 
| 52 52 |  | 
| 53 53 | 
             
            struct Gosu_Song : Gosu::Song
         | 
| 54 54 | 
             
            {
         | 
    
        data/ffi/Gosu_Image.cpp
    CHANGED
    
    | @@ -2,9 +2,18 @@ | |
| 2 2 | 
             
            #include <cstring> // for std::memcpy
         | 
| 3 3 |  | 
| 4 4 | 
             
            GOSU_FFI_API Gosu_Image* Gosu_Image_create(const char* filename, unsigned image_flags)
         | 
| 5 | 
            +
            {
         | 
| 6 | 
            +
                return Gosu_translate_exceptions([=] { //
         | 
| 7 | 
            +
                    return new Gosu_Image { Gosu::Image(filename, image_flags) };
         | 
| 8 | 
            +
                });
         | 
| 9 | 
            +
            }
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_rect(const char* filename, //
         | 
| 12 | 
            +
                                                            int x, int y, int width, int height,
         | 
| 13 | 
            +
                                                            unsigned image_flags)
         | 
| 5 14 | 
             
            {
         | 
| 6 15 | 
             
                return Gosu_translate_exceptions([=] {
         | 
| 7 | 
            -
                    return new Gosu_Image{Gosu::Image | 
| 16 | 
            +
                    return new Gosu_Image { Gosu::Image(filename, { x, y, width, height }, image_flags) };
         | 
| 8 17 | 
             
                });
         | 
| 9 18 | 
             
            }
         | 
| 10 19 |  | 
| @@ -32,32 +41,35 @@ GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_text(const char* text, const cha | |
| 32 41 | 
             
                });
         | 
| 33 42 | 
             
            }
         | 
| 34 43 |  | 
| 35 | 
            -
            GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_blob(void* blob,  | 
| 36 | 
            -
                                                                 int rows,  | 
| 44 | 
            +
            GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_blob(void* blob, size_t byte_count, //
         | 
| 45 | 
            +
                                                                 int columns, int rows, //
         | 
| 46 | 
            +
                                                                 int x, int y, int width, int height,
         | 
| 47 | 
            +
                                                                 unsigned image_flags)
         | 
| 37 48 | 
             
            {
         | 
| 38 49 | 
             
                return Gosu_translate_exceptions([=] {
         | 
| 39 | 
            -
                     | 
| 40 | 
            -
                    Gosu::Bitmap bitmap | 
| 50 | 
            +
                    const int pixels = columns * rows * 4;
         | 
| 51 | 
            +
                    Gosu::Bitmap bitmap;
         | 
| 41 52 |  | 
| 42 | 
            -
                    if (byte_count ==  | 
| 53 | 
            +
                    if (byte_count == pixels) {
         | 
| 43 54 | 
             
                        // 32 bit per pixel, assume R8G8B8A8
         | 
| 44 | 
            -
                         | 
| 55 | 
            +
                        bitmap = Gosu::Bitmap(columns, rows, Gosu::Buffer(blob, byte_count, nullptr));
         | 
| 45 56 | 
             
                    }
         | 
| 46 | 
            -
                    else if (byte_count ==  | 
| 47 | 
            -
                         | 
| 57 | 
            +
                    else if (byte_count == pixels * 4UL * sizeof(float)) {
         | 
| 58 | 
            +
                        bitmap.resize(columns, rows);
         | 
| 59 | 
            +
                        // 128 bit per channel, assume float/float/float/float RGBA - for Texplay compatibility.
         | 
| 48 60 | 
             
                        const float* in = static_cast<const float*>(blob);
         | 
| 49 61 | 
             
                        Gosu::Color::Channel* out = reinterpret_cast<Gosu::Color::Channel*>(bitmap.data());
         | 
| 50 | 
            -
                        for (std::size_t i = 0; i <  | 
| 62 | 
            +
                        for (std::size_t i = 0; i < pixels; ++i) {
         | 
| 51 63 | 
             
                            out[i] = static_cast<Gosu::Color::Channel>(in[i] * 255);
         | 
| 52 64 | 
             
                        }
         | 
| 53 65 | 
             
                    }
         | 
| 54 66 | 
             
                    else {
         | 
| 55 | 
            -
                        throw std::invalid_argument | 
| 56 | 
            -
                                                    "for image of size " + std::to_string(columns) + "x" | 
| 57 | 
            -
                                                    std::to_string(rows) | 
| 67 | 
            +
                        throw std::invalid_argument("Invalid byte_count " + std::to_string(byte_count)
         | 
| 68 | 
            +
                                                    + " for image of size " + std::to_string(columns) + "x"
         | 
| 69 | 
            +
                                                    + std::to_string(rows));
         | 
| 58 70 | 
             
                    }
         | 
| 59 71 |  | 
| 60 | 
            -
                    return new Gosu_Image{Gosu::Image | 
| 72 | 
            +
                    return new Gosu_Image { Gosu::Image(bitmap, { x, y, width, height }, image_flags) };
         | 
| 61 73 | 
             
                });
         | 
| 62 74 | 
             
            }
         | 
| 63 75 |  | 
    
        data/ffi/Gosu_Image.h
    CHANGED
    
    | @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            #pragma once
         | 
| 2 2 |  | 
| 3 3 | 
             
            #include "Gosu_FFI.h"
         | 
| 4 | 
            +
            #include <stddef.h> // for size_t
         | 
| 4 5 | 
             
            #include <stdint.h>
         | 
| 5 6 |  | 
| 6 7 | 
             
            typedef struct Gosu_Image Gosu_Image;
         | 
| @@ -13,8 +14,13 @@ typedef struct Gosu_GLTexInfo | |
| 13 14 |  | 
| 14 15 | 
             
            // Constructor
         | 
| 15 16 | 
             
            GOSU_FFI_API Gosu_Image* Gosu_Image_create(const char* filename, unsigned image_flags);
         | 
| 16 | 
            -
            GOSU_FFI_API Gosu_Image*  | 
| 17 | 
            -
             | 
| 17 | 
            +
            GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_rect(const char* filename, //
         | 
| 18 | 
            +
                                                            int x, int y, int width, int height,
         | 
| 19 | 
            +
                                                            unsigned image_flags);
         | 
| 20 | 
            +
            GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_blob(void* blob, size_t byte_count, //
         | 
| 21 | 
            +
                                                                 int columns, int rows, //
         | 
| 22 | 
            +
                                                                 int x, int y, int width, int height,
         | 
| 23 | 
            +
                                                                 unsigned image_flags);
         | 
| 18 24 | 
             
            GOSU_FFI_API Gosu_Image* Gosu_Image_create_from_markup(const char* markup, const char* font,
         | 
| 19 25 | 
             
                                                                   double font_height, int width,
         | 
| 20 26 | 
             
                                                                   double spacing, unsigned align,
         | 
    
        data/include/Gosu/Image.hpp
    CHANGED
    
    | @@ -24,7 +24,7 @@ namespace Gosu | |
| 24 24 | 
             
                    /// For more flexibility, use the corresponding constructor that uses a Bitmap object.
         | 
| 25 25 | 
             
                    explicit Image(const std::string& filename, unsigned image_flags = IF_SMOOTH);
         | 
| 26 26 |  | 
| 27 | 
            -
                     | 
| 27 | 
            +
                    /// Loads a portion of the the image at the given filename..
         | 
| 28 28 | 
             
                    ///
         | 
| 29 29 | 
             
                    /// A color key of #ff00ff is automatically applied to BMP image files.
         | 
| 30 30 | 
             
                    /// For more flexibility, use the corresponding constructor that uses a Bitmap object.
         | 
    
        data/lib/SDL2.dll
    CHANGED
    
    | Binary file | 
    
        data/lib/gosu/ffi.rb
    CHANGED
    
    | @@ -134,11 +134,12 @@ module GosuFFI | |
| 134 134 | 
             
              attach_function :Gosu_Font_set_image, [:pointer, :string, :uint32, :pointer], :void
         | 
| 135 135 |  | 
| 136 136 | 
             
              attach_function :Gosu_Image_create, [:string, :uint32], :pointer
         | 
| 137 | 
            +
              attach_function :Gosu_Image_create_from_rect, [:string, :int, :int, :int, :int, :uint32], :pointer
         | 
| 137 138 | 
             
              attach_function :Gosu_Image_destroy, [:pointer], :void
         | 
| 138 139 |  | 
| 139 140 | 
             
              attach_function :Gosu_Image_create_from_markup, [:string, :string, :double, :int, :double, :uint32, :uint32, :uint32], :pointer
         | 
| 140 141 | 
             
              attach_function :Gosu_Image_create_from_text, [:string, :string, :double, :int, :double, :uint32, :uint32, :uint32], :pointer
         | 
| 141 | 
            -
              attach_function :Gosu_Image_create_from_blob, [:pointer, : | 
| 142 | 
            +
              attach_function :Gosu_Image_create_from_blob, [:pointer, :size_t, :int, :int, :int, :int, :int, :int, :uint32], :pointer
         | 
| 142 143 | 
             
              attach_function :Gosu_Image_create_from_subimage, [:pointer, :int, :int, :int, :int], :pointer
         | 
| 143 144 | 
             
              attach_function :Gosu_Image_create_from_tiles, [:string, :int, :int, :_callback_with_image, :pointer, :uint32], :void
         | 
| 144 145 | 
             
              attach_function :Gosu_Image_create_tiles_from_image, [:pointer, :int, :int, :_callback_with_image, :pointer, :uint32], :void
         | 
    
        data/lib/gosu/image.rb
    CHANGED
    
    | @@ -1,9 +1,8 @@ | |
| 1 1 | 
             
            module Gosu
         | 
| 2 2 | 
             
              class Image
         | 
| 3 | 
            -
                BlobHelper = Struct.new(:columns, :rows, :to_blob)
         | 
| 4 | 
            -
             | 
| 5 3 | 
             
                def self.from_blob(width, height, rgba = "\0\0\0\0" * (width * height), retro: false, tileable: false)
         | 
| 6 | 
            -
                   | 
| 4 | 
            +
                  @struct ||= Struct.new(:columns, :rows, :to_blob)
         | 
| 5 | 
            +
                  self.new(@struct.new(width, height, rgba), retro: retro, tileable: tileable)
         | 
| 7 6 | 
             
                end
         | 
| 8 7 |  | 
| 9 8 | 
             
                def self.from_text(markup, line_height, font: Gosu.default_font_name, width: -1, spacing: 0, align: :left,
         | 
| @@ -48,25 +47,38 @@ module Gosu | |
| 48 47 | 
             
                  return images
         | 
| 49 48 | 
             
                end
         | 
| 50 49 |  | 
| 51 | 
            -
                def initialize(object, retro: false, tileable: false)
         | 
| 50 | 
            +
                def initialize(object, retro: false, tileable: false, rect: nil)
         | 
| 51 | 
            +
                  if rect and rect.size != 4
         | 
| 52 | 
            +
                    raise ArgumentError, "Expected 4-element array as rect"
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  flags = GosuFFI.image_flags(retro: retro, tileable: tileable)
         | 
| 56 | 
            +
             | 
| 52 57 | 
             
                  if object.is_a? String
         | 
| 53 | 
            -
                     | 
| 58 | 
            +
                    if rect
         | 
| 59 | 
            +
                      __image = GosuFFI.Gosu_Image_create_from_rect(object, *rect, flags)
         | 
| 60 | 
            +
                    else
         | 
| 61 | 
            +
                      __image = GosuFFI.Gosu_Image_create(object, flags)
         | 
| 62 | 
            +
                    end
         | 
| 54 63 | 
             
                    GosuFFI.check_last_error
         | 
| 55 64 | 
             
                  elsif object.is_a?(FFI::Pointer)
         | 
| 56 65 | 
             
                    __image = object
         | 
| 57 | 
            -
                  elsif object.respond_to?(:to_blob)  | 
| 58 | 
            -
                        object.respond_to?(:columns)  | 
| 66 | 
            +
                  elsif object.respond_to?(:to_blob) and
         | 
| 67 | 
            +
                        object.respond_to?(:columns) and
         | 
| 59 68 | 
             
                        object.respond_to?(:rows)
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                     | 
| 62 | 
            -
                      blob.write_array_of_type(:uchar, :put_uchar, blob_bytes)
         | 
| 63 | 
            -
                      __image = GosuFFI.Gosu_Image_create_from_blob(blob, blob_bytes.size, object.columns, object.rows, GosuFFI.image_flags(retro: retro, tileable: tileable))
         | 
| 64 | 
            -
                      GosuFFI.check_last_error
         | 
| 65 | 
            -
                    end
         | 
| 69 | 
            +
                  
         | 
| 70 | 
            +
                    blob = object.to_blob { self.format = "RGBA"; self.depth = 8 }
         | 
| 66 71 |  | 
| 67 | 
            -
                     | 
| 72 | 
            +
                    # This creates a copy of the Ruby string data, which shouldn't be necessary with CRuby.
         | 
| 73 | 
            +
                    ptr = FFI::MemoryPointer.from_string(blob)
         | 
| 74 | 
            +
                    rect ||= [0, 0, object.columns, object.rows]
         | 
| 75 | 
            +
                    # Do not consider the terminating null byte part of the ptr length.
         | 
| 76 | 
            +
                    __image = GosuFFI.Gosu_Image_create_from_blob(ptr, ptr.size - 1, object.columns, object.rows, *rect, flags)
         | 
| 77 | 
            +
                    ptr.free
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                    GosuFFI.check_last_error
         | 
| 68 80 | 
             
                  else
         | 
| 69 | 
            -
                    raise ArgumentError
         | 
| 81 | 
            +
                    raise ArgumentError, "Expected String or RMagick::Image (or a type compatible with it)"
         | 
| 70 82 | 
             
                  end
         | 
| 71 83 |  | 
| 72 84 | 
             
                  @managed_pointer = FFI::AutoPointer.new(__image, GosuFFI.method(:Gosu_Image_destroy))
         | 
| @@ -112,17 +124,17 @@ module Gosu | |
| 112 124 | 
             
                end
         | 
| 113 125 |  | 
| 114 126 | 
             
                def subimage(left, top, width, height)
         | 
| 115 | 
            -
                   | 
| 127 | 
            +
                  __subimage = GosuFFI.Gosu_Image_create_from_subimage(__pointer, left, top, width, height)
         | 
| 116 128 | 
             
                  GosuFFI.check_last_error
         | 
| 117 | 
            -
                  Gosu::Image.new( | 
| 129 | 
            +
                  Gosu::Image.new(__subimage)
         | 
| 118 130 | 
             
                end
         | 
| 119 131 |  | 
| 120 132 | 
             
                def insert(image, x, y)
         | 
| 121 133 | 
             
                  image_ = nil
         | 
| 122 134 | 
             
                  if image.is_a?(Gosu::Image)
         | 
| 123 135 | 
             
                    image_ = image.__pointer
         | 
| 124 | 
            -
                  elsif image.respond_to?(:to_blob)  | 
| 125 | 
            -
                        image.respond_to?(:rows)  | 
| 136 | 
            +
                  elsif image.respond_to?(:to_blob) and
         | 
| 137 | 
            +
                        image.respond_to?(:rows) and
         | 
| 126 138 | 
             
                        image.respond_to?(:columns)
         | 
| 127 139 | 
             
                    image_ = Gosu::Image.new(image).__pointer
         | 
| 128 140 | 
             
                  else
         | 
    
        data/lib64/SDL2.dll
    CHANGED
    
    | Binary file | 
    
        data/src/BinPacker.cpp
    CHANGED
    
    | @@ -136,7 +136,7 @@ void Gosu::BinPacker::merge_neighbors(int index) | |
| 136 136 | 
             
                //   ┃ ┣━━┻━┫
         | 
| 137 137 | 
             
                //   ┗━┻━━━━┛
         | 
| 138 138 | 
             
                // In this case, the texture gets stuck in this fragmented state. We assume that this is not an
         | 
| 139 | 
            -
                // issue in practice, just like  | 
| 139 | 
            +
                // issue in practice, just like RAM fragmentation has never been problematic for us.
         | 
| 140 140 |  | 
| 141 141 | 
             
                // Merge any of the other rectangles in the list into the one with the given index if they share
         | 
| 142 142 | 
             
                // any of their four sides.
         | 
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            #include "ClipRectStack.hpp"
         | 
| 2 | 
            +
            #include <stdexcept>
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            void Gosu::ClipRectStack::clear()
         | 
| 5 | 
            +
            {
         | 
| 6 | 
            +
                m_stack.clear();
         | 
| 7 | 
            +
                m_effective_rect = std::nullopt;
         | 
| 8 | 
            +
            }
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            void Gosu::ClipRectStack::push(const Rect& rect)
         | 
| 11 | 
            +
            {
         | 
| 12 | 
            +
                m_stack.push_back(rect);
         | 
| 13 | 
            +
                if (m_effective_rect) {
         | 
| 14 | 
            +
                    m_effective_rect->clip_to(rect);
         | 
| 15 | 
            +
                }
         | 
| 16 | 
            +
                else {
         | 
| 17 | 
            +
                    m_effective_rect = rect;
         | 
| 18 | 
            +
                }
         | 
| 19 | 
            +
            }
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            void Gosu::ClipRectStack::pop()
         | 
| 22 | 
            +
            {
         | 
| 23 | 
            +
                if (m_stack.empty()) {
         | 
| 24 | 
            +
                    throw std::logic_error("ClipRectStack is empty");
         | 
| 25 | 
            +
                }
         | 
| 26 | 
            +
                m_stack.pop_back();
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                // The clip rect is the intersection of all active clip rects (if any).
         | 
| 29 | 
            +
                m_effective_rect = std::nullopt;
         | 
| 30 | 
            +
                for (const auto& rect : m_stack) {
         | 
| 31 | 
            +
                    if (m_effective_rect) {
         | 
| 32 | 
            +
                        m_effective_rect->clip_to(rect);
         | 
| 33 | 
            +
                    }
         | 
| 34 | 
            +
                    else {
         | 
| 35 | 
            +
                        m_effective_rect = rect;
         | 
| 36 | 
            +
                    }
         | 
| 37 | 
            +
                }
         | 
| 38 | 
            +
            }
         | 
    
        data/src/ClipRectStack.hpp
    CHANGED
    
    | @@ -1,90 +1,24 @@ | |
| 1 1 | 
             
            #pragma once
         | 
| 2 2 |  | 
| 3 | 
            +
            #include <Gosu/Utility.hpp>
         | 
| 3 4 | 
             
            #include "GraphicsImpl.hpp"
         | 
| 4 | 
            -
            #include < | 
| 5 | 
            +
            #include <limits>
         | 
| 6 | 
            +
            #include <optional>
         | 
| 7 | 
            +
            #include <stdexcept>
         | 
| 5 8 | 
             
            #include <vector>
         | 
| 6 9 |  | 
| 7 | 
            -
             | 
| 10 | 
            +
            namespace Gosu
         | 
| 8 11 | 
             
            {
         | 
| 9 | 
            -
                 | 
| 10 | 
            -
                bool has_effective_rect; // is effective_rect valid?
         | 
| 11 | 
            -
                ClipRect effective_rect;
         | 
| 12 | 
            -
                
         | 
| 13 | 
            -
                void update_effective_rect()
         | 
| 12 | 
            +
                class ClipRectStack
         | 
| 14 13 | 
             
                {
         | 
| 15 | 
            -
                     | 
| 16 | 
            -
                     | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
                     | 
| 20 | 
            -
                    
         | 
| 21 | 
            -
                     | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
                        result.x             = std::max(result.x, rect.x);
         | 
| 27 | 
            -
                        result.y             = std::max(result.y, rect.y);
         | 
| 28 | 
            -
                        
         | 
| 29 | 
            -
                        if (result.x >= result_right || result.y >= result_bottom) {
         | 
| 30 | 
            -
                            // We have clipped the world away!
         | 
| 31 | 
            -
                            has_effective_rect = false;
         | 
| 32 | 
            -
                            return;
         | 
| 33 | 
            -
                        }
         | 
| 34 | 
            -
                        
         | 
| 35 | 
            -
                        result.width  = result_right - result.x;
         | 
| 36 | 
            -
                        result.height = result_bottom - result.y;
         | 
| 37 | 
            -
                    }
         | 
| 38 | 
            -
                    
         | 
| 39 | 
            -
                    // On the iPhone, we may have to multiply everything by 2 for Retina displays.
         | 
| 40 | 
            -
                    // TODO: Doesn't this affect Retina Macs as well?
         | 
| 41 | 
            -
                    // TODO: This should be handled by a global transform.
         | 
| 42 | 
            -
                    int fac = clip_rect_base_factor();
         | 
| 43 | 
            -
                    result.x *= fac;
         | 
| 44 | 
            -
                    result.y *= fac;
         | 
| 45 | 
            -
                    result.width *= fac;
         | 
| 46 | 
            -
                    result.height *= fac;
         | 
| 47 | 
            -
                    
         | 
| 48 | 
            -
                    // Normal clipping.
         | 
| 49 | 
            -
                    effective_rect     = result;
         | 
| 50 | 
            -
                    has_effective_rect = true;
         | 
| 51 | 
            -
                }
         | 
| 52 | 
            -
                
         | 
| 53 | 
            -
            public:
         | 
| 54 | 
            -
                ClipRectStack()
         | 
| 55 | 
            -
                : has_effective_rect(false)
         | 
| 56 | 
            -
                {
         | 
| 57 | 
            -
                }
         | 
| 58 | 
            -
                
         | 
| 59 | 
            -
                void clear()
         | 
| 60 | 
            -
                {
         | 
| 61 | 
            -
                    stack.clear();
         | 
| 62 | 
            -
                    has_effective_rect = false;
         | 
| 63 | 
            -
                }
         | 
| 64 | 
            -
                
         | 
| 65 | 
            -
                void begin_clipping(double x, double y, double width, double height)
         | 
| 66 | 
            -
                {
         | 
| 67 | 
            -
                    ClipRect rect = { x, y, width, height };
         | 
| 68 | 
            -
                    stack.push_back(rect);
         | 
| 69 | 
            -
                    update_effective_rect();
         | 
| 70 | 
            -
                }
         | 
| 71 | 
            -
                
         | 
| 72 | 
            -
                void end_clipping()
         | 
| 73 | 
            -
                {
         | 
| 74 | 
            -
                    assert (!stack.empty());
         | 
| 75 | 
            -
                    stack.pop_back();
         | 
| 76 | 
            -
                    update_effective_rect();
         | 
| 77 | 
            -
                }
         | 
| 78 | 
            -
                
         | 
| 79 | 
            -
                const ClipRect* maybe_effective_rect() const
         | 
| 80 | 
            -
                {
         | 
| 81 | 
            -
                    return has_effective_rect ? &effective_rect : 0;
         | 
| 82 | 
            -
                }
         | 
| 83 | 
            -
                
         | 
| 84 | 
            -
                bool clipped_world_away() const
         | 
| 85 | 
            -
                {
         | 
| 86 | 
            -
                    // When we have no effective rect but the stack is not empty, we have clipped
         | 
| 87 | 
            -
                    // the whole world away and don't need to render things.
         | 
| 88 | 
            -
                    return !has_effective_rect && !stack.empty();
         | 
| 89 | 
            -
                }
         | 
| 90 | 
            -
            };
         | 
| 14 | 
            +
                    std::vector<Rect> m_stack;
         | 
| 15 | 
            +
                    std::optional<Rect> m_effective_rect;
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                public:
         | 
| 18 | 
            +
                    void clear();
         | 
| 19 | 
            +
                    void push(const Rect& rect);
         | 
| 20 | 
            +
                    void pop();
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    const std::optional<Rect>& effective_rect() const { return m_effective_rect; }
         | 
| 23 | 
            +
                };
         | 
| 24 | 
            +
            }
         | 
    
        data/src/DrawOp.hpp
    CHANGED
    
    
    
        data/src/DrawOpQueue.hpp
    CHANGED
    
    | @@ -9,6 +9,7 @@ | |
| 9 9 | 
             
            #include <cmath>
         | 
| 10 10 | 
             
            #include <functional>
         | 
| 11 11 | 
             
            #include <map>
         | 
| 12 | 
            +
            #include <utility>
         | 
| 12 13 | 
             
            #include <vector>
         | 
| 13 14 |  | 
| 14 15 | 
             
            class Gosu::DrawOpQueue
         | 
| @@ -22,7 +23,7 @@ class Gosu::DrawOpQueue | |
| 22 23 | 
             
                std::vector<std::function<void ()>> gl_blocks;
         | 
| 23 24 |  | 
| 24 25 | 
             
            public:
         | 
| 25 | 
            -
                DrawOpQueue(QueueMode mode)
         | 
| 26 | 
            +
                explicit DrawOpQueue(QueueMode mode)
         | 
| 26 27 | 
             
                : queue_mode(mode)
         | 
| 27 28 | 
             
                {
         | 
| 28 29 | 
             
                }
         | 
| @@ -34,39 +35,31 @@ public: | |
| 34 35 |  | 
| 35 36 | 
             
                void schedule_draw_op(DrawOp op)
         | 
| 36 37 | 
             
                {
         | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
                #ifdef GOSU_IS_OPENGLES
         | 
| 38 | 
            +
            #ifdef GOSU_IS_OPENGLES
         | 
| 40 39 | 
             
                    // No triangles, no lines supported
         | 
| 41 | 
            -
                    assert | 
| 42 | 
            -
             | 
| 40 | 
            +
                    assert(op.vertices_or_block_index == 4);
         | 
| 41 | 
            +
            #endif
         | 
| 43 42 |  | 
| 44 43 | 
             
                    op.render_state.transform = &transform_stack.current();
         | 
| 45 | 
            -
                     | 
| 46 | 
            -
                        op.render_state.clip_rect = *cr;
         | 
| 47 | 
            -
                    }
         | 
| 44 | 
            +
                    op.render_state.clip_rect = clip_rect_stack.effective_rect();
         | 
| 48 45 | 
             
                    ops.push_back(op);
         | 
| 49 46 | 
             
                }
         | 
| 50 47 |  | 
| 51 48 | 
             
                void gl(std::function<void ()> gl_block, ZPos z)
         | 
| 52 49 | 
             
                {
         | 
| 53 | 
            -
                    // TODO: Document this case: Clipped-away GL blocks are *not* being run.
         | 
| 54 | 
            -
                    if (clip_rect_stack.clipped_world_away()) return;
         | 
| 55 | 
            -
             | 
| 56 50 | 
             
                    int complement_of_block_index = ~(int)gl_blocks.size();
         | 
| 57 | 
            -
                    gl_blocks.push_back(gl_block);
         | 
| 51 | 
            +
                    gl_blocks.push_back(std::move(gl_block));
         | 
| 58 52 |  | 
| 59 53 | 
             
                    DrawOp op;
         | 
| 60 54 | 
             
                    op.vertices_or_block_index = complement_of_block_index;
         | 
| 61 55 | 
             
                    op.render_state.transform = &transform_stack.current();
         | 
| 62 | 
            -
                     | 
| 63 | 
            -
                        op.render_state.clip_rect = *cr;
         | 
| 64 | 
            -
                    }
         | 
| 56 | 
            +
                    op.render_state.clip_rect = clip_rect_stack.effective_rect();
         | 
| 65 57 | 
             
                    op.z = z;
         | 
| 66 58 | 
             
                    ops.push_back(op);
         | 
| 67 59 | 
             
                }
         | 
| 68 60 |  | 
| 69 | 
            -
                void begin_clipping(double x, double y, double width, double height, | 
| 61 | 
            +
                void begin_clipping(double x, double y, double width, double height,
         | 
| 62 | 
            +
                                    std::optional<int> viewport_height)
         | 
| 70 63 | 
             
                {
         | 
| 71 64 | 
             
                    if (mode() == QM_RECORD_MACRO) {
         | 
| 72 65 | 
             
                        throw std::logic_error("Clipping is not allowed while creating a macro");
         | 
| @@ -80,21 +73,21 @@ public: | |
| 80 73 | 
             
                    transform_stack.current().apply(left, top);
         | 
| 81 74 | 
             
                    transform_stack.current().apply(right, bottom);
         | 
| 82 75 |  | 
| 83 | 
            -
                     | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 76 | 
            +
                    Rect clip_rect {
         | 
| 77 | 
            +
                        .x = static_cast<int>(std::min(left, right)),
         | 
| 78 | 
            +
                        .y = static_cast<int>(std::min(top, bottom)),
         | 
| 79 | 
            +
                        .width = static_cast<int>(std::abs(left - right)),
         | 
| 80 | 
            +
                        .height = static_cast<int>(std::abs(top - bottom)),
         | 
| 81 | 
            +
                    };
         | 
| 88 82 | 
             
                    // Adjust for OpenGL having the wrong idea of where y=0 is.
         | 
| 89 | 
            -
                     | 
| 83 | 
            +
                    if (viewport_height && mode() == QM_RENDER_TO_SCREEN) {
         | 
| 84 | 
            +
                        clip_rect.y = *viewport_height - clip_rect.y - clip_rect.height;
         | 
| 85 | 
            +
                    }
         | 
| 90 86 |  | 
| 91 | 
            -
                    clip_rect_stack. | 
| 87 | 
            +
                    clip_rect_stack.push(clip_rect);
         | 
| 92 88 | 
             
                }
         | 
| 93 89 |  | 
| 94 | 
            -
                void end_clipping()
         | 
| 95 | 
            -
                {
         | 
| 96 | 
            -
                    clip_rect_stack.end_clipping();
         | 
| 97 | 
            -
                }
         | 
| 90 | 
            +
                void end_clipping() { clip_rect_stack.pop(); }
         | 
| 98 91 |  | 
| 99 92 | 
             
                void set_base_transform(const Transform& base_transform)
         | 
| 100 93 | 
             
                {
         | 
| @@ -118,7 +111,8 @@ public: | |
| 118 111 | 
             
                    }
         | 
| 119 112 |  | 
| 120 113 | 
             
                    // Apply Z-Ordering.
         | 
| 121 | 
            -
                    std::stable_sort(ops.begin(), ops.end() | 
| 114 | 
            +
                    std::stable_sort(ops.begin(), ops.end(),
         | 
| 115 | 
            +
                                     [](const DrawOp& lhs, const DrawOp& rhs) { return lhs.z < rhs.z; });
         | 
| 122 116 |  | 
| 123 117 | 
             
                    RenderStateManager manager;
         | 
| 124 118 |  | 
| @@ -156,7 +150,7 @@ public: | |
| 156 150 | 
             
                        throw std::logic_error("Custom OpenGL code cannot be recorded as a macro");
         | 
| 157 151 | 
             
                    }
         | 
| 158 152 |  | 
| 159 | 
            -
                    std::stable_sort(ops.begin(), ops.end());
         | 
| 153 | 
            +
                    std::stable_sort(ops.begin(), ops.end(), [](const DrawOp& lhs, const DrawOp& rhs) { return lhs.z < rhs.z; });
         | 
| 160 154 | 
             
                    for (const auto& op : ops) {
         | 
| 161 155 | 
             
                        op.compile_to(vas);
         | 
| 162 156 | 
             
                    }
         | 
    
        data/src/GosuGLView.cpp
    CHANGED
    
    | @@ -28,12 +28,6 @@ namespace Gosu | |
| 28 28 | 
             
                {
         | 
| 29 29 | 
             
                    // Don't bother unsetting anything.
         | 
| 30 30 | 
             
                }
         | 
| 31 | 
            -
                
         | 
| 32 | 
            -
                int clip_rect_base_factor()
         | 
| 33 | 
            -
                {
         | 
| 34 | 
            -
                    static int result = [UIScreen mainScreen].scale;
         | 
| 35 | 
            -
                    return result;
         | 
| 36 | 
            -
                }
         | 
| 37 31 | 
             
            }
         | 
| 38 32 |  | 
| 39 33 | 
             
            @implementation GosuGLView
         | 
| @@ -97,7 +91,7 @@ namespace Gosu | |
| 97 91 | 
             
                [EAGLContext setCurrentContext:_context];
         | 
| 98 92 | 
             
                [self destroyFramebuffer];
         | 
| 99 93 | 
             
                [self createFramebuffer];
         | 
| 100 | 
            -
                self.contentScaleFactor =  | 
| 94 | 
            +
                self.contentScaleFactor = [UIScreen mainScreen].scale;
         | 
| 101 95 | 
             
            }
         | 
| 102 96 |  | 
| 103 97 | 
             
            - (BOOL)createFramebuffer
         | 
    
        data/src/Graphics.cpp
    CHANGED
    
    | @@ -247,17 +247,20 @@ void Gosu::gl(Gosu::ZPos z, const std::function<void()>& f) | |
| 247 247 | 
             
            #endif
         | 
| 248 248 | 
             
            }
         | 
| 249 249 |  | 
| 250 | 
            -
            void Gosu::clip_to(double x, double y, double width, double height,
         | 
| 251 | 
            -
                                         const std::function<void()>& f)
         | 
| 250 | 
            +
            void Gosu::clip_to(double x, double y, double width, double height, const std::function<void()>& f)
         | 
| 252 251 | 
             
            {
         | 
| 253 | 
            -
                 | 
| 254 | 
            -
                 | 
| 252 | 
            +
                std::optional<int> viewport_height;
         | 
| 253 | 
            +
                if (current_viewport_pointer) {
         | 
| 254 | 
            +
                    viewport_height = current_viewport_pointer->m_impl->phys_height;
         | 
| 255 | 
            +
                }
         | 
| 256 | 
            +
             | 
| 257 | 
            +
                current_queue().begin_clipping(x, y, width, height, viewport_height);
         | 
| 255 258 | 
             
                f();
         | 
| 256 259 | 
             
                current_queue().end_clipping();
         | 
| 257 260 | 
             
            }
         | 
| 258 261 |  | 
| 259 262 | 
             
            Gosu::Image Gosu::render(int width, int height, const std::function<void()>& f,
         | 
| 260 | 
            -
             | 
| 263 | 
            +
                                     unsigned image_flags)
         | 
| 261 264 | 
             
            {
         | 
| 262 265 | 
             
                const OpenGLContext current_context;
         | 
| 263 266 |  | 
    
        data/src/GraphicsImpl.hpp
    CHANGED
    
    | @@ -13,23 +13,6 @@ namespace Gosu | |
| 13 13 | 
             
                struct RenderState;
         | 
| 14 14 | 
             
                class RenderStateManager;
         | 
| 15 15 |  | 
| 16 | 
            -
                const unsigned NO_CLIPPING = 0xffffffff;
         | 
| 17 | 
            -
             | 
| 18 | 
            -
                // In various places in Gosu, width==NO_CLIPPING by convention means
         | 
| 19 | 
            -
                // that no clipping should happen.
         | 
| 20 | 
            -
                struct ClipRect
         | 
| 21 | 
            -
                {
         | 
| 22 | 
            -
                    double x, y, width, height;
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                    bool operator==(const ClipRect& other) const
         | 
| 25 | 
            -
                    {
         | 
| 26 | 
            -
                        // No clipping
         | 
| 27 | 
            -
                        return (width == NO_CLIPPING && other.width == NO_CLIPPING) ||
         | 
| 28 | 
            -
                            // Clipping, but same
         | 
| 29 | 
            -
                            (x == other.x && y == other.y && width == other.width && height == other.height);
         | 
| 30 | 
            -
                    }
         | 
| 31 | 
            -
                };
         | 
| 32 | 
            -
             | 
| 33 16 | 
             
                enum QueueMode
         | 
| 34 17 | 
             
                {
         | 
| 35 18 | 
             
                    QM_RENDER_TO_SCREEN,
         | 
| @@ -71,12 +54,6 @@ namespace Gosu | |
| 71 54 |  | 
| 72 55 | 
             
                void schedule_draw_op(const DrawOp& op);
         | 
| 73 56 |  | 
| 74 | 
            -
            #ifdef GOSU_IS_IPHONE
         | 
| 75 | 
            -
                int clip_rect_base_factor();
         | 
| 76 | 
            -
            #else
         | 
| 77 | 
            -
                inline int clip_rect_base_factor() { return 1; }
         | 
| 78 | 
            -
            #endif
         | 
| 79 | 
            -
             | 
| 80 57 | 
             
                void register_frame();
         | 
| 81 58 |  | 
| 82 59 | 
             
                inline std::string escape_markup(const std::string& text) {
         | 
    
        data/src/RenderState.hpp
    CHANGED
    
    | @@ -1,9 +1,11 @@ | |
| 1 1 | 
             
            #pragma once
         | 
| 2 2 |  | 
| 3 3 | 
             
            #include <Gosu/Transform.hpp>
         | 
| 4 | 
            +
            #include "ClipRectStack.hpp"
         | 
| 4 5 | 
             
            #include "GraphicsImpl.hpp"
         | 
| 5 6 | 
             
            #include "OpenGLContext.hpp"
         | 
| 6 7 | 
             
            #include "Texture.hpp"
         | 
| 8 | 
            +
            #include <optional>
         | 
| 7 9 |  | 
| 8 10 | 
             
            // Properties that potentially need to be changed between each draw operation.
         | 
| 9 11 | 
             
            // This does not include the color or vertex data of the actual quads.
         | 
| @@ -11,13 +13,12 @@ struct Gosu::RenderState | |
| 11 13 | 
             
            {
         | 
| 12 14 | 
             
                std::shared_ptr<Texture> texture;
         | 
| 13 15 | 
             
                const Transform* transform;
         | 
| 14 | 
            -
                 | 
| 16 | 
            +
                std::optional<Rect> clip_rect;
         | 
| 15 17 | 
             
                BlendMode mode;
         | 
| 16 18 |  | 
| 17 19 | 
             
                RenderState()
         | 
| 18 20 | 
             
                : transform(0), mode(BM_DEFAULT)
         | 
| 19 21 | 
             
                {
         | 
| 20 | 
            -
                    clip_rect.width = NO_CLIPPING;
         | 
| 21 22 | 
             
                }
         | 
| 22 23 |  | 
| 23 24 | 
             
                bool operator==(const RenderState& rhs) const
         | 
| @@ -54,12 +55,12 @@ struct Gosu::RenderState | |
| 54 55 |  | 
| 55 56 | 
             
                void apply_clip_rect() const
         | 
| 56 57 | 
             
                {
         | 
| 57 | 
            -
                    if (clip_rect. | 
| 58 | 
            -
                         | 
| 58 | 
            +
                    if (clip_rect.has_value()) {
         | 
| 59 | 
            +
                        glEnable(GL_SCISSOR_TEST);
         | 
| 60 | 
            +
                        glScissor(clip_rect->x, clip_rect->y, clip_rect->width, clip_rect->height);
         | 
| 59 61 | 
             
                    }
         | 
| 60 62 | 
             
                    else {
         | 
| 61 | 
            -
                         | 
| 62 | 
            -
                        glScissor(clip_rect.x, clip_rect.y, clip_rect.width, clip_rect.height);
         | 
| 63 | 
            +
                        glDisable(GL_SCISSOR_TEST);
         | 
| 63 64 | 
             
                    }
         | 
| 64 65 | 
             
                }
         | 
| 65 66 |  | 
| @@ -76,12 +77,8 @@ struct Gosu::RenderState | |
| 76 77 |  | 
| 77 78 | 
             
            // Manages the OpenGL rendering state. It caches the current state, only forwarding the
         | 
| 78 79 | 
             
            // changes to OpenGL if the new state is really different.
         | 
| 79 | 
            -
            class Gosu::RenderStateManager : private Gosu::RenderState
         | 
| 80 | 
            +
            class Gosu::RenderStateManager : private Gosu::RenderState, private Gosu::Noncopyable
         | 
| 80 81 | 
             
            {
         | 
| 81 | 
            -
                // Not copyable
         | 
| 82 | 
            -
                RenderStateManager(const RenderStateManager&);
         | 
| 83 | 
            -
                RenderStateManager& operator=(const RenderStateManager&);
         | 
| 84 | 
            -
             | 
| 85 82 | 
             
                void apply_transform() const
         | 
| 86 83 | 
             
                {
         | 
| 87 84 | 
             
                    glMatrixMode(GL_MODELVIEW);
         | 
| @@ -110,9 +107,7 @@ public: | |
| 110 107 |  | 
| 111 108 | 
             
                ~RenderStateManager()
         | 
| 112 109 | 
             
                {
         | 
| 113 | 
            -
                     | 
| 114 | 
            -
                    no_clipping.width = NO_CLIPPING;
         | 
| 115 | 
            -
                    set_clip_rect(no_clipping);
         | 
| 110 | 
            +
                    set_clip_rect(std::nullopt);
         | 
| 116 111 | 
             
                    set_texture(std::shared_ptr<Texture>());
         | 
| 117 112 | 
             
                    // Return to previous MV matrix
         | 
| 118 113 | 
             
                    glMatrixMode(GL_MODELVIEW);
         | 
| @@ -127,9 +122,11 @@ public: | |
| 127 122 | 
             
                    set_alpha_mode(rs.mode);
         | 
| 128 123 | 
             
                }
         | 
| 129 124 |  | 
| 130 | 
            -
                void set_texture(std::shared_ptr<Texture | 
| 125 | 
            +
                void set_texture(const std::shared_ptr<Texture>& new_texture)
         | 
| 131 126 | 
             
                {
         | 
| 132 | 
            -
                    if (new_texture == texture)  | 
| 127 | 
            +
                    if (new_texture == texture) {
         | 
| 128 | 
            +
                        return;
         | 
| 129 | 
            +
                    }
         | 
| 133 130 |  | 
| 134 131 | 
             
                    if (new_texture) {
         | 
| 135 132 | 
             
                        if (!texture) {
         | 
| @@ -146,39 +143,29 @@ public: | |
| 146 143 |  | 
| 147 144 | 
             
                void set_transform(const Transform* new_transform)
         | 
| 148 145 | 
             
                {
         | 
| 149 | 
            -
                    if (new_transform == transform)  | 
| 146 | 
            +
                    if (new_transform == transform) {
         | 
| 147 | 
            +
                        return;
         | 
| 148 | 
            +
                    }
         | 
| 150 149 |  | 
| 151 150 | 
             
                    transform = new_transform;
         | 
| 152 151 | 
             
                    apply_transform();
         | 
| 153 152 | 
             
                }
         | 
| 154 153 |  | 
| 155 | 
            -
                void set_clip_rect(const  | 
| 154 | 
            +
                void set_clip_rect(const std::optional<Rect>& new_clip_rect)
         | 
| 156 155 | 
             
                {
         | 
| 157 | 
            -
                    if ( | 
| 158 | 
            -
                         | 
| 159 | 
            -
                        if (clip_rect.width != NO_CLIPPING) {
         | 
| 160 | 
            -
                            glDisable(GL_SCISSOR_TEST);
         | 
| 161 | 
            -
                            clip_rect.width = NO_CLIPPING;
         | 
| 162 | 
            -
                        }
         | 
| 163 | 
            -
                    }
         | 
| 164 | 
            -
                    else {
         | 
| 165 | 
            -
                        // Enable clipping if off
         | 
| 166 | 
            -
                        if (clip_rect.width == NO_CLIPPING) {
         | 
| 167 | 
            -
                            glEnable(GL_SCISSOR_TEST);
         | 
| 168 | 
            -
                            clip_rect = new_clip_rect;
         | 
| 169 | 
            -
                            glScissor(clip_rect.x, clip_rect.y, clip_rect.width, clip_rect.height);
         | 
| 170 | 
            -
                        }
         | 
| 171 | 
            -
                        // Adjust clipping if necessary
         | 
| 172 | 
            -
                        else if (!(clip_rect == new_clip_rect)) {
         | 
| 173 | 
            -
                            clip_rect = new_clip_rect;
         | 
| 174 | 
            -
                            glScissor(clip_rect.x, clip_rect.y, clip_rect.width, clip_rect.height);
         | 
| 175 | 
            -
                        }
         | 
| 156 | 
            +
                    if (clip_rect == new_clip_rect) {
         | 
| 157 | 
            +
                        return;
         | 
| 176 158 | 
             
                    }
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                    clip_rect = new_clip_rect;
         | 
| 161 | 
            +
                    apply_clip_rect();
         | 
| 177 162 | 
             
                }
         | 
| 178 163 |  | 
| 179 164 | 
             
                void set_alpha_mode(BlendMode new_mode)
         | 
| 180 165 | 
             
                {
         | 
| 181 | 
            -
                    if (new_mode == mode)  | 
| 166 | 
            +
                    if (new_mode == mode) {
         | 
| 167 | 
            +
                        return;
         | 
| 168 | 
            +
                    }
         | 
| 182 169 |  | 
| 183 170 | 
             
                    mode = new_mode;
         | 
| 184 171 | 
             
                    apply_alpha_mode();
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: gosu
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 2.0.0. | 
| 4 | 
            +
              version: 2.0.0.pre7
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Julian Raschke
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2023-09- | 
| 11 | 
            +
            date: 2023-09-14 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: ffi
         | 
| @@ -258,6 +258,7 @@ files: | |
| 258 258 | 
             
            - src/BitmapIO.cpp
         | 
| 259 259 | 
             
            - src/Buffer.cpp
         | 
| 260 260 | 
             
            - src/Channel.cpp
         | 
| 261 | 
            +
            - src/ClipRectStack.cpp
         | 
| 261 262 | 
             
            - src/ClipRectStack.hpp
         | 
| 262 263 | 
             
            - src/Color.cpp
         | 
| 263 264 | 
             
            - src/Directories.cpp
         | 
| @@ -336,7 +337,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 336 337 | 
             
                - !ruby/object:Gem::Version
         | 
| 337 338 | 
             
                  version: 1.3.1
         | 
| 338 339 | 
             
            requirements: []
         | 
| 339 | 
            -
            rubygems_version: 3.4. | 
| 340 | 
            +
            rubygems_version: 3.4.10
         | 
| 340 341 | 
             
            signing_key:
         | 
| 341 342 | 
             
            specification_version: 4
         | 
| 342 343 | 
             
            summary: 2D game development library.
         |