module Rabbit::Renderer::Engine::Cairo

Attributes

background[W]
foreground[W]

Public Instance Methods

alpha_available?() click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 15
def alpha_available?
  true
end
background_image=(pixbuf) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 19
def background_image=(pixbuf)
  surface = ::Cairo::ImageSurface.new(::Cairo::FORMAT_A1, 1, 1)
  context = ::Cairo::Context.new(surface)
  context.set_source_pixbuf(pixbuf)
  @background_image = context.source
  @background_image.extend = ::Cairo::EXTEND_REPEAT
  pixbuf
end
create_pango_context() click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 296
def create_pango_context
  context = Pango::CairoFontMap.default.create_context
  set_font_resolution(context)
  context
end
draw_arc(filled, x, y, w, h, a1, a2, color=nil, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 141
def draw_arc(filled, x, y, w, h, a1, a2, color=nil, params={})
  r = w * 0.5
  draw_arc_by_radius(filled, x + w * 0.5, y + h * 0.5,
                     r, a1, a2, color, params)
end
draw_arc_by_radius(filled, x, y, r, a1, a2, color=nil, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 147
def draw_arc_by_radius(filled, x, y, r, a1, a2, color=nil, params={})
  x, y = from_screen(x, y)
  a1, a2 = convert_angle(a1, a2)
  @context.save do
    set_source(color, params)
    set_line_options(params)
    args = [x, y, r, a1, a2]
    action, = cairo_action(filled, params)
    @context.move_to(x, y) unless action == :stroke
    @context.arc(*args)
    @context.close_path unless action == :stroke
    apply_cairo_action(filled, params)
  end
end
draw_background(slide) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 93
def draw_background(slide)
  super
  if @background_image
    @context.save do
      @context.set_source(@background_image)
      @context.paint
    end
  end
end
draw_layout(layout, x, y, color=nil, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 180
def draw_layout(layout, x, y, color=nil, params={})
  x, y = from_screen(x, y)
  @context.save do
    set_source(color, params)
    set_line_options(params)
    @context.move_to(x, y)
    if params[:stroke]
      @context.pango_layout_path(layout)
      apply_cairo_action(false, params)
    else
      @context.show_pango_layout(layout)
    end
  end
end
draw_line(x1, y1, x2, y2, color=nil, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 103
def draw_line(x1, y1, x2, y2, color=nil, params={})
  x1, y1 = from_screen(x1, y1)
  x2, y2 = from_screen(x2, y2)
  @context.save do
    set_source(color, params)
    set_line_options(params)
    @context.new_path
    @context.move_to(x1, y1)
    @context.line_to(x2, y2)
    apply_cairo_action(false, params)
  end
end
draw_lines(points, color=nil, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 162
def draw_lines(points, color=nil, params={})
  draw_polygon(false, points, color, params.merge({:opened => true}))
end
draw_pixbuf(pixbuf, x, y, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 195
def draw_pixbuf(pixbuf, x, y, params={})
  x, y = from_screen(x, y)
  @context.save do
    apply_clip(x, y, pixbuf.width, pixbuf.height, params)
    @context.translate(x, y)
    set_source_pixbuf(pixbuf, params)
    @context.paint(params[:alpha])
  end

  _draw_reflected_pixbuf(pixbuf, x, y, params)
end
draw_polygon(filled, points, color=nil, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 166
def draw_polygon(filled, points, color=nil, params={})
  return if points.empty?
  @context.save do
    set_source(color, params)
    set_line_options(params)
    @context.move_to(*from_screen(*points.first))
    points[1..-1].each do |x, y|
      @context.line_to(*from_screen(x, y))
    end
    @context.line_to(*from_screen(*points.first)) unless params[:opened]
    apply_cairo_action(filled, params)
  end
end
draw_poppler_page(page, x, y, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 263
def draw_poppler_page(page, x, y, params={})
  x, y = from_screen(x, y)
  w, h = page.size
  width = (params[:width] || w).to_f
  height = (params[:height] || h).to_f
  @context.save do
    apply_clip(x, y, w, h, params)
    @context.translate(x, y)
    @context.scale(width / w, height / h)
    @context.render_poppler_page(page)
  end
end
draw_rectangle(filled, x, y, w, h, color=nil, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 116
def draw_rectangle(filled, x, y, w, h, color=nil, params={})
  x, y = from_screen(x, y)
  @context.save do
    set_source(color, params)
    set_line_options(params)
    @context.rectangle(x, y, w, h)
    apply_cairo_action(filled, params)
  end
end
draw_rounded_rectangle(filled, x, y, w, h, radius, color=nil, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 126
def draw_rounded_rectangle(filled, x, y, w, h, radius,
                           color=nil, params={})
  x, y = from_screen(x, y)
  x_radius = params[:x_radius] || radius
  y_radius = params[:y_radius] || radius

  @context.save do
    set_source(color, params)
    set_line_options(params)
    @context.new_path
    @context.rounded_rectangle(x, y, w, h, x_radius, y_radius)
    apply_cairo_action(filled, params)
  end
end
draw_rsvg_handle(handle, x, y, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 245
def draw_rsvg_handle(handle, x, y, params={})
  x, y = from_screen(x, y)
  dim = handle.dimensions
  w = dim.width
  h = dim.height
  width = (params[:width] || w).to_f
  height = (params[:height] || h).to_f
  @context.save do
    apply_clip(x, y, w, h, params)
    @context.translate(x, y)
    @context.scale(width / w, height / h)
    @context.render_rsvg_handle(handle)
  end

  _draw_reflected_rsvg_handle(handle, x, y, width, height,
                              params)
end
finish_context() click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 45
def finish_context
  @contexts.pop
  @context.destroy if @context.respond_to?(:destroy)
  @context = @contexts.last
end
finish_renderer() click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 32
def finish_renderer
  finish_context
end
init_context(context) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 36
def init_context(context)
  @context = context
  @contexts ||= []
  @contexts.push(@context)
  set_line_width(1)
  @context.line_cap = ::Cairo::LINE_CAP_ROUND
  @context.line_join = ::Cairo::LINE_JOIN_ROUND
end
init_renderer(drawable) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 28
def init_renderer(drawable)
  init_context(drawable.create_cairo_context)
end
make_layout(text) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 286
def make_layout(text)
  attributes, text = Pango.parse_markup(text)
  layout = @context.create_pango_layout
  layout.text = text
  layout.attributes = attributes
  set_font_resolution(layout.context)
  @context.update_pango_layout(layout)
  layout
end
reflect_context(base, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 67
def reflect_context(base, params={})
  case base
  when :y
    matrix = make_matrix(-1, 0, 0,
                          0, 1, 0)
  else
    matrix = make_matrix(1,  0, 0,
                         0, -1, 0)
  end
  @context.transform(matrix)
end
restore_context() click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 89
def restore_context
  @context.restore
end
rotate_context(angle, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 59
def rotate_context(angle, params={})
  @context.rotate(convert_angle(angle, 0)[0])
end
save_context() click to toggle source
Calls superclass method Rabbit::Renderer::Kernel#save_context
# File lib/rabbit/renderer/engine/cairo.rb, line 84
def save_context
  @context.save
  super
end
scale_context(x, y, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 63
def scale_context(x, y, params={})
  @context.scale(x, y)
end
set_font_resolution(context) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 302
def set_font_resolution(context)
  context.resolution = @canvas.font_resolution
end
set_source_pixbuf(pixbuf, params) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 207
def set_source_pixbuf(pixbuf, params)
  draw_scaled_pixbuf = params[:draw_scaled_pixbuf]
  draw_scaled_pixbuf = @draw_scaled_image if draw_scaled_pixbuf.nil?
  width = (params[:width] || pixbuf.width).to_f
  height = (params[:height] || pixbuf.height).to_f

  if [width, height] == [pixbuf.width, pixbuf.height]
    @context.set_source_pixbuf(pixbuf, 0, 0)
    return
  end

  case draw_scaled_pixbuf
  when true
    scaled_pixbuf = pixbuf.scale(width, height)
    @context.set_source_pixbuf(scaled_pixbuf, 0, 0)
  when false
    @context.set_source_pixbuf(pixbuf, 0, 0)
    matrix = ::Cairo::Matrix.scale(pixbuf.width / width,
                                   pixbuf.height / height)
    @context.source.matrix = matrix
  else
    scales = [4, 3, 2]
    scales.each do |scale|
      if width * scale < pixbuf.width and height * scale < pixbuf.height
        scaled_pixbuf = pixbuf.scale(width * scale, height * scale)
        @context.set_source_pixbuf(scaled_pixbuf)
        matrix = ::Cairo::Matrix.scale(scale, scale)
        @context.source.matrix = matrix
        return
      end
    end
    @context.set_source_pixbuf(pixbuf, 0, 0)
    matrix = ::Cairo::Matrix.scale(pixbuf.width / width,
                                   pixbuf.height / height)
    @context.source.matrix = matrix
  end
end
shear_context(x, y, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 79
def shear_context(x, y, params={})
  @context.transform(make_matrix(1, x, 0,
                                 y, 1, 0))
end
to_gdk_rgb(color) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 51
def to_gdk_rgb(color)
  make_color(color).to_gdk_rgb
end
translate_context(x, y, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 55
def translate_context(x, y, params={})
  @context.translate(x, y)
end

Private Instance Methods

_draw_reflected_pixbuf(pixbuf, x, y, params) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 424
def _draw_reflected_pixbuf(pixbuf, x, y, params)
  reflect_params = params[:reflect]
  return unless reflect_params

  reflect_params = {} if reflect_params == true
  ratio = reflect_params[:ratio] || 0.3
  start_alpha = reflect_params[:start_alpha] || 0.3

  @context.save do
    width = (params[:width] || pixbuf.width).to_f
    height = (params[:height] || pixbuf.height).to_f
    @context.translate(x, y + height * 2)
    reflect_context(:x)
    set_source_pixbuf(pixbuf, params)
    pattern = ::Cairo::LinearPattern.new(width * 0.5, 0,
                                         width * 0.5, height)
    pattern.add_color_stop_rgba(0, 0, 0, 0, 0)
    pattern.add_color_stop_rgba(1 - ratio, 0, 0, 0, 0)
    pattern.add_color_stop_rgba(1, 0, 0, 0, start_alpha)
    @context.mask(pattern)
  end
end
_draw_reflected_rsvg_handle(handle, x, y, width, height, params) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 447
def _draw_reflected_rsvg_handle(handle, x, y, width, height, params)
  return unless params

  dim = handle.dimensions
  ::Cairo::ImageSurface.new(:argb32, width, height) do |surface|
    ::Cairo::Context.new(surface) do |context|
      context.scale(width / dim.width, height / dim.height)
      context.render_rsvg_handle(handle)
      png = StringIO.new
      context.target.write_to_png(png)
      loader = ImageDataLoader.new(png.string)
      loader.load
      _draw_reflected_pixbuf(loader.pixbuf, x, y, params)
    end
  end
end
apply_cairo_action(filled, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 394
def apply_cairo_action(filled, params={})
  action, *other_info = cairo_action(filled, params)
  @context.send(action)
  case action
  when :clip
    block, = other_info
    block.call if block
  end
end
apply_clip(x, y, w, h, params) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 404
def apply_clip(x, y, w, h, params)
  clip_x = params[:clip_x]
  clip_y = params[:clip_y]
  clip_width = params[:clip_width]
  clip_height = params[:clip_height]
  if clip_x or clip_y or clip_width or clip_height
    @context.rectangle(x,
                       y,
                       clip_width || w,
                       clip_height || h)
    @context.clip
    @context.translate(x - (clip_x || x),
                       y - (clip_y || y))
  end
end
cairo_action(filled, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 384
def cairo_action(filled, params={})
  if params[:clip]
    [:clip, params[:clip]]
  elsif filled
    :fill
  else
    :stroke
  end
end
convert_angle(a1, a2) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 375
def convert_angle(a1, a2)
  a2 += a1
  [a2, a1].collect {|a| (360 - a) * (Math::PI / 180.0)}
end
from_screen(x, y) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 380
def from_screen(x, y)
  [x.ceil, y.ceil]
end
init_engine_color() click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 307
def init_engine_color
  @foreground = make_color("black")
  @background = make_color(@background_color)
end
make_matrix(xx, xy, x0, yx, yy, y0) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 420
def make_matrix(xx, xy, x0, yx, yy, y0)
  ::Cairo::Matrix.new(xx, yx, xy, yy, x0, y0)
end
set_color(color) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 365
def set_color(color)
  @context.set_source_rgba(make_color(color).to_a)
end
set_line_options(params) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 464
def set_line_options(params)
  set_line_width(get_line_width(params))
  [:line_cap, :line_join].each do |key|
    value = params[key]
    @context.send("#{key}=", value) if value
  end
end
set_line_width(line_width) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 369
def set_line_width(line_width)
  if line_width
    @context.set_line_width(line_width)
  end
end
set_pattern(info) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 322
def set_pattern(info)
  pattern = nil
  case info[:type]
  when :radial
    cx0, cy0, radius0, cx1, cy1, radius1 = info[:base]
    cx0, cy0 = from_screen(cx0, cy0)
    cx1, cy1 = from_screen(cx1, cy1)
    pattern = ::Cairo::RadialPattern.new(cx0, cy0, radius0,
                                         cx1, cy1, radius1)
    info[:color_stops].each do |offset, r, g, b, a|
      pattern.add_color_stop_rgba(offset, r, g, b, a)
    end
  when :linear
    x, y, w, h = info[:base]
    x, y = from_screen(x, y)
    pattern = ::Cairo::LinearPattern.new(x, y, w, h)
    info[:color_stops].each do |offset, r, g, b, a|
      pattern.add_color_stop_rgba(offset, r, g, b, a)
    end
  when :pixbuf
    @context.set_source_pixbuf(info[:pixbuf])
    pattern = @context.source
  end
  if pattern
    set_pattern_common_options(pattern, info)
    @context.set_source(pattern)
  end
  !pattern.nil?
end
set_pattern_common_options(pattern, info) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 352
def set_pattern_common_options(pattern, info)
  extend = info[:extend]
  pattern.extend = extend if extend
  transformations = info[:transformations]
  if transformations
    matrix = ::Cairo::Matrix.identity
    transformations.each do |operation, *args|
      matrix.send("#{operation}!", *args)
    end
    pattern.matrix = matrix
  end
end
set_source(color, params={}) click to toggle source
# File lib/rabbit/renderer/engine/cairo.rb, line 312
def set_source(color, params={})
  pattern = params[:pattern]
  set = false
  if pattern
    set = set_pattern(pattern)
    color ||= Color.parse("#fff0") unless set
  end
  set_color(make_color(color)) unless set
end