require 'rabbit/gtk' require 'rabbit/renderer/kernel' module Rabbit module Renderer module Engine module GDK include Kernel class << self def priority 0 end end def prepare_renderer(drawable) @gdk_drawables ||= [] @gdk_drawable = drawable @gdk_drawables.push(@gdk_drawable) end def init_renderer(drawable) prepare_renderer(drawable) end def finish_renderer @gdk_drawables.pop @gdk_drawable = @gdk_drawables.pop end def alpha_available? false end def foreground=(color) @foreground.set_rgb_fg_color(color.to_gdk_color) end def background=(color) @background.set_rgb_fg_color(color.to_gdk_color) end def background_image=(pixbuf) w, h = pixbuf.width, pixbuf.height pixmap = Gdk::Pixmap.new(nil, w, h, depth) pixmap.draw_rectangle(@background, true, 0, 0, w, h) args = [ @foreground, pixbuf, 0, 0, 0, 0, w, h, Gdk::RGB::DITHER_NORMAL, 0, 0, ] pixmap.draw_pixbuf(*args) @background.set_tile(pixmap) @background.fill = Gdk::GC::Fill::TILED end def draw_line(x1, y1, x2, y2, color=nil, params={}) gc = make_gc(color, params) return if gc.nil? @gdk_drawable.draw_line(gc, x1, y1, x2, y2) end def draw_lines(points, color=nil, params={}) gc = make_gc(color, params) return if gc.nil? @gdk_drawable.draw_lines(gc, points) end def draw_rectangle(filled, x, y, w, h, color=nil, params={}) gc = make_gc(color, params) return if gc.nil? @gdk_drawable.draw_rectangle(gc, filled, x, y, w, h) end def draw_rounded_rectangle(filled, x, y, w, h, radius, color=nil, params={}) x_radius = params[:x_radius] || radius y_radius = params[:y_radius] || radius x_diameter = x_radius * 2 y_diameter = y_radius * 2 line_width = params[:line_width] inner_x = x + x_radius inner_y = y + y_radius inner_w = w - x_diameter inner_h = h - y_diameter if filled draw_rectangle(true, inner_x, inner_y, inner_w, inner_h, color) end if filled top = [inner_x, y, inner_w, y_radius] left = [x, inner_y, x_radius, inner_h] bottom = [inner_x, inner_y + inner_h, inner_w, y_radius] right = [inner_x + inner_w, inner_y, x_radius, inner_h] [top, left, bottom, right].each do |rx, ry, rw, rh| draw_rectangle(true, rx, ry, rw, rh, color) end else top = [inner_x, y, inner_x + inner_w, y] left = [x, inner_y, x, inner_y + inner_h] bottom = [inner_x, y + h, inner_x + inner_w, y + h] right = [x + w, inner_y, x + w, inner_y + inner_h] [top, left, bottom, right].each do |start_x, start_y, end_x, end_y| draw_line(start_x, start_y, end_x, end_y, color, {:line_width => line_width}) end end upper_left = [x, y, 90] lower_left = [x, y + inner_h, 180] lower_right = [x + inner_w, y + inner_h, 270] upper_right = [x + inner_w, y, 0] [ upper_left, lower_left, lower_right, upper_right ].each do |ax, ay, start_angle| draw_arc(filled, ax, ay, x_diameter, y_diameter, start_angle, 90, color, {:line_width => line_width}) end end def draw_arc(filled, x, y, w, h, a1, a2, color=nil, params={}) gc = make_gc(color, params) return if gc.nil? a1 *= 64 a2 *= 64 @gdk_drawable.draw_arc(gc, filled, x, y, w, h, a1, a2) end def draw_arc_by_radius(filled, x, y, r, a1, a2, color=nil, params={}) sx = x - r sy = y - r w = r * 2 h = r * 2 draw_arc(filled, sx, sy, w, h, a1, a2, color, params) end def draw_polygon(filled, points, color=nil, params={}) gc = make_gc(color, params) return if gc.nil? @gdk_drawable.draw_polygon(gc, filled, points) end def draw_layout(layout, x, y, color=nil, params={}) gc = make_gc(color, params) return if gc.nil? @gdk_drawable.draw_layout(gc, x, y, layout) end def draw_pixbuf(pixbuf, x, y, params={}) gc = make_gc(params[:color], params) return if gc.nil? draw_scaled_pixbuf = params[:draw_scaled_pixbuf] draw_scaled_pixbuf = @draw_scaled_image if draw_scaled_pixbuf.nil? width = params[:width] || pixbuf.width height = params[:height] || pixbuf.height if draw_scaled_pixbuf and [width, height] != [pixbuf.width, pixbuf.height] pixbuf = pixbuf.scale(width, height) end args = [0, 0, x, y, width, height, params[:dither_mode] || Gdk::RGB::DITHER_NORMAL, params[:x_dither] || 0, params[:y_dither] || 0] @gdk_drawable.draw_pixbuf(gc, pixbuf, *args) end private def init_engine_color @foreground = Gdk::GC.new(@gdk_drawable) @background = make_gc_from_string(@background_color) end # this method is no longer need. the reason that # this isn't removed is only for my memo. def set_mask(gc, x, y, mask) clip_mask = gc.clip_mask clip_origin = gc.clip_origin gc.clip_mask = mask gc.set_clip_origin(x, y) result = yield(gc) gc.clip_mask = clip_mask gc.set_clip_origin(*clip_origin) result end def internal_make_gc(color) if color.nil? Gdk::GC.new(@gdk_drawable) elsif color.is_a?(String) make_gc_from_string(color) elsif color.is_a?(Gdk::Color) make_gc_from_gdk_color(color) elsif color.is_a?(Renderer::Color) make_gc_from_gdk_color(color.to_gdk_color) else color end end def make_gc_from_gdk_color(color) gc = Gdk::GC.new(@gdk_drawable) gc.set_rgb_fg_color(color) gc end def make_gc_from_string(str) color = Color.parse(str).to_gdk_color make_gc_from_gdk_color(color) end def make_gc(color, params={}) return nil if params[:pattern] and color.nil? gc = internal_make_gc(color) gc.set_line_attributes(get_line_width(params, 1), Gdk::GC::LINE_SOLID, Gdk::GC::CAP_ROUND, Gdk::GC::JOIN_ROUND) gc end end end end end