Class: Rubygame::Surface

Inherits:
Object
  • Object
show all
Includes:
NamedResource
Defined in:
lib/rubygame/surface.rb,
lib/rubygame/image.rb,
lib/rubygame/gfx.rb

Overview

Surface represents an image, a block of colored pixels arranged in a 2D grid. You can load image files to a new Surface with #load, or create an empty one with Surface.new and draw shapes on it with #draw_line, #draw_circle, and all the rest.

One of the most important Surface concepts is #blit, copying image data from one Surface onto another. By blitting Surfaces onto the Screen (which is a special type of Surface) and then using Screen#update, you can make images appear for the player to see.

As of Rubygame 2.3.0, Surface includes the Rubygame::NamedResource mixin module, which can perform autoloading of images on demand, among other things.

Direct Known Subclasses

Screen

Class Method Summary collapse

Instance Method Summary collapse

Methods included from NamedResource

included, #name, #name=

Constructor Details

#initialize(size, depth = 0, flags = []) ⇒ Surface

Create and initialize a new Surface object.

A Surface is a grid of image data which you blit (i.e. copy) onto other Surfaces. Since the Rubygame display is also a Surface (see the Screen class), Surfaces can be blit to the screen; this is the most common way to display images on the screen.

This method may raise SDLError if the SDL video subsystem could not be initialized for some reason.

This function takes these arguments:

size

requested surface size; an array of the form [width, height].

depth

requested color depth (in bits per pixel). If depth is 0 (default), automatically choose a color depth: either the depth of the Screen mode (if one has been set), or the greatest color depth available on the system.

flags

an Array or Bitwise-OR’d list of zero or more of the following flags (located in the Rubygame module, e.g. Rubygame::SWSURFACE). This argument may be omitted, in which case the Surface will be a normal software surface (this is not necessarily a bad thing).

SWSURFACE

(default) request a software surface.

HWSURFACE

request a hardware-accelerated surface (using a graphics card), if available. Creates a software surface if hardware surfaces are not available.

SRCCOLORKEY

request a colorkeyed surface. #set_colorkey will also enable colorkey as needed. For a description of colorkeys, see #set_colorkey.

SRCALPHA

request an alpha channel. #set_alpha will also enable alpha. as needed. For a description of alpha, see #alpha.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/rubygame/surface.rb', line 83

def initialize( size, depth=0, flags=[] )

  # Cheating a bit. First arg can be a SDL::Surface to wrap it.
  #
  if( size.kind_of? SDL::Surface )
    surf = size
    if( surf.pointer.null? )
      raise Rubygame::SDLError, "Surface cannot wrap NULL Surface!"
    else
      @struct = surf
    end
    return
  end

  unless size.kind_of? Array
    raise TypeError, "Surface size is not an Array: #{size.inspect}"
  end

  unless size.length == 2 and size.all?{ |n| n.kind_of? Numeric }
    raise ArgumentError, "Invalid Surface size: #{size.inspect}"
  end


  pixformat = nil

  vs = SDL.GetVideoSurface()

  unless( vs.pointer.null? )
    # Pixel format is retrieved from the video surface.
    pixformat = vs.format
  else
    # We can only get the system color depth when the
    # video system has been initialized.
    if( Rubygame.init_video_system == 0 )
      pixformat = SDL.GetVideoInfo().vfmt
    else
      raise(Rubygame::SDLError,
            "Could not initialize SDL video subsystem.")
    end
  end

  rmask = pixformat.Rmask
  gmask = pixformat.Gmask
  bmask = pixformat.Bmask
  amask = pixformat.Amask

  if( depth <= 0 )
    depth = pixformat.BitsPerPixel
  end

  w, h = size

  flags = Rubygame.collapse_flags(flags)

  @struct = SDL.CreateRGBSurface(flags, w, h, depth,
                                 rmask, gmask, bmask, amask)
end

Class Method Details

.autoload(name) ⇒ Object

Searches each directory in Surface.autoload_dirs for a file with the given filename. If it finds that file, loads it and returns a Surface instance. If it doesn’t find the file, returns nil.

See Rubygame::NamedResource for more information about this functionality.



38
39
40
41
42
43
44
45
46
# File 'lib/rubygame/image.rb', line 38

def autoload( name )
  path = find_file( name )

  if( path )
    return load( path )
  else
    return nil
  end
end

.load(filename) ⇒ Object

IMPORTANT: this method only exists if SDL_image is available! Your code should check “defined?(Rubygame::Surface.load) != nil” to see if you can use this method, or be prepared to rescue from NameError.

Load an image file from the disk to a Surface. If the image has an alpha channel (e.g. PNG with transparency), the Surface will as well. If the image cannot be loaded (for example if the image format is unsupported), will raise SDLError.

This method takes this argument:

filename

a string containing the relative or absolute path to the image file. The file must have the proper file extension, as it is used to determine image format.

These formats may be supported, but some may not be available on a particular system.

BMP

“Windows Bitmap” format.

GIF

“Graphics Interchange Format.”

JPG

“Independent JPEG Group” format.

LBM

“Linear Bitmap” format (?)

PCX

“PC Paintbrush” format

PNG

“Portable Network Graphics” format.

PNM

“Portable Any Map” format. (i.e., PPM, PGM, or PBM)

TGA

“Truevision TARGA” format.

TIF

“Tagged Image File Format”

XCF

“eXperimental Computing Facility” (GIMP native format).

XPM

“XPixMap” format.



78
79
80
81
82
83
84
85
86
87
# File 'lib/rubygame/image.rb', line 78

def load( filename )
  surf = SDL::Image.Load( filename )

  if( surf.pointer.null? )
    raise( Rubygame::SDLError, "Couldn't load image \"%s\": %s"%\
           [filename, SDL.GetError()] )
  end

  return self.new(surf)
end

.load_from_string(data, type = nil) ⇒ Object

IMPORTANT: this method only exists if SDL_image is available! Your code should check “defined?(Rubygame::Surface.load_from_string) != nil” to see if you can use this method, or be prepared to rescue from NameError.

Load an image file from memory (in the form of the given data) to a Surface. If the image has an alpha channel (e.g. PNG with transparency), the Surface will as well. If the image cannot be loaded (for example if the image format is unsupported), will raise SDLError.

This method takes these arguments:

data

a string containing the data for the image, such as IO::read would return.

type

The type of file that the image is (i.e. ‘TGA’). Case is not important. If absent, the library will try to automatically detect the type.

See Surface.load for a list of possible supported file types.



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/rubygame/image.rb', line 118

def load_from_string( data, type=nil )
  raw = FFI::Buffer.new(:char, data.length)
  raw.put_bytes(0, data)

  rw = SDL.RWFromMem( raw, data.length )

  surf = if type
           SDL::Image.LoadTyped_RW(rw, 1, type)
         else
           SDL::Image.Load_RW(rw, 1)
         end
  
  if surf.pointer.null?
    raise( Rubygame::SDLError,
           "Couldn't load image from string: #{SDL.GetError()}" )
  end

  return new(surf)
end

.load_image(filename) ⇒ Object

Deprecated. Use Surface.load instead!



91
92
93
94
# File 'lib/rubygame/image.rb', line 91

def load_image( filename )
  Rubygame.deprecated( "Rubygame::Surface.load_image", "3.0" )
  load( filename )
end

.rotozoom_size(size, angle, zoom) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:rotozoom_size)” to see if you can use this method, or be prepared to rescue from NameError.

Return the dimensions of the surface that would be returned if #rotozoom were called on a Surface of the given size, with the same angle and zoom factors.

This method takes these arguments:

size

an Array with the hypothetical Surface width and height (pixels)

angle

degrees to rotate counter-clockwise (negative for clockwise).

zoom

scaling factor(s). A number (to scale X and Y by the same factor) or an array of 2 numbers (to scale X and Y by different factors). NOTE: Due to a quirk in SDL_gfx, if angle is not 0, the image is zoomed by the X factor on both X and Y, and the Y factor is only used for flipping (if it’s negative).



459
460
461
462
463
464
465
466
467
468
469
470
471
472
# File 'lib/rubygame/gfx.rb', line 459

def self.rotozoom_size( size, angle, zoom )
  w, h = size

  case zoom
  when Array
    zx, zy = zoom.collect { |n| n.to_f }
    SDL::Gfx.rotozoomSurfaceSizeXY(w, h, angle, zx, zy)
  when Numeric
    zoom = zoom.to_f
    SDL::Gfx.rotozoomSurfaceSize(w, h, angle, zoom)
  else
    raise ArgumentError, "Invalid zoom factor: #{zoom.inspect}"
  end
end

.zoom_size(size, zoom) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:zoom_size)” to see if you can use this method, or be prepared to rescue from NameError.

Return the dimensions of the surface that would be returned if #zoom were called on a Surface of the given size, with the same zoom factors.

This method takes these arguments:

size

an Array with the hypothetical Surface width and height (pixels)

zoom

scaling factor(s). A number (to scale X and Y by the same factor) or an array of 2 numbers (to scale X and Y by different factors).



525
526
527
528
529
530
531
532
533
534
535
536
537
538
# File 'lib/rubygame/gfx.rb', line 525

def self.zoom_size( size, zoom )
  w, h = size

  case zoom
  when Array
    zx, zy = zoom.collect { |n| n.to_f }
    SDL::Gfx.zoomSurfaceSize(w, h, zx, zy)
  when Numeric
    zoom = zoom.to_f
    SDL::Gfx.zoomSurfaceSize(w, h, zoom, zoom)
  else
    raise ArgumentError, "Invalid zoom factor: #{zoom.inspect}"
  end
end

Instance Method Details

#alphaObject

Return the per-surface alpha (opacity; non-transparency) of the surface. It can range from 0 (full transparent) to 255 (full opaque).



200
201
202
# File 'lib/rubygame/surface.rb', line 200

def alpha
  @struct.format.alpha
end

#blit(target, pos, src_rect = nil) ⇒ Object

Blit (copy) all or part of the surface’s image to another surface, at a given position. Returns a Rect representing the area of target which was affected by the blit.

This method takes these arguments:

target

the target Surface on which to paste the image.

pos

the coordinates of the top-left corner of the blit. Affects the area of target the image data is /pasted/ over. Can also be a Rect or an Array larger than 2, but width and height will be ignored.

src_rect

a Rect representing the area of the source surface to get data from. Affects where the image data is /copied/ from. Can also be an Array of no less than 4 values.



285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/rubygame/surface.rb', line 285

def blit( target, pos, src_rect=nil )
  unless target.kind_of? Rubygame::Surface
    raise TypeError, "blit target must be a Surface"
  end

  src_x, src_y, src_w, src_h =
    case src_rect
    when SDL::Rect
      [src_rect.x, src_rect.y, src_rect.w, src_rect.h]
    when Array
      src_rect
    when nil
      [0, 0] + self.size
    end

  src_rect  = SDL::Rect.new([src_x,  src_y,  src_w, src_h])
  blit_x, blit_y = pos
  blit_rect = SDL::Rect.new([blit_x, blit_y, src_w, src_h])

  SDL.BlitSurface( @struct, src_rect, target.struct, blit_rect )

  return Rubygame::Rect.new( blit_rect.to_ary )
end

#clipObject

Return the clipping area for this Surface. See also #clip=.

The clipping area of a Surface is the only part which can be drawn upon by other Surface’s #blits. By default, the clipping area is the entire area of the Surface.



471
472
473
# File 'lib/rubygame/surface.rb', line 471

def clip
  Rubygame::Rect.new( SDL.GetClipRect(@struct).to_ary )
end

#clip=(newclip) ⇒ Object

Set the current clipping area of the Surface. See also #clip.

The clipping area of a Surface is the only part which can be drawn upon by other Surface’s #blits. The clipping area will be clipped to the edges of the surface so that the clipping area for a Surface can never fall outside the edges of the Surface.

By default, the clipping area is the entire area of the Surface. You may set clip to nil, which will reset the clipping area to cover the entire Surface.



487
488
489
490
491
492
493
494
495
496
497
498
499
# File 'lib/rubygame/surface.rb', line 487

def clip=( newclip )
  newclip = case newclip
            when nil, SDL::Rect
              newclip         # no change
            when Rubygame::Rect
              newclip.to_sdl
            when Array
              Rubygame::Rect.new(newclip).to_sdl
            end

  SDL.SetClipRect(@struct, newclip)
  return self
end

#colorkeyObject

call-seq:

colorkey  ->  [r,g,b]  or  nil

Return the colorkey of the surface in the form [r,g,b] (or nil if there is no key). The colorkey of a surface is the exact color which will be ignored when the surface is blitted, effectively turning that color transparent. This is often used to make a blue (for example) background on an image seem transparent.



235
236
237
238
239
240
241
# File 'lib/rubygame/surface.rb', line 235

def colorkey
  if( (@struct.flags & Rubygame::SRCCOLORKEY) == Rubygame::SRCCOLORKEY )
    SDL::GetRGB(@struct.format.colorkey, @struct.format)
  else
    nil
  end 
end

#convert(other = nil, flags = nil) ⇒ Object

Copies the Surface to a new Surface with the pixel format of another Surface, for fast blitting. May raise SDLError if a problem occurs.

This method takes these arguments:

other

The Surface to match pixel format against. If nil, the display surface (i.e. Screen) is used, if available; if no display surface is available, raises SDLError.

flags

An array of flags to pass when the new Surface is created. See Surface#new.



514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
# File 'lib/rubygame/surface.rb', line 514

def convert( other=nil, flags=nil )

  if other.nil?
    begin
      other = Rubygame::Screen.get_surface
    rescue Rubygame::SDLError
      raise( Rubygame::SDLError, "Cannot convert Surface with no target " +
             "given and no Screen made: #{SDL.GetError()}" )
    end
  end

  flags = Rubygame.collapse_flags(flags)

  newsurf =
    if( Rubygame.init_video_system() == 0 )
      SDL.ConvertSurface( @struct, other.struct.format, flags )
    else
      nil
    end

  if( newsurf.nil? or newsurf.pointer.null?)
    raise( Rubygame::SDLError,
           "Could not convert the Surface: #{SDL.GetError()}" )
  end

  # Wrap it
  return self.class.new( newsurf )
end

#depthObject

Return the color depth (in bits per pixel) of the surface.



171
172
173
# File 'lib/rubygame/surface.rb', line 171

def depth
  @struct.format.BitsPerPixel
end

#draw_arc(center, radius, angles, color) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:draw_arc)” to see if you can use this method, or be prepared to rescue from NameError.

Draw a non-solid arc (part of a circle), given the coordinates of its center, radius, and starting/ending angles. See also #draw_arc_s

This method takes these arguments:

center

the coordinates of circle’s center, [x,y].

radius

the radius (pixels) of the circle.

angles

the start and end angles (in degrees) of the arc, [start,end]. Angles are given CLOCKWISE from the positive x (remember that the positive Y direction is down, rather than up).

color

the color of the shape. [r,g,b] or [r,g,b,a] (0-255), color name, or Rubygame::Color.



300
301
302
303
# File 'lib/rubygame/gfx.rb', line 300

def draw_arc( center, radius, angles, color )
  _draw_arc( center, radius, angles, color, false )
  return self
end

#draw_arc_s(center, radius, angles, color) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:draw_arc_s)” to see if you can use this method, or be prepared to rescue from NameError.

Like #draw_arc, but the shape is solid, instead of an outline.



313
314
315
316
# File 'lib/rubygame/gfx.rb', line 313

def draw_arc_s( center, radius, angles, color )
  _draw_arc( center, radius, angles, color, true )
  return self
end

#draw_box(point1, point2, color) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:draw_box)” to see if you can use this method, or be prepared to rescue from NameError.

Draw a non-solid box (rectangle) on the Surface, given the coordinates of its top-left corner and bottom-right corner. See also #draw_box_s

This method takes these arguments:

point1

the coordinates of top-left corner, [x1,y1].

point2

the coordinates of bottom-right corner, [x2,y2].

color

the color of the shape. [r,g,b] or [r,g,b,a] (0-255), color name, or Rubygame::Color.



115
116
117
118
# File 'lib/rubygame/gfx.rb', line 115

def draw_box( point1, point2, color )
  _draw_box( point1, point2, color, false )
  return self
end

#draw_box_s(point1, point2, color) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:draw_box_s)” to see if you can use this method, or be prepared to rescue from NameError.

Like #draw_box, but the shape is solid, instead of an outline. (You may find using #fill to be more convenient and perhaps faster than this method.)



130
131
132
133
# File 'lib/rubygame/gfx.rb', line 130

def draw_box_s( point1, point2, color )
  _draw_box( point1, point2, color, true )
  return self
end

#draw_circle(center, radius, color) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:draw_circle)” to see if you can use this method, or be prepared to rescue from NameError.

Draw a non-solid circle on the Surface, given the coordinates of its center and its radius. See also #draw_circle_a and #draw_circle_s

This method takes these arguments:

center

the coordinates of circle’s center, [x,y].

radius

the radius (pixels) of the circle.

color

the color of the shape. [r,g,b] or [r,g,b,a] (0-255), color name, or Rubygame::Color.



169
170
171
172
# File 'lib/rubygame/gfx.rb', line 169

def draw_circle( center, radius, color )
  _draw_circle( center, radius, color, false, false )
  return self
end

#draw_circle_a(center, radius, color) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:draw_circle_a)” to see if you can use this method, or be prepared to rescue from NameError.

Like #draw_circle, but the outline is anti-aliased.



181
182
183
184
# File 'lib/rubygame/gfx.rb', line 181

def draw_circle_a( center, radius, color )
  _draw_circle( center, radius, color, true, false )
  return self
end

#draw_circle_s(center, radius, color) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:draw_circle_s)” to see if you can use this method, or be prepared to rescue from NameError.

Like #draw_circle, but the shape is solid, instead of an outline.



194
195
196
197
# File 'lib/rubygame/gfx.rb', line 194

def draw_circle_s( center, radius, color )
  _draw_circle( center, radius, color, false, true )
  return self
end

#draw_ellipse(center, radii, color) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:draw_ellipse)” to see if you can use this method, or be prepared to rescue from NameError.

Draw a non-solid ellipse (oval) on the Surface, given the coordinates of its center and its horizontal and vertical radii. See also #draw_ellipse_a and #draw_ellipse_s

This method takes these arguments:

center

the coordinates of ellipse’s center, [x,y].

radii

the x and y radii (pixels), [rx,ry].

color

the color of the shape. [r,g,b] or [r,g,b,a] (0-255), color name, or Rubygame::Color.



234
235
236
237
# File 'lib/rubygame/gfx.rb', line 234

def draw_ellipse( center, radii, color )
  _draw_ellipse( center, radii, color, false, false )
  return self
end

#draw_ellipse_a(center, radii, color) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:draw_ellipse_a)” to see if you can use this method, or be prepared to rescue from NameError.

Like #draw_ellipse, but the ellipse border is anti-aliased.



246
247
248
249
# File 'lib/rubygame/gfx.rb', line 246

def draw_ellipse_a( center, radii, color )
  _draw_ellipse( center, radii, color, true, false )
  return self
end

#draw_ellipse_s(center, radii, color) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:draw_ellipse_s)” to see if you can use this method, or be prepared to rescue from NameError.

Like #draw_ellipse, but the shape is solid, instead of an outline.



259
260
261
262
# File 'lib/rubygame/gfx.rb', line 259

def draw_ellipse_s( center, radii, color )
  _draw_ellipse( center, radii, color, false, true )
  return self
end

#draw_line(point1, point2, color) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:draw_line)” to see if you can use this method, or be prepared to rescue from NameError.

Draw a line segment between two points on the Surface. See also #draw_line_a

This method takes these arguments:

point1

the coordinates of one end of the line, [x1,y1].

point2

the coordinates of the other end of the line, [x2,y2].

color

the color of the shape. [r,g,b] or [r,g,b,a] (0-255), color name, or Rubygame::Color.



66
67
68
69
# File 'lib/rubygame/gfx.rb', line 66

def draw_line( point1, point2, color )
  _draw_line( point1, point2, color, false )
  return self
end

#draw_line_a(point1, point2, color) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:draw_line_a)” to see if you can use this method, or be prepared to rescue from NameError.

Like #draw_line, but the line will be anti-aliased.



78
79
80
81
# File 'lib/rubygame/gfx.rb', line 78

def draw_line_a( point1, point2, color )
  _draw_line( point1, point2, color, true )
  return self
end

#draw_polygon(points, color) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:draw_polygon)” to see if you can use this method, or be prepared to rescue from NameError.

Draw a non-solid polygon, given the coordinates of its vertices, in the order that they are connected. This is essentially a series of connected dots. See also #draw_polygon_a and #draw_polygon_s.

This method takes these arguments:

points

an Array containing the coordinate pairs for each vertex of the polygon, in the order that they are connected, e.g.

[x1,y1], [x2,y2], …, [xn,yn

].

color

the color of the shape. [r,g,b] or [r,g,b,a] (0-255), color name, or Rubygame::Color.



361
362
363
364
# File 'lib/rubygame/gfx.rb', line 361

def draw_polygon( points, color )
  _draw_polygon( points, color, false, false )
  return self
end

#draw_polygon_a(points, color) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:draw_polygon_a)” to see if you can use this method, or be prepared to rescue from NameError.

Like #draw_polygon, but the lines are anti-aliased.



374
375
376
377
# File 'lib/rubygame/gfx.rb', line 374

def draw_polygon_a( points, color )
  _draw_polygon( points, color, true, false )
  return self
end

#draw_polygon_s(points, color) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:draw_polygon_s)” to see if you can use this method, or be prepared to rescue from NameError.

Like #draw_polygon, but the shape is solid, instead of an outline.



387
388
389
390
# File 'lib/rubygame/gfx.rb', line 387

def draw_polygon_s( points, color )
  _draw_polygon( points, color, false, true )
  return self
end

#fill(color, rect = nil) ⇒ Object

Fill all or part of a Surface with a color.

This method takes these arguments:

color

color to fill with, in the form [r,g,b] or [r,g,b,a] (for partially transparent fills).

rect

a Rubygame::Rect representing the area of the surface to fill with color. Omit to fill the entire surface.



318
319
320
321
322
323
324
325
326
327
# File 'lib/rubygame/surface.rb', line 318

def fill( color, rect=nil )
  unless rect.nil? or rect.kind_of? Array
    raise TypeError, "invalid fill Rect: #{rect.inspect}"
  end

  color = _map_sdl_color( color )
  rect = SDL::Rect.new( rect.to_ary ) unless rect.nil?
  SDL.FillRect( @struct, rect, color )
  return self
end

#flagsObject

Return any flags the surface was initialized with (as a bitwise OR’d integer).



179
180
181
# File 'lib/rubygame/surface.rb', line 179

def flags
  @struct.flags
end

#flip(horz, vert) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:flip)” to see if you can use this method, or be prepared to rescue from NameError.

Flips the source surface horizontally (if horz is true), vertically (if vert is true), or both (if both are true).



578
579
580
# File 'lib/rubygame/gfx.rb', line 578

def flip( horz, vert )
  self.zoom( [ (horz ? -1.0 : 1.0), (vert ? -1.0 : 1.0)], false )
end

#get_at(*args) ⇒ Object

call-seq:

get_at( [x,y] )
get_at( x,y )

Return the color [r,g,b,a] (0-255) of the pixel at [x,y]. If the Surface does not have a per-pixel alpha channel (i.e. not 32-bit), alpha will always be 255. The Surface’s overall alpha value (from #set_alpha) does not affect the returned alpha value.

Raises IndexError if the coordinates are out of bounds.



349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
# File 'lib/rubygame/surface.rb', line 349

def get_at( *args )
  x,y = case args.length
        when 1; args[0].to_ary.collect { |n| n.round }
        when 2; [args[0].round, args[1].round]
        else
          raise( ArgumentError,
                 "wrong number of arguments (#{args.length} for 1)" )
        end

  if( x < 0 or x >= @struct.w or y < 0 or y >= @struct.h)
    raise( IndexError, "point [%d,%d] is out of bounds for %dx%d Surface"%\
           [x, y, @struct.w, @struct.h] )
  end

  SDL.LockSurface(@struct)

  bpp = @struct.format.BytesPerPixel
  ptr = @struct.pixels + (y * @struct.pitch + x * bpp)

  pixel =
    case bpp
    when 1
      ptr.get_uint8(0)
    when 2
      ptr.get_uint16(0)
    when 3
      if( FFI::Platform::BYTE_ORDER == FFI::Platform::BIG_ENDIAN )
        (ptr.get_uint8(0) << 16)|(ptr.get_uint8(1) << 8)|ptr.get_uint8(2)
      else
        ptr.get_uint8(0)|(ptr.get_uint8(1) << 8)|(ptr.get_uint8(2) << 16)
      end
    when 4
      ptr.get_uint32(0)
    end

  SDL.UnlockSurface(@struct)

  return SDL::GetRGBA(pixel, @struct.format) 
end

#hObject Also known as: height

Return the height (in pixels) of the surface.



153
154
155
# File 'lib/rubygame/surface.rb', line 153

def h
  @struct.h
end

#make_rectObject

Return a Rect with the same width and height as the Surface, with topleft = [0,0].



333
334
335
# File 'lib/rubygame/surface.rb', line 333

def make_rect()
  return Rubygame::Rect.new( 0, 0, self.w, self.h )
end

#masksObject

call-seq:

masks  ->  [r,g,b,a]

Return the color masks [r,g,b,a] of the surface. Almost everyone can ignore this function. Color masks are used to separate an integer representation of a color into its seperate channels.



191
192
193
194
# File 'lib/rubygame/surface.rb', line 191

def masks
  fmt = @struct.format
  [fmt.Rmask, fmt.Gmask, fmt.Bmask, fmt.Amask]
end

#pixelsObject

Return a string of pixel data for the Surface. Most users will not need to use this method. If you want to convert a Surface into an OpenGL texture, pass the returned string to the TexImage2D method of the ruby-opengl library. (See samples/demo_gl_tex.rb for an example.)

(Please note that the dimensions of OpenGL textures must be powers of 2 (e.g. 64x128, 512x512), so if you want to use a Surface as an OpenGL texture, the Surface’s dimensions must also be powers of 2!)



455
456
457
458
459
460
461
# File 'lib/rubygame/surface.rb', line 455

def pixels
  len = @struct.pitch * @struct.h
  SDL.LockSurface(@struct)
  pix = @struct.pixels.get_bytes(0, len)
  SDL.UnlockSurface(@struct)
  return pix
end

#rotozoom(angle, zoom, smooth = false) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:rotozoom)” to see if you can use this method, or be prepared to rescue from NameError.

Return a rotated and/or zoomed version of the given surface. Note that rotating a Surface anything other than a multiple of 90 degrees will cause the new surface to be larger than the original to accomodate the corners (which would otherwise extend beyond the surface).

May raise Rubygame::SDLError if the rotozoom fails.

angle

degrees to rotate counter-clockwise (negative for clockwise).

zoom

scaling factor(s). A number (to scale X and Y by the same factor) or an array of 2 numbers (to scale X and Y by different factors). Negative numbers flip the image. NOTE: Due to a quirk in SDL_gfx, if angle is not 0, the image is zoomed by the X factor on both X and Y, and the Y factor is only used for flipping (if it’s negative).

smooth

whether to anti-alias the new surface. By the way, if true, the new surface will be 32bit RGBA.



417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
# File 'lib/rubygame/gfx.rb', line 417

def rotozoom( angle, zoom, smooth=false )
  smooth = smooth ? 1 : 0

  surf = case zoom
         when Array
           zx, zy = zoom.collect { |n| n.to_f }
           SDL::Gfx.rotozoomSurfaceXY(@struct, angle, zx, zy, smooth)
         when Numeric
           zoom = zoom.to_f
           SDL::Gfx.rotozoomSurface(@struct, angle, zoom, smooth)
         else
           raise ArgumentError, "Invalid zoom factor: #{zoom.inspect}"
         end

  if( surf.pointer.null? )
    raise( Rubygame::SDLError,
           "Rotozoom failed: " + SDL.GetError() )
  end

  return self.class.new(surf)
end

#savebmp(filename) ⇒ Object

Save the Surface as a Windows Bitmap (BMP) file with the given filename. May raise SDLError if a problem occurs.



603
604
605
606
607
608
609
610
# File 'lib/rubygame/surface.rb', line 603

def savebmp( filename )
  result = SDL.SaveBMP( @struct, filename )
  if(result != 0)
    raise( Rubygame::SDLError, "Couldn't save surface to file %s: %s"%\
           [filename, SDL.GetError()] )
  end
  nil
end

#set_alpha(alpha, flags = Rubygame::SRCALPHA) ⇒ Object Also known as: alpha=

Set the per-surface alpha (opacity; non-transparency) of the surface. You can do the same thing with #alpha= if you don’t care about flags.

This function takes these arguments:

alpha

requested opacity of the surface. Alpha must be from 0 (fully transparent) to 255 (fully opaque).

flags

0 or Rubygame::SRCALPHA (default). Most people will want the default, in which case this argument can be omitted. For advanced users: this flag affects the surface as described in the docs for the SDL C function, SDL_SetAlpha.

Returns self.

Raises:



217
218
219
220
221
# File 'lib/rubygame/surface.rb', line 217

def set_alpha( alpha, flags=Rubygame::SRCALPHA )
  result = SDL.SetAlpha(@struct, flags, alpha.to_i)
  raise Rubygame::SDLError, SDL.GetError() unless result == 0
  return self
end

#set_at(pos, color) ⇒ Object

call-seq:

set_at( [x,y], color )

Set the color of the pixel at [x,y]. If no alpha value is given, or if the Surface does not have a per-pixel alpha channel (i.e. not 32-bit), the pixel will be set at full opacity.

color can be one of:

  • an Array, [r,g,b] or [r,g,b,a] with each component in 0-255.

  • an instance of Rubygame::ColorRGB, Rubygame::ColorHSV, etc.

  • the name of a color in Rubygame::Color, as a Symbol or String

Raises IndexError if the coordinates are out of bounds.



404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
# File 'lib/rubygame/surface.rb', line 404

def set_at( pos, color )
  x,y = pos.to_ary.collect { |n| n.round }

  if( x < 0 or x >= @struct.w or y < 0 or y >= @struct.h)
    raise( IndexError, "point [%d,%d] is out of bounds for %dx%d Surface"%\
           [x, y, @struct.w, @struct.h] )
  end

  color = _map_sdl_color( color )

  SDL.LockSurface(@struct)

  bpp = @struct.format.BytesPerPixel
  ptr = @struct.pixels + (y * @struct.pitch + x * bpp)

  case bpp
  when 1
    ptr.put_uint8(0, color)
  when 2
    ptr.put_uint16(0, color)
  when 3
    if( FFI::Platform::BYTE_ORDER == FFI::Platform::BIG_ENDIAN )
      ptr.put_uint8(0, (color >> 16) & 0xff)
      ptr.put_uint8(1, (color >> 8)  & 0xff)
      ptr.put_uint8(2, color & 0xff)
    else
      ptr.put_uint8(0, color & 0xff)
      ptr.put_uint8(1, (color >> 8)  & 0xff)
      ptr.put_uint8(2, (color >> 16) & 0xff)
    end
  when 4
    ptr.put_uint32(0, color)
  end

  SDL.UnlockSurface(@struct)

  return
end

#set_colorkey(color, flags = Rubygame::SRCCOLORKEY) ⇒ Object Also known as: colorkey=

Set the colorkey of the surface. See Surface#colorkey for a description of colorkeys.

This method takes these arguments:

color

color to use as the key, in the form [r,g,b]. Can be nil to un-set the colorkey.

flags

0 or Rubygame::SRCCOLORKEY (default) or Rubygame::SRCCOLORKEY|Rubygame::SDL_RLEACCEL. Most people will want the default, in which case this argument can be omitted. For advanced users: this flag affects the surface as described in the docs for the SDL C function, SDL_SetColorkey.

Raises:



256
257
258
259
260
261
262
263
264
265
266
# File 'lib/rubygame/surface.rb', line 256

def set_colorkey( color, flags=Rubygame::SRCCOLORKEY )
  if color.nil?
    color, flags = 0, 0
  else
    color = _map_sdl_color( color )
  end

  result = SDL.SetColorKey(@struct, flags, color)
  raise Rubygame::SDLError, SDL.GetError() unless result == 0
  return self
end

#sizeObject

call-seq:

size  ->  [w,h]

Return the surface’s width and height (in pixels) in an Array.



164
165
166
# File 'lib/rubygame/surface.rb', line 164

def size
  [@struct.w, @struct.h]
end

#to_displayObject

Copies the Surface to a new Surface with the pixel format of the display, suitable for fast blitting to the display surface (i.e. Screen). May raise SDLError if a problem occurs.

If you want to take advantage of hardware colorkey or alpha blit acceleration, you should set the colorkey and alpha value before calling this function.



553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
# File 'lib/rubygame/surface.rb', line 553

def to_display
  newsurf =
    if( Rubygame.init_video_system() == 0 )
      SDL.DisplayFormat( @struct )
    else
      nil
    end

  if( newsurf.nil? or newsurf.pointer.null?)
    raise( Rubygame::SDLError,
           "Could not convert the Surface to display format: %s"%\
           SDL.GetError() )
  end

  # Wrap it
  return self.class.new( newsurf )
end

#to_display_alphaObject

Like #to_display except the Surface has an extra channel for alpha (i.e. opacity). May raise SDLError if a problem occurs.

This function can be used to convert a colorkey to an alpha channel, if the SRCCOLORKEY flag is set on the surface. The generated surface will then be transparent (alpha=0) where the pixels match the colorkey, and opaque (alpha=255) elsewhere.



581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
# File 'lib/rubygame/surface.rb', line 581

def to_display_alpha
  newsurf =
    if( Rubygame.init_video_system() == 0 )
      SDL.DisplayFormatAlpha( @struct )
    else
      nil
    end

  if( newsurf.nil? or newsurf.pointer.null?)
    raise( Rubygame::SDLError,
           "Could not convert the Surface to display format "+
           "with alpha channel: #{SDL.GetError()}" )
  end

  # Wrap it
  return self.class.new( newsurf )
end

#to_sObject Also known as: inspect



613
614
615
# File 'lib/rubygame/surface.rb', line 613

def to_s
  "#<%s:%#.x>"%[self.class.name, self.object_id]
end

#wObject Also known as: width

Return the width (in pixels) of the surface.



145
146
147
# File 'lib/rubygame/surface.rb', line 145

def w
  @struct.w
end

#zoom(zoom, smooth = false) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:zoom)” to see if you can use this method, or be prepared to rescue from NameError.

Return a zoomed version of the Surface.

This method takes these arguments:

zoom

a Numeric factor to scale by in both x and y directions, or an Array with separate x and y scale factors.

smooth

whether to anti-alias the new surface. By the way, if true, the new surface will be 32bit RGBA.



488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
# File 'lib/rubygame/gfx.rb', line 488

def zoom( zoom, smooth=false )
  smooth = smooth ? 1 : 0

  surf = case zoom
         when Array
           zx, zy = zoom.collect { |n| n.to_f }
           SDL::Gfx.zoomSurface(@struct, zx, zy, smooth)
         when Numeric
           zoom = zoom.to_f
           SDL::Gfx.zoomSurface(@struct, zoom, zoom, smooth)
         else
           raise ArgumentError, "Invalid zoom factor: #{zoom.inspect}"
         end

  if( surf.pointer.null? )
    raise( Rubygame::SDLError, "Zoom failed: " + SDL.GetError() )
  end

  return self.class.new(surf)
end

#zoom_to(width, height, smooth = false) ⇒ Object

IMPORTANT: this method only exists if SDL_gfx is available! Your code should check “surface.respond_to?(:zoom_to)” to see if you can use this method, or be prepared to rescue from NameError.

Return a version of the Surface zoomed to a new size.

This method takes these arguments:

width

the desired width. If nil, the width will stay the same.

height

the desired height. If nil, the height will stay the same.

smooth

whether to anti-alias the new surface. This option can be omitted, in which case the surface will not be anti-aliased. If true, the new surface will be 32bit RGBA.



555
556
557
558
559
560
561
562
563
564
565
566
567
# File 'lib/rubygame/gfx.rb', line 555

def zoom_to( width, height, smooth=false )
  zoomx = case width
          when nil;      1.0
          when Numeric;  width.to_f / @struct.w
          end
           
  zoomy = case height
          when nil;      1.0
          when Numeric;  height.to_f / @struct.h
          end

  return self.zoom( [zoomx, zoomy], smooth )
end