Module: Tea::PrimitiveDrawing
Overview
The PrimitiveDrawing mixin enables primitive shapes to be drawn to classes with an internal SDL::Surface.
To use this mixin, include it and implement/alias a primitive_buffer method that gets the object’s SDL::Surface.
include 'PrimitiveDrawing'
def primitive_buffer
@internal_sdl_buffer
end
Constant Summary collapse
- BLEND_MIXER =
Mixer for alpha blend mix strategy.
lambda do |src_r, src_g, src_b, src_a, dest_r, dest_g, dest_b, dest_a, intensity| ai = src_a * intensity ratio = dest_a > 0 ? ai / dest_a.to_f : 1 ratio = 1 if ratio > 1 final_r = dest_r + (src_r - dest_r) * ratio final_g = dest_g + (src_g - dest_g) * ratio final_b = dest_b + (src_b - dest_b) * ratio final_a = (dest_a + ai < 255) ? (dest_a + ai) : 255 [final_r, final_g, final_b, final_a] end
- REPLACE_MIXER =
Mixer for replace mix strategy.
lambda do |src_r, src_g, src_b, src_a, dest_r, dest_g, dest_b, dest_a, intensity| [src_r, src_g, src_b, src_a * intensity] end
Instance Method Summary collapse
-
#circle(x, y, radius, color, options = nil) ⇒ Object
Draw a circle centred at (x, y) with the given radius and color (0xRRGGBBAA).
-
#clear ⇒ Object
Clear the drawing buffer.
-
#line(x1, y1, x2, y2, color, options = nil) ⇒ Object
Draw a line from (x1, y1) to (x2, y2) with the given color (0xRRGGBBAA).
-
#point(x, y, color) ⇒ Object
Plot a point at (x, y) with the given color (0xRRGGBBAA) on the Bitmap.
-
#rect(x, y, w, h, color, options = nil) ⇒ Object
Draw a rectangle of size w * h with the top-left corner at (x, y) with the given color (0xRRGGBBAA).
Instance Method Details
#circle(x, y, radius, color, options = nil) ⇒ Object
Draw a circle centred at (x, y) with the given radius and color (0xRRGGBBAA). Optional hash arguments:
:outline-
If true, do not fill the circle, just draw an outline.
:antialias-
If true, smooth the edges of the circle with antialiasing.
:mix-
:blendaverages the RGB parts of the circle and destination colours by the colour’s alpha (default).:replacewrites over the RGBA parts of the circle’s destination pixels.
Raises Tea::Error if the radius is less than 0, or :mix is given an unrecognised symbol.
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/tea/m_primitive_drawing.rb', line 149 def circle(x, y, radius, color, =nil) if radius < 0 raise Tea::Error, "can't draw circle with radius #{radius}", caller end if == nil outline = false antialias = false mix = :blend else outline = [:outline] || false antialias = [:antialias] || false mix = [:mix] || :blend unless [:blend, :replace].include?(mix) raise Tea::Error, "invalid mix option \"#{mix}\"", caller end end if primitive_buffer.class == SDL::Screen case mix when :blend r, g, b, a = primitive_hex_to_rgba(color) if !outline && antialias && a < 0xff # rubysdl can't draw filled antialiased alpha circles for some reason. # Big endian because the SGE-powered circle antialiasing apparently # doesn't like it any other way. ts = SDL::Surface.new(SDL::SWSURFACE, (radius + 1) * 2, (radius + 1) * 2, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff) ts.draw_circle radius + 1, radius + 1, radius, ts.map_rgba(r, g, b, a), true, true SDL::Surface.blit ts, 0, 0, ts.w, ts.h, primitive_buffer, x - radius - 1, y - radius - 1 else primitive_buffer.draw_circle x, y, radius, primitive_rgba_to_color(r, g, b, 255), !outline, antialias, (a == 255 ? nil : a) end when :replace primitive_buffer.draw_circle x, y, radius, primitive_color(color), !outline, antialias end else # SGE and alpha mixing don't... mix. Gotta do it ourselves. mixer = (mix == :blend) ? BLEND_MIXER : REPLACE_MIXER r, g, b, a = primitive_hex_to_rgba(color) primitive_circle x, y, radius, !outline, antialias, r, g, b, a, mixer end end |
#clear ⇒ Object
Clear the drawing buffer. This is the same as drawing a completely black rectangle over the whole buffer.
24 25 26 27 |
# File 'lib/tea/m_primitive_drawing.rb', line 24 def clear primitive_buffer.fill_rect 0, 0, primitive_buffer.w, primitive_buffer.h, primitive_color(0x000000ff) end |
#line(x1, y1, x2, y2, color, options = nil) ⇒ Object
Draw a line from (x1, y1) to (x2, y2) with the given color (0xRRGGBBAA). Optional hash arguments:
:antialias-
If true, smooth the line with antialiasing.
:mix-
:blendaverages the RGB parts of the line and destination colours by the line alpha (default).:replacewrites over the RGBA parts of the line destination pixels.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/tea/m_primitive_drawing.rb', line 111 def line(x1, y1, x2, y2, color, =nil) if == nil antialias = false mix = :blend else antialias = [:antialias] || false mix = [:mix] || :blend unless [:blend, :replace].include?(mix) raise Tea::Error, "invalid mix option \"#{mix}\"", caller end end r, g, b, a = primitive_hex_to_rgba(color) if primitive_buffer.class == SDL::Screen primitive_buffer.draw_line x1, y1, x2, y2, primitive_rgba_to_color(r, g, b, (mix == :replace ? a : 255)), antialias, (mix == :blend ? a : nil) else if antialias primitive_aa_line x1, y1, x2, y2, r, g, b, a, (mix == :blend ? BLEND_MIXER : REPLACE_MIXER) else primitive_line x1, y1, x2, y2, r, g, b, a, (mix == :blend ? BLEND_MIXER : REPLACE_MIXER) end end end |
#point(x, y, color) ⇒ Object
Plot a point at (x, y) with the given color (0xRRGGBBAA) on the Bitmap.
Raises Tea::Error if (x, y) is outside of the drawing buffer.
32 33 34 35 36 37 38 39 |
# File 'lib/tea/m_primitive_drawing.rb', line 32 def point(x, y, color) w = primitive_buffer.w h = primitive_buffer.h if x < 0 || x > w || y < 0 || y > h raise Tea::Error, "can't plot point (#{x}, #{y}), not within #{w}x#{h}", caller end primitive_buffer[x, y] = primitive_color(color) end |
#rect(x, y, w, h, color, options = nil) ⇒ Object
Draw a rectangle of size w * h with the top-left corner at (x, y) with the given color (0xRRGGBBAA). Hash arguments that can be used:
:mix-
:blendaverages the RGB parts the rectangle and destination colours according to the colour’s alpha (default).:replacewrites over the full RGBA parts of the rectangle area’s pixels.
Raises Tea::Error if w or h are less than 0, or if :mix is given an unrecognised symbol.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/tea/m_primitive_drawing.rb', line 68 def rect(x, y, w, h, color, =nil) if w < 0 || h < 0 || ( && [:mix] == :blend && (w < 1 || h < 1)) raise Tea::Error, "can't draw rectangle of size #{w}x#{h}", caller end if == nil || [:mix] == nil mix = :blend else unless [:blend, :replace].include?([:mix]) raise Tea::Error, "invalid mix option \"#{options[:mix]}\"", caller end mix = [:mix] end r, g, b, a = primitive_hex_to_rgba(color) case mix when :blend if a == 0xff # Same as for mix == :replace primitive_buffer.fill_rect x, y, w, h, primitive_rgba_to_color(r, g, b, a) elsif primitive_buffer.class == SDL::Screen # SGE's broken alpha blending doesn't matter on the screen, so # optimise for it. rubysdl's draw_rect is off-by-one for width and # height, so compensate for that. primitive_buffer.draw_rect x, y, w - 1, h - 1, primitive_rgba_to_color(r, g, b, 255), true, a else # CAUTION: This is _really_ slow, almost unusably so. Perhaps I # should consider not making :blend the default mix mode. primitive_rect x, y, w, h, r, g, b, a, BLEND_MIXER end when :replace primitive_buffer.fill_rect x, y, w, h, primitive_rgba_to_color(r, g, b, a) end end |