[cairo-commit] rcairo/src .cvsignore, NONE, 1.1 cairo.def, NONE, 1.1 depend, NONE, 1.1 rb_cairo.c, NONE, 1.1 rb_cairo.h, NONE, 1.1 rb_cairo_constants.c, NONE, 1.1 rb_cairo_context.c, NONE, 1.1 rb_cairo_exception.c, NONE, 1.1 rb_cairo_font_extents.c, NONE, 1.1 rb_cairo_font_face.c, NONE, 1.1 rb_cairo_font_options.c, NONE, 1.1 rb_cairo_glyph.c, NONE, 1.1 rb_cairo_matrix.c, NONE, 1.1 rb_cairo_path.c, NONE, 1.1 rb_cairo_pattern.c, NONE, 1.1 rb_cairo_private.c, NONE, 1.1 rb_cairo_private.h, NONE, 1.1 rb_cairo_scaled_font.c, NONE, 1.1 rb_cairo_surface.c, NONE, 1.1 rb_cairo_text_extents.c, NONE, 1.1

Kouhei Sutou commit at pdx.freedesktop.org
Tue Mar 6 04:17:41 PST 2007


Committed by: kou

Update of /cvs/cairo/rcairo/src
In directory kemper:/tmp/cvs-serv14983/src

Added Files:
	.cvsignore cairo.def depend rb_cairo.c rb_cairo.h 
	rb_cairo_constants.c rb_cairo_context.c rb_cairo_exception.c 
	rb_cairo_font_extents.c rb_cairo_font_face.c 
	rb_cairo_font_options.c rb_cairo_glyph.c rb_cairo_matrix.c 
	rb_cairo_path.c rb_cairo_pattern.c rb_cairo_private.c 
	rb_cairo_private.h rb_cairo_scaled_font.c rb_cairo_surface.c 
	rb_cairo_text_extents.c 
Log Message:
* setup.rb: removed dependency on setup.rb. used Ruby-GNOME2 style.
* extconf.rb: moved from packages/cairo/ext/.

* packages/cairo/ext: move to ...
* src/: ... here.

* packages/cairo/lib: move to ...
* src/lib: ... here.

* README, samples/: followed the changes.


--- NEW FILE: .cvsignore ---
Makefile
*.o
*.so

--- NEW FILE: cairo.def ---
EXPORTS
    Init_cairo
    rb_mCairo                 DATA
    rb_cCairo_Context         DATA
    rb_cCairo_Path            DATA
    rb_cCairo_Matrix          DATA
    rb_cCairo_Pattern         DATA
    rb_cCairo_SolidPattern    DATA
    rb_cCairo_SurfacePattern  DATA
    rb_cCairo_GradientPattern DATA
    rb_cCairo_LinearPattern   DATA
    rb_cCairo_RadialPattern   DATA
    rb_cCairo_FontFace        DATA
    rb_cCairo_FontExtents     DATA
    rb_cCairo_FontOptions     DATA
    rb_cCairo_ScaledFont      DATA
    rb_cCairo_TextExtents     DATA
    rb_cCairo_Glyph           DATA
    rb_cCairo_Surface         DATA
    rb_cairo_context_from_ruby_object
    rb_cairo_context_to_ruby_object
    rb_cairo_path_from_ruby_object
    rb_cairo_path_to_ruby_object
    rb_cairo_matrix_from_ruby_object
    rb_cairo_matrix_to_ruby_object
    rb_cairo_pattern_from_ruby_object
    rb_cairo_pattern_to_ruby_object
    rb_cairo_font_face_from_ruby_object
    rb_cairo_font_face_to_ruby_object
    rb_cairo_font_extents_from_ruby_object
    rb_cairo_font_extents_to_ruby_object
    rb_cairo_font_options_to_ruby_object
    rb_cairo_font_options_from_ruby_object
    rb_cairo_scaled_font_to_ruby_object
    rb_cairo_scaled_font_from_ruby_object
    rb_cairo_text_extents_from_ruby_object
    rb_cairo_text_extents_to_ruby_object
    rb_cairo_glyph_from_ruby_object
    rb_cairo_glyph_to_ruby_object
    rb_cairo_surface_from_ruby_object
    rb_cairo_surface_to_ruby_object
    rb_cairo_operator_from_ruby_object
    rb_cairo_antialias_from_ruby_object
    rb_cairo_fill_rule_from_ruby_object
    rb_cairo_line_cap_from_ruby_object
    rb_cairo_line_join_from_ruby_object
    rb_cairo_font_slant_from_ruby_object
    rb_cairo_font_weight_from_ruby_object
    rb_cairo_subpixel_order_from_ruby_object
    rb_cairo_hint_style_from_ruby_object
    rb_cairo_hint_metrics_from_ruby_object
    rb_cairo_path_data_type_from_ruby_object
    rb_cairo_content_from_ruby_object
    rb_cairo_format_from_ruby_object
    rb_cairo_extend_from_ruby_object
    rb_cairo_filter_from_ruby_object
    rb_cairo_svg_version_from_ruby_object
    rb_cairo_check_status

--- NEW FILE: depend ---
install:
	@$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0644, true)' $(srcdir)/rb_cairo.h $(sitearchdir)$(target_prefix)

--- NEW FILE: rb_cairo.c ---
/* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
 * Ruby Cairo Binding
 *
 * $Author: kou $
 * $Date: 2007/03/06 12:17:34 $
 *
 * Copyright 2005 Øyvind Kolås <pippin at freedesktop.org>
 * Copyright 2004-2005 MenTaLguY <mental at rydia.com>
 *
 * This file is made available under the same terms as Ruby
 *
 */


#include "rb_cairo.h"

VALUE rb_mCairo;

extern void Init_cairo_context (void);
extern void Init_cairo_path (void);
extern void Init_cairo_matrix (void);
extern void Init_cairo_surface (void);
extern void Init_cairo_constants (void);
extern void Init_cairo_exception (void);
extern void Init_cairo_font (void);
extern void Init_cairo_font_extents (void);
extern void Init_cairo_font_options (void);
extern void Init_cairo_scaled_font (void);
extern void Init_cairo_text_extents (void);
extern void Init_cairo_pattern (void);
extern void Init_cairo_glyph (void);

static ID id__add_one_arg_setter;

void
rb_cairo_def_setters (VALUE klass)
{
  rb_funcall (rb_mCairo, id__add_one_arg_setter, 1, klass);
}

void
Init_cairo ()
{
  int major, minor, micro;

  id__add_one_arg_setter = rb_intern("__add_one_arg_setter");

  rb_mCairo = rb_define_module ("Cairo");

  rb_define_const (rb_mCairo, "BUILD_VERSION",
                   rb_ary_new3 (3,
                                INT2FIX (CAIRO_VERSION_MAJOR),
                                INT2FIX (CAIRO_VERSION_MINOR),
                                INT2FIX (CAIRO_VERSION_MICRO)));

  major = cairo_version () / 10000;
  minor = (cairo_version () % 10000) / 100;
  micro = cairo_version () % 100;

  rb_define_const (rb_mCairo, "VERSION",
                   rb_ary_new3 (3,
                                INT2FIX (major),
                                INT2FIX (minor),
                                INT2FIX (micro)));
  
  rb_define_const (rb_mCairo, "MAJOR_VERSION", INT2FIX (major));
  rb_define_const (rb_mCairo, "MINOR_VERSION", INT2FIX (minor));
  rb_define_const (rb_mCairo, "MICRO_VERSION", INT2FIX (micro));

  rb_define_const (rb_mCairo, "BINDINGS_VERSION",
                   rb_ary_new3 (4,
                                INT2FIX (1), INT2FIX (4), INT2FIX (0), Qnil));

  Init_cairo_constants ();

  Init_cairo_context ();
  Init_cairo_path ();
  Init_cairo_matrix ();
  Init_cairo_surface ();
  Init_cairo_exception ();
  Init_cairo_font ();
  Init_cairo_font_extents ();
  Init_cairo_font_options ();
  Init_cairo_scaled_font ();
  Init_cairo_text_extents ();
  Init_cairo_pattern ();
  Init_cairo_glyph ();
}

--- NEW FILE: rb_cairo.h ---
/* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
 * Ruby Cairo Binding
 *
 * $Author: kou $
 * $Date: 2007/03/06 12:17:34 $
 *
 * Copyright 2005 Øyvind Kolås <pippin at freedesktop.org>
 * Copyright 2004-2005 MenTaLguY <mental at rydia.com>
 *
 * This file is made available under the same terms as Ruby
 *
 */


#ifndef RB_CAIRO_H
#define RB_CAIRO_H

#include <cairo.h>

#if CAIRO_HAS_PS_SURFACE
#  include <cairo-ps.h>
#endif

#if CAIRO_HAS_PDF_SURFACE
#  include <cairo-pdf.h>
#endif

#if CAIRO_HAS_SVG_SURFACE
#  include <cairo-svg.h>
#endif

#define CAIRO_CHECK_VERSION(major, minor, micro)    \
    (CAIRO_VERSION_MAJOR > (major) || \
     (CAIRO_VERSION_MAJOR == (major) && CAIRO_VERSION_MINOR > (minor)) || \
     (CAIRO_VERSION_MAJOR == (major) && CAIRO_VERSION_MINOR == (minor) && \
      CAIRO_VERSION_MICRO >= (micro)))

#include "ruby.h"

#if defined(RUBY_CAIRO_PLATFORM_WIN32) && !defined(RUBY_CAIRO_STATIC_COMPILATION)
#  ifdef RUBY_CAIRO_COMPILATION
#    define RUBY_CAIRO_VAR __declspec(dllexport)
#  else
#    define RUBY_CAIRO_VAR extern __declspec(dllimport)
#  endif
#else
#  define RUBY_CAIRO_VAR extern
#endif

RUBY_CAIRO_VAR VALUE rb_mCairo;
RUBY_CAIRO_VAR VALUE rb_cCairo_Context;
RUBY_CAIRO_VAR VALUE rb_cCairo_Path;
RUBY_CAIRO_VAR VALUE rb_cCairo_Matrix;
RUBY_CAIRO_VAR VALUE rb_cCairo_Pattern;
RUBY_CAIRO_VAR VALUE rb_cCairo_SolidPattern;
RUBY_CAIRO_VAR VALUE rb_cCairo_SurfacePattern;
RUBY_CAIRO_VAR VALUE rb_cCairo_GradientPattern;
RUBY_CAIRO_VAR VALUE rb_cCairo_LinearPattern;
RUBY_CAIRO_VAR VALUE rb_cCairo_RadialPattern;
RUBY_CAIRO_VAR VALUE rb_cCairo_FontFace;
RUBY_CAIRO_VAR VALUE rb_cCairo_FontExtents;
RUBY_CAIRO_VAR VALUE rb_cCairo_FontOptions;
RUBY_CAIRO_VAR VALUE rb_cCairo_ScaledFont;
RUBY_CAIRO_VAR VALUE rb_cCairo_TextExtents;
RUBY_CAIRO_VAR VALUE rb_cCairo_Glyph;
RUBY_CAIRO_VAR VALUE rb_cCairo_Surface;

#define RVAL2CRCONTEXT(obj)     (rb_cairo_context_from_ruby_object(obj))
#define CRCONTEXT2RVAL(cr)      (rb_cairo_context_to_ruby_object(cr))

#define RVAL2CRPATH(obj)        (rb_cairo_path_from_ruby_object(obj))
#define CRPATH2RVAL(path)       (rb_cairo_path_to_ruby_object(path))

#define RVAL2CRMATRIX(obj)      (rb_cairo_matrix_from_ruby_object(obj))
#define CRMATRIX2RVAL(matrix)   (rb_cairo_matrix_to_ruby_object(matrix))

#define RVAL2CRPATTERN(obj)     (rb_cairo_pattern_from_ruby_object(obj))
#define CRPATTERN2RVAL(pattern, klass) (rb_cairo_pattern_to_ruby_object(pattern, klass))

#define RVAL2CRFONTFACE(obj)    (rb_cairo_font_face_from_ruby_object(obj))
#define CRFONTFACE2RVAL(face)   (rb_cairo_font_face_to_ruby_object(face))

#define RVAL2CRFONTEXTENTS(obj) (rb_cairo_font_extents_from_ruby_object(obj))
#define CRFONTEXTENTS2RVAL(ext) (rb_cairo_font_extents_to_ruby_object(ext))

#define RVAL2CRFONTOPTIONS(obj) (rb_cairo_font_options_from_ruby_object(obj))
#define CRFONTOPTIONS2RVAL(opt) (rb_cairo_font_options_to_ruby_object(opt))

#define RVAL2CRSCALEDFONT(obj)  (rb_cairo_scaled_font_from_ruby_object(obj))
#define CRSCALEDFONT2RVAL(font) (rb_cairo_scaled_font_to_ruby_object(font))

#define RVAL2CRTEXTEXTENTS(obj) (rb_cairo_text_extents_from_ruby_object(obj))
#define CRTEXTEXTENTS2RVAL(ext) (rb_cairo_text_extents_to_ruby_object(ext))

#define RVAL2CRGLYPH(obj)       (rb_cairo_glyph_from_ruby_object(obj))
#define CRGLYPH2RVAL(glyph)     (rb_cairo_glyph_to_ruby_object(glyph))

#define RVAL2CRSURFACE(obj)     (rb_cairo_surface_from_ruby_object(obj))
#define CRSURFACE2RVAL(surface) (rb_cairo_surface_to_ruby_object(surface))

cairo_t              *rb_cairo_context_from_ruby_object      (VALUE obj);
VALUE                 rb_cairo_context_to_ruby_object        (cairo_t *cr);

cairo_path_t         *rb_cairo_path_from_ruby_object         (VALUE obj);
VALUE                 rb_cairo_path_to_ruby_object           (cairo_path_t *path);

cairo_matrix_t       *rb_cairo_matrix_from_ruby_object       (VALUE obj);
VALUE                 rb_cairo_matrix_to_ruby_object         (cairo_matrix_t *matrix);

cairo_pattern_t      *rb_cairo_pattern_from_ruby_object      (VALUE obj);
VALUE                 rb_cairo_pattern_to_ruby_object        (cairo_pattern_t *pat, VALUE klass);

cairo_font_face_t    *rb_cairo_font_face_from_ruby_object    (VALUE obj);
VALUE                 rb_cairo_font_face_to_ruby_object      (cairo_font_face_t *face);

cairo_font_extents_t *rb_cairo_font_extents_from_ruby_object (VALUE obj);
VALUE                 rb_cairo_font_extents_to_ruby_object   (cairo_font_extents_t *extents);

cairo_font_options_t *rb_cairo_font_options_from_ruby_object (VALUE obj);
VALUE                 rb_cairo_font_options_to_ruby_object   (cairo_font_options_t *options);

cairo_scaled_font_t  *rb_cairo_scaled_font_from_ruby_object  (VALUE obj);
VALUE                 rb_cairo_scaled_font_to_ruby_object    (cairo_scaled_font_t *options);

cairo_text_extents_t *rb_cairo_text_extents_from_ruby_object (VALUE obj);
VALUE                 rb_cairo_text_extents_to_ruby_object   (cairo_text_extents_t *extents);

cairo_glyph_t        *rb_cairo_glyph_from_ruby_object        (VALUE obj);
VALUE                 rb_cairo_glyph_to_ruby_object          (cairo_glyph_t *glyph);

cairo_surface_t      *rb_cairo_surface_from_ruby_object      (VALUE obj);
VALUE                 rb_cairo_surface_to_ruby_object        (cairo_surface_t *surface);


#define RVAL2CROPERATOR(obj)      (rb_cairo_operator_from_ruby_object(obj))
#define RVAL2CRANTIALIAS(obj)     (rb_cairo_antialias_from_ruby_object(obj))
#define RVAL2CRFILLRULE(obj)      (rb_cairo_fill_rule_from_ruby_object(obj))
#define RVAL2CRLINECAP(obj)       (rb_cairo_line_cap_from_ruby_object(obj))
#define RVAL2CRLINEJOIN(obj)      (rb_cairo_line_join_from_ruby_object(obj))
#define RVAL2CRFONTSLANT(obj)     (rb_cairo_font_slant_from_ruby_object(obj))
#define RVAL2CRFONTWEIGHT(obj)    (rb_cairo_font_weight_from_ruby_object(obj))
#define RVAL2CRSUBPIXELORDER(obj) (rb_cairo_subpixel_order_from_ruby_object(obj))
#define RVAL2CRHINTSTYLE(obj)     (rb_cairo_hint_style_from_ruby_object(obj))
#define RVAL2CRHINTMETRICS(obj)   (rb_cairo_hint_metrics_from_ruby_object(obj))
#define RVAL2CRPATHDATATYPE(obj)  (rb_cairo_path_data_type_from_ruby_object(obj))
#define RVAL2CRCONTENT(obj)       (rb_cairo_content_from_ruby_object(obj))
#define RVAL2CRFORMAT(obj)        (rb_cairo_format_from_ruby_object(obj))
#define RVAL2CREXTEND(obj)        (rb_cairo_extend_from_ruby_object(obj))
#define RVAL2CRFILTER(obj)        (rb_cairo_filter_from_ruby_object(obj))
#if CAIRO_HAS_SVG_SURFACE
#define RVAL2CRSVGVERSION(obj)    (rb_cairo_svg_version_from_ruby_object(obj))
#endif

cairo_operator_t       rb_cairo_operator_from_ruby_object       (VALUE obj);
cairo_antialias_t      rb_cairo_antialias_from_ruby_object      (VALUE obj);
cairo_fill_rule_t      rb_cairo_fill_rule_from_ruby_object      (VALUE obj);
cairo_line_cap_t       rb_cairo_line_cap_from_ruby_object       (VALUE obj);
cairo_line_join_t      rb_cairo_line_join_from_ruby_object      (VALUE obj);
cairo_font_slant_t     rb_cairo_font_slant_from_ruby_object     (VALUE obj);
cairo_font_weight_t    rb_cairo_font_weight_from_ruby_object    (VALUE obj);
cairo_subpixel_order_t rb_cairo_subpixel_order_from_ruby_object (VALUE obj);
cairo_hint_style_t     rb_cairo_hint_style_from_ruby_object     (VALUE obj);
cairo_hint_metrics_t   rb_cairo_hint_metrics_from_ruby_object   (VALUE obj);
cairo_path_data_type_t rb_cairo_path_data_type_from_ruby_object (VALUE obj);
cairo_content_t        rb_cairo_content_from_ruby_object        (VALUE obj);
cairo_format_t         rb_cairo_format_from_ruby_object         (VALUE obj);
cairo_extend_t         rb_cairo_extend_from_ruby_object         (VALUE obj);
cairo_filter_t         rb_cairo_filter_from_ruby_object         (VALUE obj);
#if CAIRO_HAS_SVG_SURFACE
cairo_svg_version_t    rb_cairo_svg_version_from_ruby_object    (VALUE obj);
#endif

void rb_cairo_check_status (cairo_status_t status);


#define RB_CAIRO_DEF_SETTERS(klass) rb_cairo_def_setters(klass);
void rb_cairo_def_setters (VALUE klass);

#endif

--- NEW FILE: rb_cairo_constants.c ---
/* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
 * Ruby Cairo Binding
 *
 * $Author: kou $
 * $Date: 2007/03/06 12:17:34 $
 *
 * Copyright 2005 Øyvind Kolås <pippin at freedesktop.org>
 * Copyright 2004-2005 MenTaLguY <mental at rydia.com>
 *
 * This file is made available under the same terms as Ruby
 *
*/


#include "rb_cairo.h"

#define CAIRO_OPERATOR_MIN CAIRO_OPERATOR_CLEAR
#define CAIRO_OPERATOR_MAX CAIRO_OPERATOR_SATURATE

#define CAIRO_ANTIALIAS_MIN CAIRO_ANTIALIAS_DEFAULT
#define CAIRO_ANTIALIAS_MAX CAIRO_ANTIALIAS_SUBPIXEL

#define CAIRO_FILL_RULE_MIN CAIRO_FILL_RULE_WINDING
#define CAIRO_FILL_RULE_MAX CAIRO_FILL_RULE_EVEN_ODD

#define CAIRO_LINE_CAP_MIN CAIRO_LINE_CAP_BUTT
#define CAIRO_LINE_CAP_MAX CAIRO_LINE_CAP_SQUARE

#define CAIRO_LINE_JOIN_MIN CAIRO_LINE_JOIN_MITER
#define CAIRO_LINE_JOIN_MAX CAIRO_LINE_JOIN_BEVEL

#define CAIRO_FONT_SLANT_MIN CAIRO_FONT_SLANT_NORMAL
#define CAIRO_FONT_SLANT_MAX CAIRO_FONT_SLANT_OBLIQUE

#define CAIRO_FONT_WEIGHT_MIN CAIRO_FONT_WEIGHT_NORMAL
#define CAIRO_FONT_WEIGHT_MAX CAIRO_FONT_WEIGHT_BOLD

#define CAIRO_SUBPIXEL_ORDER_MIN CAIRO_SUBPIXEL_ORDER_DEFAULT
#define CAIRO_SUBPIXEL_ORDER_MAX CAIRO_SUBPIXEL_ORDER_VBGR

#define CAIRO_HINT_STYLE_MIN CAIRO_HINT_STYLE_DEFAULT
#define CAIRO_HINT_STYLE_MAX CAIRO_HINT_STYLE_FULL

#define CAIRO_HINT_METRICS_MIN CAIRO_HINT_METRICS_DEFAULT
#define CAIRO_HINT_METRICS_MAX CAIRO_HINT_METRICS_OFF

#define CAIRO_PATH_MIN CAIRO_PATH_MOVE_TO
#define CAIRO_PATH_MAX CAIRO_PATH_CLOSE_PATH

#define CAIRO_CONTENT_MIN CAIRO_CONTENT_COLOR
#define CAIRO_CONTENT_MAX CAIRO_CONTENT_COLOR_ALPHA

#define CAIRO_FORMAT_MIN CAIRO_FORMAT_ARGB32
#define CAIRO_FORMAT_MAX CAIRO_FORMAT_A1

#define CAIRO_EXTEND_MIN CAIRO_EXTEND_NONE
#define CAIRO_EXTEND_MAX CAIRO_EXTEND_REFLECT

#define CAIRO_FILTER_MIN CAIRO_FILTER_FAST
#define CAIRO_FILTER_MAX CAIRO_FILTER_GAUSSIAN

#define CAIRO_SVG_VERSION_MIN CAIRO_SVG_VERSION_1_1
#define CAIRO_SVG_VERSION_MAX CAIRO_SVG_VERSION_1_2

#define DEFINE_RVAL2ENUM(name, const_name)                  \
cairo_ ## name ## _t                                        \
rb_cairo_ ## name ## _from_ruby_object (VALUE rb_ ## name)  \
{                                                           \
  cairo_ ## name ## _t name;                                \
  name = FIX2INT (rb_ ## name);                             \
  if (name < CAIRO_ ## const_name ## _MIN ||                \
      name > CAIRO_ ## const_name ## _MAX)                  \
    {                                                       \
      rb_raise (rb_eArgError,                               \
                "invalid %s: %d (expect %d <= %s <= %d)",   \
                #name, name,                                \
                CAIRO_ ## const_name ## _MIN,               \
                #name,                                      \
                CAIRO_ ## const_name ## _MAX);              \
    }                                                       \
  return name;                                              \
}

DEFINE_RVAL2ENUM(operator, OPERATOR)
DEFINE_RVAL2ENUM(antialias, ANTIALIAS)
DEFINE_RVAL2ENUM(fill_rule, FILL_RULE)
DEFINE_RVAL2ENUM(line_cap, LINE_CAP)
DEFINE_RVAL2ENUM(line_join, LINE_JOIN)
DEFINE_RVAL2ENUM(font_slant, FONT_SLANT)
DEFINE_RVAL2ENUM(font_weight, FONT_WEIGHT)
DEFINE_RVAL2ENUM(subpixel_order, SUBPIXEL_ORDER)
DEFINE_RVAL2ENUM(hint_style, HINT_STYLE)
DEFINE_RVAL2ENUM(hint_metrics, HINT_METRICS)
DEFINE_RVAL2ENUM(path_data_type, PATH)
DEFINE_RVAL2ENUM(content, CONTENT)
DEFINE_RVAL2ENUM(format, FORMAT)
DEFINE_RVAL2ENUM(extend, EXTEND)
DEFINE_RVAL2ENUM(filter, FILTER)
#if CAIRO_HAS_SVG_SURFACE
DEFINE_RVAL2ENUM(svg_version, SVG_VERSION)
#endif

void
Init_cairo_constants (void)
{
  /* cairo_operator_t */
  rb_define_const (rb_mCairo,    "OPERATOR_CLEAR",
                   INT2FIX (CAIRO_OPERATOR_CLEAR));

  rb_define_const (rb_mCairo,    "OPERATOR_SOURCE",
                   INT2FIX (CAIRO_OPERATOR_SOURCE));
  rb_define_const (rb_mCairo,    "OPERATOR_OVER",
                   INT2FIX (CAIRO_OPERATOR_OVER));
  rb_define_const (rb_mCairo,    "OPERATOR_IN",
                   INT2FIX (CAIRO_OPERATOR_IN));
  rb_define_const (rb_mCairo,    "OPERATOR_OUT",
                   INT2FIX (CAIRO_OPERATOR_OUT));
  rb_define_const (rb_mCairo,    "OPERATOR_ATOP",
                   INT2FIX (CAIRO_OPERATOR_ATOP));
  
  rb_define_const (rb_mCairo,    "OPERATOR_DEST",
                   INT2FIX (CAIRO_OPERATOR_DEST));
  rb_define_const (rb_mCairo,    "OPERATOR_DEST_OVER",
                   INT2FIX (CAIRO_OPERATOR_DEST_OVER));
  rb_define_const (rb_mCairo,    "OPERATOR_DEST_IN",
                   INT2FIX (CAIRO_OPERATOR_DEST_IN));
  rb_define_const (rb_mCairo,    "OPERATOR_DEST_OUT",
                   INT2FIX (CAIRO_OPERATOR_DEST_OUT));
  rb_define_const (rb_mCairo,    "OPERATOR_DEST_ATOP",
                   INT2FIX (CAIRO_OPERATOR_DEST_ATOP));

  rb_define_const (rb_mCairo,    "OPERATOR_XOR",
                   INT2FIX (CAIRO_OPERATOR_XOR));
  rb_define_const (rb_mCairo,    "OPERATOR_ADD",
                   INT2FIX (CAIRO_OPERATOR_ADD));
  rb_define_const (rb_mCairo,    "OPERATOR_SATURATE",
                   INT2FIX (CAIRO_OPERATOR_SATURATE));

  
  /* cairo_antialias_t */
  rb_define_const (rb_mCairo,    "ANTIALIAS_DEFAULT",
                   INT2FIX (CAIRO_ANTIALIAS_DEFAULT));
  rb_define_const (rb_mCairo,    "ANTIALIAS_NONE",
                   INT2FIX (CAIRO_ANTIALIAS_NONE));
  rb_define_const (rb_mCairo,    "ANTIALIAS_GRAY",
                   INT2FIX (CAIRO_ANTIALIAS_GRAY));
  rb_define_const (rb_mCairo,    "ANTIALIAS_SUBPIXEL",
                   INT2FIX (CAIRO_ANTIALIAS_SUBPIXEL));


  /* cairo_fill_rule_t */
  rb_define_const (rb_mCairo,    "FILL_RULE_WINDING",
                   INT2FIX (CAIRO_FILL_RULE_WINDING));
  rb_define_const (rb_mCairo,    "FILL_RULE_EVEN_ODD",
                   INT2FIX (CAIRO_FILL_RULE_EVEN_ODD));


  /* cairo_line_cap_t */
  rb_define_const (rb_mCairo,    "LINE_CAP_BUTT",
                   INT2FIX (CAIRO_LINE_CAP_BUTT));
  rb_define_const (rb_mCairo,    "LINE_CAP_ROUND",
                   INT2FIX (CAIRO_LINE_CAP_ROUND));
  rb_define_const (rb_mCairo,    "LINE_CAP_SQUARE",
                   INT2FIX (CAIRO_LINE_CAP_SQUARE));


  /* cairo_line_join_t */
  rb_define_const (rb_mCairo,    "LINE_JOIN_MITER",
                   INT2FIX (CAIRO_LINE_JOIN_MITER));
  rb_define_const (rb_mCairo,    "LINE_JOIN_ROUND",
                   INT2FIX (CAIRO_LINE_JOIN_ROUND));
  rb_define_const (rb_mCairo,    "LINE_JOIN_BEVEL",
                   INT2FIX (CAIRO_LINE_JOIN_BEVEL));


  /* cairo_font_slant_t */
  rb_define_const (rb_mCairo,    "FONT_SLANT_NORMAL",
                   INT2FIX (CAIRO_FONT_SLANT_NORMAL));
  rb_define_const (rb_mCairo,    "FONT_SLANT_ITALIC",
                   INT2FIX (CAIRO_FONT_SLANT_ITALIC));
  rb_define_const (rb_mCairo,    "FONT_SLANT_OBLIQUE",
                   INT2FIX (CAIRO_FONT_SLANT_OBLIQUE));


  /* cairo_font_weight_t */
  rb_define_const (rb_mCairo,    "FONT_WEIGHT_NORMAL",
                   INT2FIX (CAIRO_FONT_WEIGHT_NORMAL));
  rb_define_const (rb_mCairo,    "FONT_WEIGHT_BOLD",
                   INT2FIX (CAIRO_FONT_WEIGHT_BOLD));
  

  /* cairo_subpixel_order_t */
  rb_define_const (rb_mCairo,    "SUBPIXEL_ORDER_DEFAULT",
                   INT2FIX (CAIRO_SUBPIXEL_ORDER_DEFAULT));
  rb_define_const (rb_mCairo,    "SUBPIXEL_ORDER_RGB",
                   INT2FIX (CAIRO_SUBPIXEL_ORDER_RGB));
  rb_define_const (rb_mCairo,    "SUBPIXEL_ORDER_BGR",
                   INT2FIX (CAIRO_SUBPIXEL_ORDER_BGR));
  rb_define_const (rb_mCairo,    "SUBPIXEL_ORDER_VRGB",
                   INT2FIX (CAIRO_SUBPIXEL_ORDER_VRGB));
  rb_define_const (rb_mCairo,    "SUBPIXEL_ORDER_VBGR",
                   INT2FIX (CAIRO_SUBPIXEL_ORDER_VBGR));
  

  /* cairo_hint_style_t */
  rb_define_const (rb_mCairo,    "HINT_STYLE_DEFAULT",
                   INT2FIX (CAIRO_HINT_STYLE_DEFAULT));
  rb_define_const (rb_mCairo,    "HINT_STYLE_NONE",
                   INT2FIX (CAIRO_HINT_STYLE_NONE));
  rb_define_const (rb_mCairo,    "HINT_STYLE_SLIGHT",
                   INT2FIX (CAIRO_HINT_STYLE_SLIGHT));
  rb_define_const (rb_mCairo,    "HINT_STYLE_MEDIUM",
                   INT2FIX (CAIRO_HINT_STYLE_MEDIUM));
  rb_define_const (rb_mCairo,    "HINT_STYLE_FULL",
                   INT2FIX (CAIRO_HINT_STYLE_FULL));


  /* cairo_hint_metrics_t */
  rb_define_const (rb_mCairo,    "HINT_METRICS_DEFAULT",
                   INT2FIX (CAIRO_HINT_METRICS_DEFAULT));
  rb_define_const (rb_mCairo,    "HINT_METRICS_ON",
                   INT2FIX (CAIRO_HINT_METRICS_ON));
  rb_define_const (rb_mCairo,    "HINT_METRICS_OFF",
                   INT2FIX (CAIRO_HINT_METRICS_OFF));


  /* cairo_font_type_t */
  rb_define_const (rb_mCairo, "FONT_TYPE_TOY", INT2FIX(CAIRO_FONT_TYPE_TOY));
  rb_define_const (rb_mCairo, "FONT_TYPE_FT", INT2FIX(CAIRO_FONT_TYPE_FT));
  rb_define_const (rb_mCairo, "FONT_TYPE_WIN32",
                   INT2FIX(CAIRO_FONT_TYPE_WIN32));
  rb_define_const (rb_mCairo, "FONT_TYPE_ATSUI",
                   INT2FIX(CAIRO_FONT_TYPE_ATSUI));


  /* cairo_path_data_type_t */
  rb_define_const (rb_mCairo,    "PATH_MOVE_TO",
                   INT2FIX (CAIRO_PATH_MOVE_TO));
  rb_define_const (rb_mCairo,    "PATH_LINE_TO",
                   INT2FIX (CAIRO_PATH_LINE_TO));
  rb_define_const (rb_mCairo,    "PATH_CURVE_TO",
                   INT2FIX (CAIRO_PATH_CURVE_TO));
  rb_define_const (rb_mCairo,    "PATH_CLOSE_PATH",
                   INT2FIX (CAIRO_PATH_CLOSE_PATH));


  /* cairo_content_t */
  rb_define_const (rb_mCairo,    "CONTENT_COLOR",
                   INT2FIX (CAIRO_CONTENT_COLOR));
  rb_define_const (rb_mCairo,    "CONTENT_ALPHA",
                   INT2FIX (CAIRO_CONTENT_ALPHA));
  rb_define_const (rb_mCairo,    "CONTENT_COLOR_ALPHA",
                   INT2FIX (CAIRO_CONTENT_COLOR_ALPHA));


  /* cairo_surface_type_t */
  rb_define_const (rb_mCairo, "SURFACE_TYPE_IMAGE",
                   INT2FIX (CAIRO_SURFACE_TYPE_IMAGE));
  rb_define_const (rb_mCairo, "SURFACE_TYPE_PDF",
                   INT2FIX (CAIRO_SURFACE_TYPE_PDF));
  rb_define_const (rb_mCairo, "SURFACE_TYPE_PS",
                   INT2FIX (CAIRO_SURFACE_TYPE_PS));
  rb_define_const (rb_mCairo, "SURFACE_TYPE_XLIB",
                   INT2FIX (CAIRO_SURFACE_TYPE_XLIB));
  rb_define_const (rb_mCairo, "SURFACE_TYPE_XCB",
                   INT2FIX (CAIRO_SURFACE_TYPE_XCB));
  rb_define_const (rb_mCairo, "SURFACE_TYPE_GLITZ",
                   INT2FIX (CAIRO_SURFACE_TYPE_GLITZ));
  rb_define_const (rb_mCairo, "SURFACE_TYPE_QUARTZ",
                   INT2FIX (CAIRO_SURFACE_TYPE_QUARTZ));
  rb_define_const (rb_mCairo, "SURFACE_TYPE_WIN32",
                   INT2FIX (CAIRO_SURFACE_TYPE_WIN32));
  rb_define_const (rb_mCairo, "SURFACE_TYPE_BEOS",
                   INT2FIX (CAIRO_SURFACE_TYPE_BEOS));
  rb_define_const (rb_mCairo, "SURFACE_TYPE_DIRECTFB",
                   INT2FIX (CAIRO_SURFACE_TYPE_DIRECTFB));
  rb_define_const (rb_mCairo, "SURFACE_TYPE_SVG",
                   INT2FIX (CAIRO_SURFACE_TYPE_SVG));
#if CAIRO_CHECK_VERSION(1, 3, 0)
  rb_define_const (rb_mCairo, "SURFACE_TYPE_OS2",
                   INT2FIX (CAIRO_SURFACE_TYPE_OS2));
#endif

  /* cairo_format_t */
  rb_define_const (rb_mCairo,    "FORMAT_ARGB32",
                   INT2FIX (CAIRO_FORMAT_ARGB32));
  rb_define_const (rb_mCairo,    "FORMAT_RGB24",
                   INT2FIX (CAIRO_FORMAT_RGB24));
  rb_define_const (rb_mCairo,    "FORMAT_A8",
                   INT2FIX (CAIRO_FORMAT_A8));
  rb_define_const (rb_mCairo,    "FORMAT_A1",
                   INT2FIX (CAIRO_FORMAT_A1));
#if !CAIRO_CHECK_VERSION(1, 3, 0)
  rb_define_const (rb_mCairo,    "FORMAT_RGB16_565",
                   INT2FIX (CAIRO_FORMAT_RGB16_565));
#endif


  /* cairo_pattern_type_t */
  rb_define_const (rb_mCairo, "PATTERN_TYPE_SOLID",
                   INT2FIX (CAIRO_PATTERN_TYPE_SOLID));
  rb_define_const (rb_mCairo, "PATTERN_TYPE_SURFACE",
                   INT2FIX (CAIRO_PATTERN_TYPE_SURFACE));
  rb_define_const (rb_mCairo, "PATTERN_TYPE_LINEAR",
                   INT2FIX (CAIRO_PATTERN_TYPE_LINEAR));
  rb_define_const (rb_mCairo, "PATTERN_TYPE_RADIAL",
                   INT2FIX (CAIRO_PATTERN_TYPE_RADIAL));

  /* cairo_extend_t */
  rb_define_const (rb_mCairo,    "EXTEND_NONE",
                   INT2FIX (CAIRO_EXTEND_NONE));
  rb_define_const (rb_mCairo,    "EXTEND_REPEAT",
                   INT2FIX (CAIRO_EXTEND_REPEAT));
  rb_define_const (rb_mCairo,    "EXTEND_REFLECT",
                   INT2FIX (CAIRO_EXTEND_REFLECT));
  rb_define_const (rb_mCairo,    "EXTEND_PAD",
                   INT2FIX (CAIRO_EXTEND_PAD));


  /* cairo_filter_t */
  rb_define_const (rb_mCairo,    "FILTER_FAST",
                   INT2FIX (CAIRO_FILTER_FAST));
  rb_define_const (rb_mCairo,    "FILTER_GOOD",
                   INT2FIX (CAIRO_FILTER_GOOD));
  rb_define_const (rb_mCairo,    "FILTER_BEST",
                   INT2FIX (CAIRO_FILTER_BEST));
  rb_define_const (rb_mCairo,    "FILTER_NEAREST",
                   INT2FIX (CAIRO_FILTER_NEAREST));
  rb_define_const (rb_mCairo,    "FILTER_BILINEAR",
                   INT2FIX (CAIRO_FILTER_BILINEAR));
  rb_define_const (rb_mCairo,    "FILTER_GAUSSIAN",
                   INT2FIX (CAIRO_FILTER_GAUSSIAN));

#if CAIRO_HAS_SVG_SURFACE
  /* cairo_svg_version_t */
  rb_define_const (rb_mCairo,    "SVG_VERSION_1_1",
                   INT2FIX (CAIRO_SVG_VERSION_1_1));
  rb_define_const (rb_mCairo,    "SVG_VERSION_1_2",
                   INT2FIX (CAIRO_SVG_VERSION_1_2));
#endif
}

--- NEW FILE: rb_cairo_context.c ---
/* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
 * Ruby Cairo Binding
 *
 * $Author: kou $
 * $Date: 2007/03/06 12:17:34 $
 *
 * Copyright 2005 Øyvind Kolås <pippin at freedesktop.org>
 * Copyright 2004-2005 MenTaLguY <mental at rydia.com>
 *
 * This file is made available under the same terms as Ruby
 *
*/

#include "rb_cairo.h"
#include "rb_cairo_private.h"

VALUE rb_cCairo_Context;

[...1360 lines suppressed...]
  rb_define_method (rb_cCairo_Context, "fill_rule", cr_get_fill_rule, 0);
  rb_define_method (rb_cCairo_Context, "line_width", cr_get_line_width, 0);
  rb_define_method (rb_cCairo_Context, "line_cap", cr_get_line_cap, 0);
  rb_define_method (rb_cCairo_Context, "line_join", cr_get_line_join, 0);
  rb_define_method (rb_cCairo_Context, "miter_limit", cr_get_miter_limit, 0);
#if CAIRO_CHECK_VERSION(1, 3, 0)
  rb_define_method (rb_cCairo_Context, "dash_count", cr_get_dash_count, 0);
  rb_define_method (rb_cCairo_Context, "dash", cr_get_dash, 0);
#endif
  rb_define_method (rb_cCairo_Context, "matrix", cr_get_matrix, 0);
  rb_define_method (rb_cCairo_Context, "target", cr_get_target, 0);
  rb_define_method (rb_cCairo_Context, "group_target", cr_get_group_target, 0);

  /* Paths */
  rb_define_method (rb_cCairo_Context, "copy_path", cr_copy_path, 0);
  rb_define_method (rb_cCairo_Context, "copy_path_flat", cr_copy_path_flat, 0);
  rb_define_method (rb_cCairo_Context, "append_path", cr_copy_append_path, 1);

  RB_CAIRO_DEF_SETTERS (rb_cCairo_Context);
}

--- NEW FILE: rb_cairo_exception.c ---
/* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
 * Ruby Cairo Binding
 *
 * $Author: kou $
 * $Date: 2007/03/06 12:17:34 $
 *
 * Copyright 2005 Øyvind Kolås <pippin at freedesktop.org>
 * Copyright 2004-2005 MenTaLguY <mental at rydia.com>
 *
 * This file is made available under the same terms as Ruby
 *
*/

#include "rb_cairo.h"

static VALUE rb_eCairo_InvalidRestoreError;
static VALUE rb_eCairo_InvalidPopGroupError;
static VALUE rb_eCairo_NoCurrentPointError;
static VALUE rb_eCairo_InvalidMatrixError;
static VALUE rb_eCairo_InvalidStatusError;
static VALUE rb_eCairo_NullPointerError;
static VALUE rb_eCairo_InvalidStringError;
static VALUE rb_eCairo_InvalidPathDataError;
static VALUE rb_eCairo_ReadError;
static VALUE rb_eCairo_WriteError;
static VALUE rb_eCairo_SurfaceFinishedError;
static VALUE rb_eCairo_SurfaceTypeMismatchError;
static VALUE rb_eCairo_PatternTypeMismatchError;
static VALUE rb_eCairo_InvalidContentError;
static VALUE rb_eCairo_InvalidFormatError;
static VALUE rb_eCairo_InvalidVisualError;
static VALUE rb_eCairo_FileNotFoundError;
static VALUE rb_eCairo_InvalidDashError;
static VALUE rb_eCairo_InvalidDscCommentError;
#if CAIRO_CHECK_VERSION(1, 3, 0)
static VALUE rb_eCairo_InvalidIndexError;
static VALUE rb_eCairo_ClipNotRepresentableError;
#endif

void
rb_cairo_check_status (cairo_status_t status)
{
  const char *string = cairo_status_to_string (status);
  
  switch (status)
    {
    case CAIRO_STATUS_SUCCESS:
      break;
    case CAIRO_STATUS_NO_MEMORY:
      rb_raise (rb_eNoMemError, string);
      break;
    case CAIRO_STATUS_INVALID_RESTORE:
      rb_raise (rb_eCairo_InvalidRestoreError, string);
      break;
    case CAIRO_STATUS_INVALID_POP_GROUP:
      rb_raise (rb_eCairo_InvalidPopGroupError, string);
      break;
    case CAIRO_STATUS_NO_CURRENT_POINT:
      rb_raise (rb_eCairo_NoCurrentPointError, string);
      break;
    case CAIRO_STATUS_INVALID_MATRIX:
      rb_raise (rb_eCairo_InvalidMatrixError, string);
      break;
    case CAIRO_STATUS_INVALID_STATUS:
      rb_raise (rb_eCairo_InvalidStatusError, string);
      break;
    case CAIRO_STATUS_NULL_POINTER:
      rb_raise (rb_eCairo_NullPointerError, string);
      break;
    case CAIRO_STATUS_INVALID_STRING:
      rb_raise (rb_eCairo_InvalidStringError, string);
      break;
    case CAIRO_STATUS_INVALID_PATH_DATA:
      rb_raise (rb_eCairo_InvalidPathDataError, string);
      break;
    case CAIRO_STATUS_READ_ERROR:
      rb_raise (rb_eCairo_ReadError, string);
      break;
    case CAIRO_STATUS_WRITE_ERROR:
      rb_raise (rb_eCairo_WriteError, string);
      break;
    case CAIRO_STATUS_SURFACE_FINISHED:
      rb_raise (rb_eCairo_SurfaceFinishedError, string);
      break;
    case CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
      rb_raise (rb_eCairo_SurfaceTypeMismatchError, string);
      break;
    case CAIRO_STATUS_PATTERN_TYPE_MISMATCH:
      rb_raise (rb_eCairo_PatternTypeMismatchError, string);
      break;
    case CAIRO_STATUS_INVALID_CONTENT:
      rb_raise (rb_eCairo_InvalidContentError, string);
      break;
    case CAIRO_STATUS_INVALID_FORMAT:
      rb_raise (rb_eCairo_InvalidFormatError, string);
      break;
    case CAIRO_STATUS_INVALID_VISUAL:
      rb_raise (rb_eCairo_InvalidVisualError, string);
      break;
    case CAIRO_STATUS_FILE_NOT_FOUND:
      rb_raise (rb_eCairo_FileNotFoundError, string);
      break;
    case CAIRO_STATUS_INVALID_DASH:
      rb_raise (rb_eCairo_InvalidDashError, string);
      break;
    case CAIRO_STATUS_INVALID_DSC_COMMENT:
      rb_raise (rb_eCairo_InvalidDscCommentError, string);
      break;
#if CAIRO_CHECK_VERSION(1, 3, 0)
    case CAIRO_STATUS_INVALID_INDEX:
      rb_raise (rb_eCairo_InvalidIndexError, string);
      break;
    case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE:
      rb_raise (rb_eCairo_ClipNotRepresentableError, string);
      break;
#endif
    }
}

void
Init_cairo_exception ()
{
  VALUE rb_eCairo_Error;
  rb_eCairo_Error =
    rb_define_class_under (rb_mCairo, "Error", rb_eStandardError);
  rb_eCairo_InvalidRestoreError =
    rb_define_class_under (rb_mCairo, "InvalidRestoreError",
                           rb_eCairo_Error);
  rb_eCairo_InvalidPopGroupError =
    rb_define_class_under (rb_mCairo, "InvalidPopGroupError",
                           rb_eCairo_Error);
  rb_eCairo_NoCurrentPointError =
    rb_define_class_under (rb_mCairo, "NoCurrentPointError",
                           rb_eCairo_Error);
  rb_eCairo_InvalidMatrixError =
    rb_define_class_under (rb_mCairo, "InvalidMatrixError",
                           rb_eArgError);
  rb_eCairo_InvalidStatusError =
    rb_define_class_under (rb_mCairo, "InvalidStatusError",
                           rb_eArgError);
  rb_eCairo_NullPointerError =
    rb_define_class_under (rb_mCairo, "NullPointerError",
                           rb_eTypeError);
  rb_eCairo_InvalidStringError =
    rb_define_class_under (rb_mCairo, "InvalidStringError",
                           rb_eArgError);
  rb_eCairo_InvalidPathDataError =
    rb_define_class_under (rb_mCairo, "InvalidPathDataError",
                           rb_eArgError);
  rb_eCairo_ReadError =
    rb_define_class_under (rb_mCairo, "ReadError",
                           rb_eIOError);
  rb_eCairo_WriteError =
    rb_define_class_under (rb_mCairo, "WriteError",
                           rb_eIOError);
  rb_eCairo_SurfaceFinishedError =
    rb_define_class_under (rb_mCairo, "SurfaceFinishedError",
                           rb_eCairo_Error);
  rb_eCairo_SurfaceTypeMismatchError =
    rb_define_class_under (rb_mCairo, "SurfaceTypeMismatchError",
                           rb_eTypeError);
  rb_eCairo_PatternTypeMismatchError =
    rb_define_class_under (rb_mCairo, "PatternTypeMismatchError",
                           rb_eTypeError);
  rb_eCairo_InvalidContentError =
    rb_define_class_under (rb_mCairo, "InvalidContentError",
                           rb_eArgError);
  rb_eCairo_InvalidFormatError =
    rb_define_class_under (rb_mCairo, "InvalidFormatError",
                           rb_eArgError);
  rb_eCairo_InvalidVisualError =
    rb_define_class_under (rb_mCairo, "InvalidVisualError",
                           rb_eArgError);
  rb_eCairo_FileNotFoundError =
    rb_define_class_under (rb_mCairo, "FileNotFound",
                           rb_eCairo_Error);
  rb_eCairo_InvalidDashError =
    rb_define_class_under (rb_mCairo, "InvalidDashError",
                           rb_eArgError);
  rb_eCairo_InvalidDscCommentError =
    rb_define_class_under (rb_mCairo, "InvalidDscCommentError",
                           rb_eArgError);
#if CAIRO_CHECK_VERSION(1, 3, 0)
  rb_eCairo_InvalidIndexError =
    rb_define_class_under (rb_mCairo, "InvalidIndexError",
                           rb_eArgError);
  rb_eCairo_ClipNotRepresentableError =
    rb_define_class_under (rb_mCairo, "ClipNotRepresentableError",
                           rb_eCairo_Error);
#endif
}

--- NEW FILE: rb_cairo_font_extents.c ---
/* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
 * Ruby Cairo Binding
 *
 * $Author: kou $
 * $Date: 2007/03/06 12:17:34 $
 *
 * Copyright 2005 Øyvind Kolås <pippin at freedesktop.org>
 * Copyright 2004-2005 MenTaLguY <mental at rydia.com>
 *
 * This file is made available under the same terms as Ruby
 *
 */

#include "rb_cairo.h"

VALUE rb_cCairo_FontExtents;

#define _SELF(self)  (RVAL2CRFONTEXTENTS(self))

cairo_font_extents_t *
rb_cairo_font_extents_from_ruby_object (VALUE obj)
{
  cairo_font_extents_t *extents;
  if (!RTEST (rb_obj_is_kind_of (obj, rb_cCairo_FontExtents)))
    {
      rb_raise (rb_eTypeError, "not a cairo font extents");
    }
  Data_Get_Struct (obj, cairo_font_extents_t, extents);
  return extents;
}

VALUE
rb_cairo_font_extents_to_ruby_object (cairo_font_extents_t *extents)
{
  if (extents)
    {
      cairo_font_extents_t *new_extents = ALLOC (cairo_font_extents_t);
      *new_extents = *extents;
      return Data_Wrap_Struct (rb_cCairo_FontExtents, NULL, -1, new_extents);
    }
  else
    {
      return Qnil;
    }
}

static    VALUE
cr_font_extents_ascent (VALUE self)
{
  return rb_float_new (_SELF(self)->ascent);
}

static    VALUE
cr_font_extents_descent (VALUE self)
{
  return rb_float_new (_SELF(self)->descent);
}

static    VALUE
cr_font_extents_height (VALUE self)
{
  return rb_float_new (_SELF(self)->height);
}

static    VALUE
cr_font_extents_max_x_advance (VALUE self)
{
  return rb_float_new (_SELF(self)->max_x_advance);
}

static    VALUE
cr_font_extents_max_y_advance (VALUE self)
{
  return rb_float_new (_SELF(self)->max_y_advance);
}

static VALUE
cr_font_extents_to_s (VALUE self)
{
  VALUE ret;

  ret = rb_str_new2 ("#<");
  rb_str_cat2 (ret, rb_class2name (CLASS_OF (self)));
  rb_str_cat2 (ret, ": ");
  rb_str_cat2 (ret, "ascent=");
  rb_str_concat (ret, rb_inspect (cr_font_extents_ascent (self)));
  rb_str_cat2 (ret, ", ");
  rb_str_cat2 (ret, "descent=");
  rb_str_concat (ret, rb_inspect (cr_font_extents_descent (self)));
  rb_str_cat2 (ret, ", ");
  rb_str_cat2 (ret, "height=");
  rb_str_concat (ret, rb_inspect (cr_font_extents_height (self)));
  rb_str_cat2 (ret, ", ");
  rb_str_cat2 (ret, "max_x_advance=");
  rb_str_concat (ret, rb_inspect (cr_font_extents_max_x_advance (self)));
  rb_str_cat2 (ret, ", ");
  rb_str_cat2 (ret, "max_y_advance=");
  rb_str_concat (ret, rb_inspect (cr_font_extents_max_y_advance (self)));
  rb_str_cat2 (ret, ">");
                 
  return ret;
}


void
Init_cairo_font_extents (void)
{
  rb_cCairo_FontExtents =
    rb_define_class_under (rb_mCairo, "FontExtents", rb_cObject);

  rb_define_method (rb_cCairo_FontExtents, "ascent",
                    cr_font_extents_ascent, 0);
  rb_define_method (rb_cCairo_FontExtents, "descent",
                    cr_font_extents_descent, 0);
  rb_define_method (rb_cCairo_FontExtents, "height",
                    cr_font_extents_height, 0);
  rb_define_method (rb_cCairo_FontExtents, "max_x_advance",
                    cr_font_extents_max_x_advance, 0);
  rb_define_method (rb_cCairo_FontExtents, "max_y_advance",
                    cr_font_extents_max_y_advance, 0);

  rb_define_method (rb_cCairo_FontExtents, "to_s", cr_font_extents_to_s, 0);
}

--- NEW FILE: rb_cairo_font_face.c ---
/* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
 * Ruby Cairo Binding
 *
 * $Author: kou $
 * $Date: 2007/03/06 12:17:34 $
 *
 * Copyright 2005 Øyvind Kolås <pippin at freedesktop.org>
 * Copyright 2004-2005 MenTaLguY <mental at rydia.com>
 *
 * This file is made available under the same terms as Ruby
 *
*/


#include "rb_cairo.h"

VALUE rb_cCairo_FontFace;

#define _SELF  (RVAL2CRFONTFACE(self))

cairo_font_face_t *
rb_cairo_font_face_from_ruby_object (VALUE obj)
{
  cairo_font_face_t *face;
  if (!RTEST (rb_obj_is_kind_of (obj, rb_cCairo_FontFace)))
    {
      rb_raise (rb_eTypeError, "not a cairo font face");
    }
  Data_Get_Struct (obj, cairo_font_face_t, face);
  return face;
}

VALUE
rb_cairo_font_face_to_ruby_object (cairo_font_face_t *face)
{
  if (face)
    {
      cairo_font_face_reference (face);
      return Data_Wrap_Struct (rb_cCairo_FontFace, NULL,
                               cairo_font_face_destroy, face);
    }
  else
    {
      return Qnil;
    }
}

static VALUE
cr_font_face_get_type (VALUE self)
{
  return INT2NUM ( cairo_font_face_get_type (_SELF));
}


void
Init_cairo_font (void)
{
  rb_cCairo_FontFace =
    rb_define_class_under (rb_mCairo, "FontFace", rb_cObject);

  rb_define_method (rb_cCairo_FontFace, "type", cr_font_face_get_type, 0);
}

--- NEW FILE: rb_cairo_font_options.c ---
/* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
 * Ruby Cairo Binding
 *
 * $Author: kou $
 * $Date: 2007/03/06 12:17:34 $
 *
 * Copyright 2005 Kouhei Sutou <kou at cozmixng.org>
 *
 * This file is made available under the same terms as Ruby
 *
 */

#include "rb_cairo.h"

#define _SELF(self) (RVAL2CRFONTOPTIONS(self))

VALUE rb_cCairo_FontOptions;

static inline void
cr_options_check_status (cairo_font_options_t *options)
{
  rb_cairo_check_status (cairo_font_options_status (options));
}

cairo_font_options_t *
rb_cairo_font_options_from_ruby_object (VALUE obj)
{
  cairo_font_options_t *options;
  if (!RTEST (rb_obj_is_kind_of (obj, rb_cCairo_FontOptions)))
    {
      rb_raise (rb_eTypeError, "not a cairo font options");
    }
  Data_Get_Struct (obj, cairo_font_options_t, options);
  return options;
}

static void
cr_options_free (void *ptr)
{
  if (ptr)
    {
      cairo_font_options_destroy ((cairo_font_options_t *) ptr);
    }
}

VALUE
rb_cairo_font_options_to_ruby_object (cairo_font_options_t *options)
{
  if (options)
    {
      return Data_Wrap_Struct (rb_cCairo_FontOptions, NULL,
                               cr_options_free, options);
    }
  else
    {
      return Qnil;
    }
}

static VALUE
cr_options_allocate (VALUE klass)
{
  return Data_Wrap_Struct (klass, NULL, cr_options_free, NULL);
}

static VALUE
cr_options_create (VALUE self)
{
  cairo_font_options_t *options;

  options = cairo_font_options_create ();
  cr_options_check_status (options);
  DATA_PTR (self) = options;
  return Qnil;
}

static VALUE
cr_options_copy (VALUE self)
{
  cairo_font_options_t *options;

  options = cairo_font_options_copy (_SELF (self));
  cr_options_check_status (options);
  return CRFONTOPTIONS2RVAL (options);
}

static VALUE
cr_options_merge (VALUE self, VALUE other)
{
  cairo_font_options_merge (_SELF (self), _SELF (other));
  return self;
}

static VALUE
cr_options_equal (VALUE self, VALUE other)
{
  return cairo_font_options_equal (_SELF (self), _SELF (other)) ? Qtrue : Qfalse;
}

static VALUE
cr_options_hash (VALUE self)
{
  return INT2NUM (cairo_font_options_hash (_SELF (self)));
}

static VALUE
cr_options_set_antialias (VALUE self, VALUE antialias)
{
  cairo_font_options_set_antialias (_SELF (self), RVAL2CRANTIALIAS (antialias));
  return self;
}

static VALUE
cr_options_get_antialias (VALUE self)
{
  return INT2NUM (cairo_font_options_get_antialias (_SELF (self)));
}

static VALUE
cr_options_set_subpixel_order (VALUE self, VALUE subpixel_order)
{
  cairo_font_options_set_subpixel_order (_SELF (self),
                                         RVAL2CRSUBPIXELORDER (subpixel_order));
  return self;
}

static VALUE
cr_options_get_subpixel_order (VALUE self)
{
  return INT2NUM (cairo_font_options_get_subpixel_order (_SELF (self)));
}

static VALUE
cr_options_set_hint_style (VALUE self, VALUE hint_style)
{
  cairo_font_options_set_hint_style (_SELF (self),
                                     RVAL2CRHINTSTYLE (hint_style));
  return self;
}

static VALUE
cr_options_get_hint_style (VALUE self)
{
  return INT2NUM (cairo_font_options_get_hint_style (_SELF (self)));
}

static VALUE
cr_options_set_hint_metrics (VALUE self, VALUE hint_metrics)
{
  cairo_font_options_set_hint_metrics (_SELF (self),
                                       RVAL2CRHINTMETRICS (hint_metrics));
  return self;
}

static VALUE
cr_options_get_hint_metrics (VALUE self)
{
  return INT2NUM (cairo_font_options_get_hint_metrics (_SELF (self)));
}


void
Init_cairo_font_options (void)
{
  rb_cCairo_FontOptions =
    rb_define_class_under (rb_mCairo, "FontOptions", rb_cObject);

  rb_define_alloc_func (rb_cCairo_FontOptions, cr_options_allocate);
  
  rb_define_method (rb_cCairo_FontOptions, "initialize", cr_options_create, 0);

  rb_define_method (rb_cCairo_FontOptions, "dup", cr_options_copy, 0);
  rb_define_method (rb_cCairo_FontOptions, "merge", cr_options_merge, 1);
  rb_define_method (rb_cCairo_FontOptions, "eql?", cr_options_equal, 1);
  rb_define_method (rb_cCairo_FontOptions, "hash", cr_options_hash, 0);
  rb_define_method (rb_cCairo_FontOptions, "set_antialias",
                    cr_options_set_antialias, 1);
  rb_define_method (rb_cCairo_FontOptions, "antialias",
                    cr_options_get_antialias, 0);
  rb_define_method (rb_cCairo_FontOptions, "set_subpixel_order",
                    cr_options_set_subpixel_order, 1);
  rb_define_method (rb_cCairo_FontOptions, "subpixel_order",
                    cr_options_get_subpixel_order, 0);
  rb_define_method (rb_cCairo_FontOptions, "set_hint_style",
                    cr_options_set_hint_style, 1);
  rb_define_method (rb_cCairo_FontOptions, "hint_style",
                    cr_options_get_hint_style, 0);
  rb_define_method (rb_cCairo_FontOptions, "set_hint_metrics",
                    cr_options_set_hint_metrics, 1);
  rb_define_method (rb_cCairo_FontOptions, "hint_metrics",
                    cr_options_get_hint_metrics, 0);

  RB_CAIRO_DEF_SETTERS (rb_cCairo_FontOptions);
}

--- NEW FILE: rb_cairo_glyph.c ---
/* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
 * Ruby Cairo Binding
 *
 * $Author: kou $
 * $Date: 2007/03/06 12:17:34 $
 *
 * Copyright 2005 Øyvind Kolås <pippin at freedesktop.org>
 * Copyright 2004-2005 MenTaLguY <mental at rydia.com>
 *
 * This file is made available under the same terms as Ruby
 *
 */


#include "rb_cairo.h"

VALUE rb_cCairo_Glyph;

#define _SELF(self)  (RVAL2CRGLYPH(self))

cairo_glyph_t *
rb_cairo_glyph_from_ruby_object (VALUE obj)
{
  cairo_glyph_t *glyph;
  if (!RTEST (rb_obj_is_kind_of (obj, rb_cCairo_Glyph)))
    {
      rb_raise (rb_eTypeError, "not a cairo glyph");
    }
  Data_Get_Struct (obj, cairo_glyph_t, glyph);
  return glyph;
}

static void
cr_glyph_free (void *ptr)
{
  if (ptr)
    {
      free (ptr);
    }
}

VALUE
rb_cairo_glyph_to_ruby_object (cairo_glyph_t *glyph)
{
  if (glyph)
    {
      cairo_glyph_t *new_glyph = ALLOC (cairo_glyph_t);
      *new_glyph = *glyph;
      return Data_Wrap_Struct (rb_cCairo_Glyph, NULL, cr_glyph_free, new_glyph);
    }
  else
    {
      return Qnil;
    }
}

static VALUE
cr_glyph_allocate (VALUE klass)
{
  return Data_Wrap_Struct (klass, NULL, cr_glyph_free, NULL);
}

static VALUE
cr_glyph_initialize (VALUE self, VALUE index, VALUE x, VALUE y)
{
  cairo_glyph_t *glyph;

  glyph = ALLOC (cairo_glyph_t);
  glyph->index = NUM2ULONG (index);
  glyph->x = NUM2DBL (x);
  glyph->y = NUM2DBL (y);

  DATA_PTR (self) = glyph;
  return Qnil;
}

static VALUE
cr_glyph_index (VALUE self)
{
  return ULONG2NUM (_SELF(self)->index);
}

static VALUE
cr_glyph_x (VALUE self)
{
  return rb_float_new (_SELF(self)->x);
}

static VALUE
cr_glyph_y (VALUE self)
{
  return rb_float_new (_SELF(self)->y);
}

static VALUE
cr_glyph_set_index (VALUE self, VALUE index)
{
  _SELF(self)->index = NUM2ULONG (index);
  return self;
}

static VALUE
cr_glyph_set_x (VALUE self, VALUE x)
{
  _SELF(self)->x = NUM2DBL (x);
  return self;
}

static VALUE
cr_glyph_set_y (VALUE self, VALUE y)
{
  _SELF(self)->y = NUM2DBL (y);
  return self;
}

static VALUE
cr_glyph_to_s (VALUE self)
{
  VALUE ret;

  ret = rb_str_new2 ("#<");
  rb_str_cat2 (ret, rb_class2name (CLASS_OF (self)));
  rb_str_cat2 (ret, ": ");
  rb_str_cat2 (ret, "index=");
  rb_str_concat (ret, rb_inspect (cr_glyph_index (self)));
  rb_str_cat2 (ret, ", ");
  rb_str_cat2 (ret, "x=");
  rb_str_concat (ret, rb_inspect (cr_glyph_x (self)));
  rb_str_cat2 (ret, ", ");
  rb_str_cat2 (ret, "y=");
  rb_str_concat (ret, rb_inspect (cr_glyph_y (self)));
  rb_str_cat2 (ret, ">");
                 
  return ret;
}


void
Init_cairo_glyph (void)
{
  rb_cCairo_Glyph = rb_define_class_under (rb_mCairo, "Glyph", rb_cObject);

  rb_define_alloc_func (rb_cCairo_Glyph, cr_glyph_allocate);

  rb_define_method (rb_cCairo_Glyph, "initialize", cr_glyph_initialize, 3);
  
  rb_define_method (rb_cCairo_Glyph, "index", cr_glyph_index, 0);
  rb_define_method (rb_cCairo_Glyph, "x", cr_glyph_x, 0);
  rb_define_method (rb_cCairo_Glyph, "y", cr_glyph_y, 0);
  rb_define_method (rb_cCairo_Glyph, "set_index", cr_glyph_set_index, 1);
  rb_define_method (rb_cCairo_Glyph, "set_x", cr_glyph_set_x, 1);
  rb_define_method (rb_cCairo_Glyph, "set_y", cr_glyph_set_y, 1);

  rb_define_method (rb_cCairo_Glyph, "to_s", cr_glyph_to_s, 0);

  RB_CAIRO_DEF_SETTERS (rb_cCairo_Glyph);
}

--- NEW FILE: rb_cairo_matrix.c ---
/* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
 * Ruby Cairo Binding
 *
 * $Author: kou $
 * $Date: 2007/03/06 12:17:34 $
 *
 * Copyright 2005 Øyvind Kolås <pippin at freedesktop.org>
 * Copyright 2004-2005 MenTaLguY <mental at rydia.com>
 *
 * This file is made available under the same terms as Ruby
 *
 */


#include "rb_cairo.h"
#include "rb_cairo_private.h"

VALUE rb_cCairo_Matrix;

#define _SELF  (RVAL2CRMATRIX(self))

cairo_matrix_t *
rb_cairo_matrix_from_ruby_object (VALUE obj)
{
  cairo_matrix_t *matrix;
  if (!RTEST (rb_obj_is_kind_of (obj, rb_cCairo_Matrix)))
    {
      rb_raise (rb_eTypeError, "not a cairo matrix");
    }
  Data_Get_Struct (obj, cairo_matrix_t, matrix);
  return matrix;
}

static void
cr_matrix_free (void *ptr)
{
  if (ptr)
    {
      free ((cairo_matrix_t *) ptr);
    }
}

VALUE
rb_cairo_matrix_to_ruby_object (cairo_matrix_t *matrix)
{
  if (matrix)
    {
      cairo_matrix_t *new_matrix = ALLOC (cairo_matrix_t);
      *new_matrix = *matrix;
      return Data_Wrap_Struct (rb_cCairo_Matrix, NULL,
                               cr_matrix_free, new_matrix);
    }
  else
    {
      return Qnil;
    }
}  

static VALUE
cr_matrix_allocate (VALUE klass)
{
  return Data_Wrap_Struct (klass, NULL, cr_matrix_free, NULL);
}

static VALUE
cr_matrix_initialize (VALUE self,
                      VALUE xx, VALUE yx,
                      VALUE xy, VALUE yy,
                      VALUE x0, VALUE y0)
{
  cairo_matrix_t *matrix = ALLOC (cairo_matrix_t);

  cairo_matrix_init (matrix,
                     NUM2DBL (xx), NUM2DBL (yx),
                     NUM2DBL (xy), NUM2DBL (yy),
                     NUM2DBL (x0), NUM2DBL (y0));
  DATA_PTR (self) = matrix;
  return Qnil;
}

static VALUE
cr_matrix_init_identity (VALUE self)
{
  cairo_matrix_t matrix;
  cairo_matrix_init_identity (&matrix);
  return CRMATRIX2RVAL (&matrix);
}

static VALUE
cr_matrix_init_translate (VALUE self, VALUE tx, VALUE ty)
{
  cairo_matrix_t matrix;
  cairo_matrix_init_translate (&matrix, NUM2DBL (tx), NUM2DBL (ty));
  return CRMATRIX2RVAL (&matrix);
}

static VALUE
cr_matrix_init_scale (VALUE self, VALUE sx, VALUE sy)
{
  cairo_matrix_t matrix;
  cairo_matrix_init_scale (&matrix, NUM2DBL (sx), NUM2DBL (sy));
  return CRMATRIX2RVAL (&matrix);
}

static VALUE
cr_matrix_init_rotate (VALUE self, VALUE radius)
{
  cairo_matrix_t matrix;
  cairo_matrix_init_rotate (&matrix, NUM2DBL (radius));
  return CRMATRIX2RVAL (&matrix);
}

static VALUE
cr_matrix_identity (VALUE self)
{
  cairo_matrix_init_identity (_SELF);
  return self;
}

static VALUE
cr_matrix_translate (VALUE self, VALUE tx, VALUE ty)
{
  cairo_matrix_translate (_SELF, NUM2DBL (tx), NUM2DBL (ty));
  return self;
}

static VALUE
cr_matrix_scale (VALUE self, VALUE sx, VALUE sy)
{
  cairo_matrix_scale (_SELF, NUM2DBL (sx), NUM2DBL (sy));
  return self;
}

static VALUE
cr_matrix_rotate (VALUE self, VALUE radians)
{
  cairo_matrix_rotate (_SELF, NUM2DBL (radians));
  return self;
}

static VALUE
cr_matrix_invert (VALUE self)
{
  rb_cairo_check_status (cairo_matrix_invert (_SELF));
  return self;
}

static VALUE
cr_matrix_multiply (VALUE self, VALUE other)
{
  cairo_matrix_multiply (_SELF, _SELF, RVAL2CRMATRIX (other));
  return self;
}

static VALUE
cr_matrix_transform_distance (VALUE self, VALUE dx, VALUE dy)
{
  double pair[2];
  pair[0] = NUM2DBL (dx);
  pair[1] = NUM2DBL (dy);
  cairo_matrix_transform_distance (_SELF, pair, pair + 1);
  return rb_cairo__float_array (pair, 2);
}

static VALUE
cr_matrix_transform_point (VALUE self, VALUE x, VALUE y)
{
  double pair[2];
  pair[0] = NUM2DBL (x);
  pair[1] = NUM2DBL (y);
  cairo_matrix_transform_point (_SELF, pair, pair + 1);
  return rb_cairo__float_array (pair, 2);
}


/* Utilities */
static VALUE
cr_matrix_set (VALUE self,
               VALUE xx, VALUE yx,
               VALUE xy, VALUE yy,
               VALUE x0, VALUE y0)
{
  cairo_matrix_init (_SELF,
                     NUM2DBL (xx), NUM2DBL (yx),
                     NUM2DBL (xy), NUM2DBL (yy),
                     NUM2DBL (x0), NUM2DBL (y0));
  return self;
}

static VALUE
cr_matrix_to_a (VALUE self)
{
  cairo_matrix_t *matrix = _SELF;
  double affine[6];
  affine[0] = matrix->xx;
  affine[1] = matrix->yx;
  affine[2] = matrix->xy;
  affine[3] = matrix->yy;
  affine[4] = matrix->x0;
  affine[5] = matrix->y0;
  return rb_cairo__float_array (affine, 6);
}

static VALUE
cr_matrix_to_s(VALUE self)
{
  VALUE ret;

  ret = rb_str_new2 ("#<");
  rb_str_cat2 (ret, rb_class2name (CLASS_OF (self)));
  rb_str_cat2 (ret, ":");
  rb_str_concat (ret, rb_inspect (cr_matrix_to_a (self)));
  rb_str_cat2 (ret, ">");
  
  return ret;
}


void
Init_cairo_matrix (void)
{
  rb_cCairo_Matrix =
    rb_define_class_under (rb_mCairo, "Matrix", rb_cObject);

  rb_define_alloc_func (rb_cCairo_Matrix, cr_matrix_allocate);

  rb_define_singleton_method (rb_cCairo_Matrix, "identity",
                              cr_matrix_init_identity, 0);
  rb_define_singleton_method (rb_cCairo_Matrix, "translate",
                              cr_matrix_init_translate, 2);
  rb_define_singleton_method (rb_cCairo_Matrix, "scale",
                              cr_matrix_init_scale, 2);
  rb_define_singleton_method (rb_cCairo_Matrix, "rotate",
                              cr_matrix_init_rotate, 1);
  
  rb_define_method (rb_cCairo_Matrix, "initialize", cr_matrix_initialize, 6);
  
  rb_define_method (rb_cCairo_Matrix, "identity!", cr_matrix_identity, 0);
  rb_define_method (rb_cCairo_Matrix, "translate!", cr_matrix_translate, 2);
  rb_define_method (rb_cCairo_Matrix, "scale!", cr_matrix_scale, 2);
  rb_define_method (rb_cCairo_Matrix, "rotate!", cr_matrix_rotate, 1);
  rb_define_method (rb_cCairo_Matrix, "invert!", cr_matrix_invert, 0);
  rb_define_method (rb_cCairo_Matrix, "multiply!", cr_matrix_multiply, 1);
  rb_define_method (rb_cCairo_Matrix, "matrix_distance",
                    cr_matrix_transform_distance, 2);
  rb_define_method (rb_cCairo_Matrix, "transform_point",
                    cr_matrix_transform_point, 2);

  /* Utilities */
  rb_define_method (rb_cCairo_Matrix, "set", cr_matrix_set, 6);
  rb_define_method (rb_cCairo_Matrix, "to_a", cr_matrix_to_a, 0);
  rb_define_method (rb_cCairo_Matrix, "to_s", cr_matrix_to_s, 0);


  RB_CAIRO_DEF_SETTERS (rb_cCairo_Matrix);
}

--- NEW FILE: rb_cairo_path.c ---
/* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
 * Ruby Cairo Binding
 *
 * $Author: kou $
 * $Date: 2007/03/06 12:17:34 $
 *
 * Copyright 2005 Kouhei Sutou <kou at cozmixng.org>
 *
 * This file is made available under the same terms as Ruby
 *
 */

#include "rb_cairo.h"

#define _SELF(self) (RVAL2CRPATH (self))

VALUE rb_cCairo_Path;

cairo_path_t *
rb_cairo_path_from_ruby_object (VALUE obj)
{
  cairo_path_t *path;
  if (!RTEST (rb_obj_is_kind_of (obj, rb_cCairo_Path)))
    {
      rb_raise (rb_eTypeError, "not a cairo path");
    }
  Data_Get_Struct (obj, cairo_path_t, path);
  return path;
}

static void
cr_path_free (void *ptr)
{
  if (ptr)
    {
      cairo_path_destroy ((cairo_path_t *)ptr);
    }
}

VALUE
rb_cairo_path_to_ruby_object (cairo_path_t *path)
{
  if (path)
    {
      return Data_Wrap_Struct (rb_cCairo_Path, NULL, cr_path_free, path);
    }
  else
    {
      return Qnil;
    }
}

static VALUE
cr_path_each (VALUE self)
{
  cairo_path_t *path = _SELF(self);
  int i, j;
  
  for (i = 0; i < path->num_data; i += path->data[i].header.length)
    {
      cairo_path_data_t *data = &(path->data[i]);
      VALUE points;

      points = rb_ary_new ();

      for (j = 1; j < data->header.length; j++)
        {
          rb_ary_push (points, rb_ary_new3 (2,
                                            rb_float_new (data[j].point.x),
                                            rb_float_new (data[j].point.y)));
        }
      rb_yield_values (2, INT2FIX (data->header.type), points);
    }

  return self;
}


void
Init_cairo_path (void)
{
  rb_cCairo_Path = rb_define_class_under (rb_mCairo, "Path", rb_cObject);

  rb_include_module (rb_cCairo_Path, rb_mEnumerable);

  rb_define_method (rb_cCairo_Path, "each", cr_path_each, 0);
}

--- NEW FILE: rb_cairo_pattern.c ---
/* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
 * Ruby Cairo Binding
 *
 * $Author: kou $
 * $Date: 2007/03/06 12:17:34 $
 *
 * Copyright 2005 Øyvind Kolås <pippin at freedesktop.org>
 * Copyright 2004-2005 MenTaLguY <mental at rydia.com>
 *
 * This file is made available under the same terms as Ruby
 *
 */

#include "rb_cairo.h"

VALUE rb_cCairo_Pattern;
VALUE rb_cCairo_SolidPattern;
VALUE rb_cCairo_SurfacePattern;
VALUE rb_cCairo_GradientPattern;
VALUE rb_cCairo_LinearPattern;
VALUE rb_cCairo_RadialPattern;

#define _SELF(self)  (RVAL2CRPATTERN(self))

static inline void
cr_pattern_check_status (cairo_pattern_t *pattern)
{
  rb_cairo_check_status (cairo_pattern_status (pattern));
}

cairo_pattern_t *
rb_cairo_pattern_from_ruby_object (VALUE obj)
{
  cairo_pattern_t *pattern;
  if (!RTEST (rb_obj_is_kind_of (obj, rb_cCairo_Pattern)))
    {
      rb_raise (rb_eTypeError, "not a cairo pattern");
    }
  Data_Get_Struct (obj, cairo_pattern_t, pattern);
  return pattern;
}

static void
cr_pattern_free (void *ptr)
{
  if (ptr)
    {
      cairo_pattern_destroy ((cairo_pattern_t *) ptr);
    }
}

VALUE
rb_cairo_pattern_to_ruby_object (cairo_pattern_t *pattern, VALUE klass)
{
  if (pattern)
    {
      cairo_pattern_reference (pattern);
      return Data_Wrap_Struct (klass, NULL, cr_pattern_free, pattern);
    }
  else
    {
      return Qnil;
    }
}

static VALUE
cr_pattern_allocate (VALUE klass)
{
  return Data_Wrap_Struct (klass, NULL, cr_pattern_free, NULL);
}

static VALUE
cr_pattern_initialize (VALUE self)
{
  rb_raise (rb_eTypeError, "abstract class");
  return Qnil;
}

static VALUE
cr_pattern_get_type (VALUE self)
{
  return INT2NUM (cairo_pattern_get_type (_SELF (self)));
}

static VALUE
cr_solid_pattern_initialize (int argc, VALUE *argv, VALUE self)
{
  VALUE red, green, blue, alpha;
  int n;
  cairo_pattern_t *pattern;

  n = rb_scan_args (argc, argv, "13", &red, &green, &blue, &alpha);
  
  if (n == 1 && rb_obj_is_kind_of (red, rb_cArray) &&
      (RARRAY (red)->len == 3 || RARRAY (red)->len == 4))
    {
      VALUE ary = red;
      n = RARRAY (ary)->len;
      
      red = rb_ary_entry (ary, 0);
      green = rb_ary_entry (ary, 1);
      blue = rb_ary_entry (ary, 2);
      alpha = rb_ary_entry (ary, 3);
    }

  if (n == 3)
    {
      pattern = cairo_pattern_create_rgb (NUM2DBL (red),
                                          NUM2DBL (green),
                                          NUM2DBL (blue));
    }
  else if (n == 4)
    {
      pattern = cairo_pattern_create_rgba (NUM2DBL (red),
                                           NUM2DBL (green),
                                           NUM2DBL (blue),
                                           NUM2DBL (alpha));
    }
  else
    {
      rb_raise (rb_eArgError,
                "invalid argument (expect "
                "(red, green, blue), "
                "([red, green, blue]), "
                "(red, green, blue, alpha) or "
                "([red, green, blue, alpha])"
                ")");
    }
  
  cr_pattern_check_status (pattern);
  DATA_PTR (self) = pattern;
  return Qnil;
}

static VALUE
cr_surface_pattern_initialize (VALUE self, VALUE surface)
{
  cairo_pattern_t *pattern;

  pattern = cairo_pattern_create_for_surface (RVAL2CRSURFACE (surface));
  cr_pattern_check_status (pattern);
  DATA_PTR (self) = pattern;
  return Qnil;
}

static VALUE
cr_linear_pattern_initialize (VALUE self, VALUE x0, VALUE y0,
                              VALUE x1, VALUE y1)
{
  cairo_pattern_t *pattern;

  pattern = cairo_pattern_create_linear (NUM2DBL (x0), NUM2DBL (y0),
                                         NUM2DBL (x1), NUM2DBL (y1));
  cr_pattern_check_status (pattern);
  DATA_PTR (self) = pattern;
  return Qnil;
}

static VALUE
cr_radial_pattern_initialize (VALUE self, VALUE cx0, VALUE cy0, VALUE radius0,
                              VALUE cx1, VALUE cy1, VALUE radius1)
{
  cairo_pattern_t *pattern;

  pattern = cairo_pattern_create_radial (NUM2DBL (cx0), NUM2DBL (cy0),
                                         NUM2DBL (radius0),
                                         NUM2DBL (cx1), NUM2DBL (cy1),
                                         NUM2DBL (radius1));
  cr_pattern_check_status (pattern);
  DATA_PTR (self) = pattern;
  return Qnil;
}

/* Cairo::GradientPattern */
static VALUE
cr_gradient_pattern_add_color_stop_rgb (int argc, VALUE *argv, VALUE self)
{
  VALUE offset, red, green, blue;
  int n;
  
  n = rb_scan_args (argc, argv, "22", &offset, &red, &green, &blue);

  if (n == 2 && rb_obj_is_kind_of (red, rb_cArray))
    {
      VALUE ary = red;
      n = RARRAY (ary)->len + 1;
      
      red = rb_ary_entry (ary, 0);
      green = rb_ary_entry (ary, 1);
      blue = rb_ary_entry (ary, 2);
    }

  if (n == 4)
    {
      cairo_pattern_add_color_stop_rgb (_SELF (self), NUM2DBL (offset),
                                        NUM2DBL (red), NUM2DBL (green),
                                        NUM2DBL (blue));
    }
  else
    {
      VALUE inspected_arg = rb_inspect (rb_ary_new4 (argc, argv));
      rb_raise (rb_eArgError,
                "invalid argument: %s (expect "
                "(offset, red, green, blue) or "
                "(offset, [red, green, blue])"
                ")",
                StringValuePtr (inspected_arg));
    }

  cr_pattern_check_status (_SELF (self));
  return self;
}

static VALUE
cr_gradient_pattern_add_color_stop_rgba (int argc, VALUE *argv, VALUE self)
{
  VALUE offset, red, green, blue, alpha;
  int n;
  
  n = rb_scan_args (argc, argv, "23", &offset, &red, &green, &blue, &alpha);

  if (n == 2 && rb_obj_is_kind_of (red, rb_cArray))
    {
      VALUE ary = red;
      n = RARRAY (ary)->len + 1;
      
      red = rb_ary_entry (ary, 0);
      green = rb_ary_entry (ary, 1);
      blue = rb_ary_entry (ary, 2);
      alpha = rb_ary_entry (ary, 3);
    }

  if (n == 4 || (n == 5 && NIL_P (alpha)))
    {
      cairo_pattern_add_color_stop_rgb (_SELF (self), NUM2DBL (offset),
                                        NUM2DBL (red), NUM2DBL (green),
                                        NUM2DBL (blue));
    }
  else if (n == 5)
    {
      cairo_pattern_add_color_stop_rgba (_SELF (self), NUM2DBL (offset),
                                         NUM2DBL (red), NUM2DBL (green),
                                         NUM2DBL (blue), NUM2DBL (alpha));
    }
  else
    {
      VALUE inspected_arg = rb_inspect (rb_ary_new4 (argc, argv));
      rb_raise (rb_eArgError,
                "invalid argument: %s (expect "
                "(offset, red, green, blue), "
                "(offset, [red, green, blue]), "
                "(offset, red, green, blue, alpha) or "
                "(offset, [red, green, blue, alpha])"
                ")",
                StringValuePtr (inspected_arg));
    }

  cr_pattern_check_status (_SELF (self));
  return self;
}


/* Cairo::Pattern */
static VALUE
cr_pattern_set_matrix (VALUE self, VALUE matrix)
{
  cairo_pattern_set_matrix (_SELF (self), RVAL2CRMATRIX (matrix));
  cr_pattern_check_status (_SELF (self));
  return self;
}

static VALUE
cr_pattern_get_matrix (VALUE self)
{
  cairo_matrix_t matrix;
  cairo_pattern_get_matrix (_SELF (self), &matrix);
  cr_pattern_check_status (_SELF (self));
  return CRMATRIX2RVAL (&matrix);
}

static VALUE
cr_pattern_set_extend (VALUE self, VALUE extend)
{
  cairo_pattern_set_extend (_SELF (self), RVAL2CREXTEND (extend));
  cr_pattern_check_status (_SELF (self));
  return self;
}

static VALUE
cr_pattern_get_extend (VALUE self)
{
  return INT2NUM (cairo_pattern_get_extend (_SELF (self)));
}

static VALUE
cr_pattern_set_filter (VALUE self, VALUE filter)
{
  cairo_pattern_set_filter (_SELF (self), RVAL2CRFILTER (filter));
  cr_pattern_check_status (_SELF (self));
  return self;
}

static VALUE
cr_pattern_get_filter (VALUE self)
{
  return INT2NUM (cairo_pattern_get_filter (_SELF (self)));
}

#if CAIRO_CHECK_VERSION(1, 3, 0)
static VALUE
cr_solid_pattern_get_rgba (VALUE self)
{
  double red, green, blue, alpha;

  rb_cairo_check_status (cairo_pattern_get_rgba (_SELF (self),
                                                 &red, &green, &blue, &alpha));
  return rb_ary_new3 (4,
                      rb_float_new (red), rb_float_new (green),
                      rb_float_new (blue), rb_float_new (alpha));
}

static VALUE
cr_surface_pattern_get_surface (VALUE self)
{
  cairo_surface_t *surface;

  rb_cairo_check_status (cairo_pattern_get_surface (_SELF (self), &surface));
  return CRSURFACE2RVAL (surface);
}

static VALUE
cr_gradient_pattern_get_color_stop_rgba (VALUE self, VALUE index)
{
  cairo_status_t status;
  double offset, red, green, blue, alpha;

  status = cairo_pattern_get_color_stop_rgba (_SELF (self), NUM2INT (index),
                                              &offset, &red, &green, &blue,
                                              &alpha);
  rb_cairo_check_status (status);
  return rb_ary_new3 (5, rb_float_new (offset),
                      rb_float_new (red), rb_float_new (green),
                      rb_float_new (blue), rb_float_new (alpha));
}

static VALUE
cr_gradient_pattern_get_color_stop_count (VALUE self)
{
  cairo_status_t status;
  int count;

  status = cairo_pattern_get_color_stop_count (_SELF (self), &count);
  rb_cairo_check_status (status);
  return INT2NUM (count);
}

static VALUE
cr_linear_pattern_get_linear_points (VALUE self)
{
  cairo_status_t status;
  double x0, y0, x1, y1;

  status = cairo_pattern_get_linear_points (_SELF (self), &x0, &y0, &x1, &y1);
  rb_cairo_check_status (status);
  return rb_ary_new3 (4,
                      rb_float_new (x0), rb_float_new (y0),
                      rb_float_new (x1), rb_float_new (y1));
}

static VALUE
cr_radial_pattern_get_radial_circles (VALUE self)
{
  cairo_status_t status;
  double x0, y0, r0, x1, y1, r1;

  status = cairo_pattern_get_radial_circles (_SELF (self),
                                             &x0, &y0, &r0,
                                             &x1, &y1, &r1);
  rb_cairo_check_status (status);
  return rb_ary_new3 (6,
                      rb_float_new (x0), rb_float_new (y0), rb_float_new (r0),
                      rb_float_new (x1), rb_float_new (y1), rb_float_new (r1));
}
#endif

/* Cairo::SurfacePattern */
/* none */

void
Init_cairo_pattern (void)
{
  rb_cCairo_Pattern =
    rb_define_class_under (rb_mCairo, "Pattern", rb_cObject);

  rb_define_alloc_func (rb_cCairo_Pattern, cr_pattern_allocate);

  rb_define_method (rb_cCairo_Pattern, "initialize", cr_pattern_initialize, 0);
  rb_define_method (rb_cCairo_Pattern, "type", cr_pattern_get_type, 0);

  rb_define_method (rb_cCairo_Pattern, "set_matrix", cr_pattern_set_matrix, 1);
  rb_define_method (rb_cCairo_Pattern, "matrix", cr_pattern_get_matrix, 0);
  rb_define_method (rb_cCairo_Pattern, "set_extend", cr_pattern_set_extend, 1);
  rb_define_alias (rb_cCairo_Pattern, "__extend__", "extend");
  rb_define_method (rb_cCairo_Pattern, "extend", cr_pattern_get_extend, 0);
  rb_define_method (rb_cCairo_Pattern, "set_filter", cr_pattern_set_filter, 1);
  rb_define_method (rb_cCairo_Pattern, "filter", cr_pattern_get_filter, 0);

  RB_CAIRO_DEF_SETTERS (rb_cCairo_Pattern);

  rb_cCairo_SolidPattern =
    rb_define_class_under (rb_mCairo, "SolidPattern", rb_cCairo_Pattern);

  rb_define_method (rb_cCairo_SolidPattern, "initialize",
                    cr_solid_pattern_initialize, -1);
#if CAIRO_CHECK_VERSION(1, 3, 0)
  rb_define_method (rb_cCairo_SolidPattern, "rgba",
                    cr_solid_pattern_get_rgba, 0);
#endif

  RB_CAIRO_DEF_SETTERS (rb_cCairo_SolidPattern);

  rb_cCairo_SurfacePattern =
    rb_define_class_under (rb_mCairo, "SurfacePattern", rb_cCairo_Pattern);

  rb_define_method (rb_cCairo_SurfacePattern, "initialize",
                    cr_surface_pattern_initialize, 1);
#if CAIRO_CHECK_VERSION(1, 3, 0)
  rb_define_method (rb_cCairo_SurfacePattern, "surface",
                    cr_surface_pattern_get_surface, 0);
#endif

  RB_CAIRO_DEF_SETTERS (rb_cCairo_SurfacePattern);

  rb_cCairo_GradientPattern =
    rb_define_class_under (rb_mCairo, "GradientPattern", rb_cCairo_Pattern);

  rb_define_method (rb_cCairo_GradientPattern, "add_color_stop_rgb",
                    cr_gradient_pattern_add_color_stop_rgb, -1);
  rb_define_method (rb_cCairo_GradientPattern, "add_color_stop_rgba",
                    cr_gradient_pattern_add_color_stop_rgba, -1);
  rb_define_alias (rb_cCairo_GradientPattern,
                   "add_color_stop", "add_color_stop_rgba");
#if CAIRO_CHECK_VERSION(1, 3, 0)
  rb_define_method (rb_cCairo_GradientPattern, "get_color_stop_rgba",
                    cr_gradient_pattern_get_color_stop_rgba, 1);
  rb_define_alias (rb_cCairo_GradientPattern,
                   "get_color_stop", "get_color_stop_rgba");
  rb_define_method (rb_cCairo_GradientPattern, "color_stop_count",
                    cr_gradient_pattern_get_color_stop_count, 0);
#endif

  RB_CAIRO_DEF_SETTERS (rb_cCairo_GradientPattern);

  rb_cCairo_LinearPattern =
    rb_define_class_under (rb_mCairo, "LinearPattern",
                           rb_cCairo_GradientPattern);

  rb_define_method (rb_cCairo_LinearPattern, "initialize",
                    cr_linear_pattern_initialize, 4);
#if CAIRO_CHECK_VERSION(1, 3, 0)
  rb_define_method (rb_cCairo_LinearPattern, "points",
                    cr_linear_pattern_get_linear_points, 0);
#endif

  RB_CAIRO_DEF_SETTERS (rb_cCairo_LinearPattern);

  rb_cCairo_RadialPattern =
    rb_define_class_under (rb_mCairo, "RadialPattern",
                           rb_cCairo_GradientPattern);

  rb_define_method (rb_cCairo_RadialPattern, "initialize",
                    cr_radial_pattern_initialize, 6);
#if CAIRO_CHECK_VERSION(1, 3, 0)
  rb_define_method (rb_cCairo_RadialPattern, "circles",
                    cr_radial_pattern_get_radial_circles, 0);
#endif

  RB_CAIRO_DEF_SETTERS (rb_cCairo_RadialPattern);
}

--- NEW FILE: rb_cairo_private.c ---
/* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
 * Ruby Cairo Binding
 *
 * $Author: kou $
 * $Date: 2007/03/06 12:17:34 $
 *
 * Copyright 2005 Kouhei Sutou <kou at cozmixng.org>
 *
 * This file is made available under the same terms as Ruby
 *
*/

#include "rb_cairo.h"

VALUE
rb_cairo__float_array (double *values, unsigned count)
{
  VALUE result;
  int i;

  result = rb_ary_new2 (count);
  for (i = 0; i < count; i++)
    {
      rb_ary_push (result, rb_float_new (values[i]));
    }
  return result;
}

void
rb_cairo__glyphs_to_array (VALUE rb_array, cairo_glyph_t **glyphs, int *length)
{
  int i;
  
  if (!rb_obj_is_kind_of (rb_array, rb_cArray))
     rb_raise (rb_eTypeError, "expected array");

  *length = RARRAY(rb_array)->len;
  *glyphs = ALLOCA_N (cairo_glyph_t, *length);

  if (!*glyphs)
    rb_cairo_check_status (CAIRO_STATUS_NO_MEMORY);

  for (i = 0; i < *length; i++)
    {
      memcpy ((char *) &(*glyphs)[i],
              (char *) RVAL2CRGLYPH (rb_ary_entry (rb_array, i)),
              sizeof (cairo_glyph_t));
    }
}


--- NEW FILE: rb_cairo_private.h ---
/* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
 * Ruby Cairo Binding
 *
 * $Author: kou $
 * $Date: 2007/03/06 12:17:34 $
 *
 * Copyright 2005 Kouhei Sutou <kou at cozmixng.org>
 *
 * This file is made available under the same terms as Ruby
 *
*/

#ifndef RB_CAIRO_PRIVATE_H
#define RB_CAIRO_PRIVATE_H

#define CR_TRUE 1
#define CR_FALSE 0

VALUE rb_cairo__float_array (double *values, unsigned count);
void rb_cairo__glyphs_to_array (VALUE rb_array, cairo_glyph_t **glyphs, int *length);

#endif

--- NEW FILE: rb_cairo_scaled_font.c ---
/* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
 * Ruby Cairo Binding
 *
 * $Author: kou $
 * $Date: 2007/03/06 12:17:34 $
 *
 * Copyright 2005 Kouhei Sutou <kou at cozmixng.org>
 *
 * This file is made available under the same terms as Ruby
 *
*/


#include "rb_cairo.h"
#include "rb_cairo_private.h"

VALUE rb_cCairo_ScaledFont;

#define _SELF(self)  (RVAL2CRSCALEDFONT(self))

static inline void
cr_scaled_font_check_status (cairo_scaled_font_t *font)
{
  rb_cairo_check_status (cairo_scaled_font_status (font));
}

cairo_scaled_font_t *
rb_cairo_scaled_font_from_ruby_object (VALUE obj)
{
  cairo_scaled_font_t *font;
  if (!RTEST (rb_obj_is_kind_of (obj, rb_cCairo_ScaledFont)))
    {
      rb_raise (rb_eTypeError, "not a cairo scaled font");
    }
  Data_Get_Struct (obj, cairo_scaled_font_t, font);
  return font;
}

static void
cr_scaled_font_free (void *ptr)
{
  if (ptr)
    {
      cairo_scaled_font_destroy ((cairo_scaled_font_t *) ptr);
    }
}

VALUE
rb_cairo_scaled_font_to_ruby_object (cairo_scaled_font_t *font)
{
  if (font)
    {
      cairo_scaled_font_reference (font);
      return Data_Wrap_Struct (rb_cCairo_ScaledFont, NULL,
                               cr_scaled_font_free, font);
    }
  else
    {
      return Qnil;
    }
}

static VALUE
cr_scaled_font_allocate (VALUE klass)
{
  return Data_Wrap_Struct (klass, NULL, cr_scaled_font_free, NULL);
}

static VALUE
cr_scaled_font_initialize (VALUE self, VALUE face, VALUE matrix,
                           VALUE ctm, VALUE options)
{
  cairo_scaled_font_t *font;

  font = cairo_scaled_font_create (RVAL2CRFONTFACE (face),
                                   RVAL2CRMATRIX (matrix),
                                   RVAL2CRMATRIX (ctm),
                                   RVAL2CRFONTOPTIONS (options));
  cr_scaled_font_check_status (font);
  DATA_PTR (self) = font;
  return Qnil;
}

static VALUE
cr_scaled_font_get_type (VALUE self)
{
  return INT2NUM (cairo_scaled_font_get_type ( _SELF (self)));
}

static VALUE
cr_scaled_font_extents (VALUE self)
{
  cairo_font_extents_t extents;
  cairo_scaled_font_extents (_SELF (self), &extents);
  cr_scaled_font_check_status (_SELF (self));
  return CRFONTEXTENTS2RVAL (&extents);
}

static VALUE
cr_scaled_font_text_extents (VALUE self, VALUE utf8)
{
  cairo_text_extents_t extents;
  cairo_scaled_font_text_extents (_SELF (self), StringValueCStr (utf8),
                                  &extents);
  cr_scaled_font_check_status (_SELF (self));
  return CRTEXTEXTENTS2RVAL (&extents);
}

static VALUE
cr_scaled_font_glyph_extents (VALUE self, VALUE rb_glyphs)
{
  cairo_text_extents_t extents;
  cairo_glyph_t *glyphs;
  int count;

  rb_cairo__glyphs_to_array (rb_glyphs, &glyphs, &count);
  cairo_scaled_font_glyph_extents (_SELF (self), glyphs, count, &extents);
  cr_scaled_font_check_status (_SELF (self));
  return CRTEXTEXTENTS2RVAL (&extents);
}

static VALUE
cr_scaled_font_get_font_face (VALUE self)
{
  cairo_font_face_t *face;
  face = cairo_scaled_font_get_font_face (_SELF (self));
  cr_scaled_font_check_status (_SELF (self));
  return CRFONTFACE2RVAL (face);
}

static VALUE
cr_scaled_font_get_font_matrix (VALUE self)
{
  cairo_matrix_t font_matrix;
  cairo_scaled_font_get_font_matrix (_SELF (self), &font_matrix);
  cr_scaled_font_check_status (_SELF (self));
  return CRMATRIX2RVAL (&font_matrix);
}

static VALUE
cr_scaled_font_get_ctm (VALUE self)
{
  cairo_matrix_t ctm;
  cairo_scaled_font_get_font_matrix (_SELF (self), &ctm);
  cr_scaled_font_check_status (_SELF (self));
  return CRMATRIX2RVAL (&ctm);
}

static VALUE
cr_scaled_font_get_font_options (VALUE self)
{
  cairo_font_options_t *options = cairo_font_options_create();
  cairo_scaled_font_get_font_options (_SELF (self), options);
  cr_scaled_font_check_status (_SELF (self));
  rb_cairo_check_status (cairo_font_options_status (options));
  return CRFONTOPTIONS2RVAL (options);
}

void
Init_cairo_scaled_font (void)
{
  rb_cCairo_ScaledFont =
    rb_define_class_under (rb_mCairo, "ScaledFont", rb_cObject);

  rb_define_alloc_func (rb_cCairo_ScaledFont, cr_scaled_font_allocate);

  rb_define_method (rb_cCairo_ScaledFont, "initialize",
                    cr_scaled_font_initialize, 4);

  rb_define_method (rb_cCairo_ScaledFont, "type", cr_scaled_font_get_type, 0);
  rb_define_method (rb_cCairo_ScaledFont, "extents", cr_scaled_font_extents, 0);
  rb_define_method (rb_cCairo_ScaledFont, "text_extents",
                    cr_scaled_font_text_extents, 1);
  rb_define_method (rb_cCairo_ScaledFont, "glyph_extents",
                    cr_scaled_font_glyph_extents, 1);
  rb_define_method (rb_cCairo_ScaledFont, "font_face",
                    cr_scaled_font_get_font_face, 0);
  rb_define_method (rb_cCairo_ScaledFont, "font_matrix",
                    cr_scaled_font_get_font_matrix, 0);
  rb_define_method (rb_cCairo_ScaledFont, "ctm", cr_scaled_font_get_ctm, 0);
  rb_define_method (rb_cCairo_ScaledFont, "font_options",
                    cr_scaled_font_get_font_options, 0);
}

--- NEW FILE: rb_cairo_surface.c ---
/* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
 * Ruby Cairo Binding
 *
 * $Author: kou $
 * $Date: 2007/03/06 12:17:34 $
 *
 * Copyright 2005 Øyvind Kolås <pippin at freedesktop.org>
 * Copyright 2004-2005 MenTaLguY <mental at rydia.com>
 *
 * This file is made available under the same terms as Ruby
 *
 */

#include "rb_cairo.h"
#include "rb_cairo_private.h"

#include "rubyio.h"

#if CAIRO_HAS_PS_SURFACE || CAIRO_HAS_PDF_SURFACE || CAIRO_HAS_SVG_SURFACE
#  define HAS_CREATE_CR_CLOSURE_SURFACE 1
#else
#  define HAS_CREATE_CR_CLOSURE_SURFACE 0
#endif


VALUE rb_cCairo_Surface;
VALUE rb_cCairo_ImageSurface;
VALUE rb_cCairo_PDFSurface;
VALUE rb_cCairo_PSSurface;
VALUE rb_cCairo_SVGSurface;

static ID cr_id_target;
static ID cr_id_read;
static ID cr_id_write;
static cairo_user_data_key_t cr_klass_key;
static cairo_user_data_key_t cr_closure_key;

#define _SELF  (RVAL2CRSURFACE(self))

static inline void
cr_surface_check_status (cairo_surface_t *surface)
{
  rb_cairo_check_status (cairo_surface_status (surface));
}

static void
cr_surface_set_klass (cairo_surface_t *surface, VALUE klass)
{
  cairo_status_t status;
  status = cairo_surface_set_user_data (surface, &cr_klass_key,
                                        (void *)klass, NULL);
  rb_cairo_check_status (status);
}

static VALUE
cr_surface_get_klass (cairo_surface_t *surface)
{
  VALUE klass;
  void *data = cairo_surface_get_user_data (surface, &cr_klass_key);

  if (data)
    klass = (VALUE) data;
  else
    {
      switch (cairo_surface_get_type (surface))
        {
        case CAIRO_SURFACE_TYPE_IMAGE:
          klass = rb_cCairo_ImageSurface;
          break;
        case CAIRO_SURFACE_TYPE_PDF:
          klass = rb_cCairo_PDFSurface;
          break;
        case CAIRO_SURFACE_TYPE_PS:
          klass = rb_cCairo_PSSurface;
          break;
        case CAIRO_SURFACE_TYPE_SVG:
          klass = rb_cCairo_SVGSurface;
          break;
        default:
          klass = rb_cCairo_Surface;
          break;
        }
    }

  return klass;
}

/* read/write callback */
typedef struct cr_io_callback_closure {
  VALUE target;
  VALUE error;
  unsigned char *data;
  unsigned int length;
} cr_io_callback_closure_t;

#if HAS_CREATE_CR_CLOSURE_SURFACE
static cr_io_callback_closure_t *
cr_closure_new (VALUE target)
{
  cr_io_callback_closure_t *closure;
  closure = ALLOC (cr_io_callback_closure_t);

  closure->target = target;
  closure->error = Qnil;

  return closure;
}

static void
cr_closure_destroy (cr_io_callback_closure_t *closure)
{
  free (closure);
}

static void
cr_closure_free (void *closure)
{
  cr_closure_destroy ((cr_io_callback_closure_t *) closure);
}
#endif

static VALUE
cr_surface_io_func_rescue (VALUE io_closure)
{
  cr_io_callback_closure_t *closure;
  closure = (cr_io_callback_closure_t *)io_closure;
  closure->error = ruby_errinfo;
  return Qnil;
}

/* write callback */
static VALUE
cr_surface_write_func_invoke (VALUE write_closure)
{
  VALUE output, data;
  long written_bytes;
  cr_io_callback_closure_t *closure;
  unsigned int length;

  closure = (cr_io_callback_closure_t *)write_closure;
  
  output = closure->target;
  data = rb_str_new ((const char *)closure->data, closure->length);

  length = RSTRING (data)->len;
  while (length != 0)
    {
      VALUE rb_written_bytes = rb_funcall (output, cr_id_write, 1, data);
      written_bytes = NUM2LONG (rb_written_bytes);
      data = rb_str_substr (data, written_bytes,
                            RSTRING (data)->len - written_bytes);
      length -= written_bytes;
    }
  
  return Qnil;
}

static cairo_status_t
cr_surface_write_func (void *write_closure,
                       const unsigned char *data, unsigned int length)
{
  cr_io_callback_closure_t *closure;

  closure = (cr_io_callback_closure_t *)write_closure;
  closure->data = (unsigned char *)data;
  closure->length = length;
  
  rb_rescue2 (cr_surface_write_func_invoke, (VALUE) closure,
              cr_surface_io_func_rescue, (VALUE) closure, rb_eException,
              (VALUE)0);
  
  if (NIL_P (closure->error))
    return CAIRO_STATUS_SUCCESS;
  else
    return CAIRO_STATUS_WRITE_ERROR;
}

/* read callback */
static VALUE
cr_surface_read_func_invoke (VALUE read_closure)
{
  VALUE input, result;
  cr_io_callback_closure_t *closure;
  unsigned int length, rest;

  closure = (cr_io_callback_closure_t *)read_closure;
  input = closure->target;
  length = closure->length;
  
  result = rb_str_new2 ("");

  for (rest = length; rest != 0; rest = length - RSTRING (result)->len)
    {
      rb_str_concat (result, rb_funcall (input, cr_id_read, 1, INT2NUM (rest)));
    }

  memcpy ((void *)closure->data, (const void *)StringValuePtr (result), length);

  return Qnil;
}

static cairo_status_t
cr_surface_read_func (void *read_closure,
                      unsigned char *data, unsigned int length)
{
  cr_io_callback_closure_t *closure;

  closure = (cr_io_callback_closure_t *)read_closure;
  closure->data = data;
  closure->length = length;
  rb_rescue2 (cr_surface_read_func_invoke, (VALUE) closure,
              cr_surface_io_func_rescue, (VALUE) closure, rb_eException,
              (VALUE)0);
  
  if (NIL_P (closure->error))
    return CAIRO_STATUS_SUCCESS;
  else
    return CAIRO_STATUS_READ_ERROR;
}

/* constructor/de-constructor */
cairo_surface_t *
rb_cairo_surface_from_ruby_object (VALUE obj)
{
  cairo_surface_t *surface;
  if (!RTEST (rb_obj_is_kind_of (obj, rb_cCairo_Surface)))
    {
      rb_raise (rb_eTypeError, "not a cairo surface");
    }
  Data_Get_Struct (obj, cairo_surface_t, surface);
  cr_surface_set_klass (surface, rb_obj_class (obj));
  return surface;
}

static void
cr_surface_free (void *ptr)
{
  if (ptr)
    {
      cairo_surface_destroy ((cairo_surface_t *) ptr);
    }
}

VALUE
rb_cairo_surface_to_ruby_object (cairo_surface_t *surface)
{
  if (surface)
    {
      VALUE klass = cr_surface_get_klass (surface);
      cairo_surface_reference (surface);
      return Data_Wrap_Struct (klass, NULL, cr_surface_free, surface);
    }
  else
    {
      return Qnil;
    }
}

static VALUE
cr_surface_allocate (VALUE klass)
{
  return Data_Wrap_Struct (klass, NULL, cr_surface_free, NULL);
}

/* Surface manipulation */
static VALUE
cr_surface_create_similar (VALUE self, VALUE content,
                           VALUE width, VALUE height)
{
  cairo_surface_t *surface;

  surface = cairo_surface_create_similar (RVAL2CRSURFACE (self),
                                          RVAL2CRCONTENT (content),
                                          NUM2INT (width), NUM2INT (height));
  cr_surface_check_status (surface);
  cr_surface_set_klass (surface, rb_obj_class (self));
  return CRSURFACE2RVAL (surface);
}

static VALUE
cr_surface_finish (VALUE self)
{
  cr_io_callback_closure_t *closure;
  closure = cairo_surface_get_user_data (_SELF, &cr_closure_key);
  
  cairo_surface_finish (_SELF);

  if (closure && !NIL_P (closure->error))
    rb_exc_raise (closure->error);
  
  cr_surface_check_status (_SELF);
  return self;
}

static VALUE
cr_surface_get_type (VALUE self)
{
  return INT2NUM (cairo_surface_get_type (_SELF));
}

static VALUE
cr_surface_get_content (VALUE self)
{
  return INT2NUM (cairo_surface_get_content (_SELF));
}


#if CAIRO_HAS_PNG_FUNCTIONS
static VALUE
cr_surface_write_to_png_stream (VALUE self, VALUE target)
{
  cairo_status_t status;
  cr_io_callback_closure_t closure;

  closure.target = target;
  closure.error = Qnil;

  status = cairo_surface_write_to_png_stream (_SELF, cr_surface_write_func,
                                              (void *)&closure);
  if (!NIL_P (closure.error))
    rb_exc_raise (closure.error);

  rb_cairo_check_status (status);
  return self;
}

static VALUE
cr_surface_write_to_png (VALUE self, VALUE filename)
{
  cairo_status_t status;
  status = cairo_surface_write_to_png (_SELF, StringValueCStr (filename));
  rb_cairo_check_status (status);
  return self;
}

static VALUE
cr_surface_write_to_png_generic (VALUE self, VALUE target)
{
  if (rb_respond_to (target, cr_id_write))
    return cr_surface_write_to_png_stream (self, target);
  else
    return cr_surface_write_to_png (self, target);
}
#endif

static VALUE
cr_surface_get_font_options (VALUE self)
{
  cairo_font_options_t *options = cairo_font_options_create();
  cairo_surface_get_font_options (_SELF, options);
  cr_surface_check_status (_SELF);
  rb_cairo_check_status (cairo_font_options_status (options));
  return CRFONTOPTIONS2RVAL (options);
}

static VALUE
cr_surface_flush (VALUE self)
{
  cairo_surface_flush (_SELF);
  cr_surface_check_status (_SELF);
  return self;
}

static VALUE
cr_surface_mark_dirty (int argc, VALUE *argv, VALUE self)
{
  VALUE x, y, width, height;
  int n;
  
  n = rb_scan_args (argc, argv, "04", &x, &y, &width, &height);

  if (n == 0)
    {
      cairo_surface_mark_dirty (_SELF);
    }
  else if (n == 4)
    {
      cairo_surface_mark_dirty_rectangle (_SELF,
                                          NUM2INT (x), NUM2INT (y),
                                          NUM2INT (width), NUM2INT (height));
    }
  else
    {
      rb_raise (rb_eArgError,
                "invalid argument (expect () or (x, y, width, height))");
    }

  cr_surface_check_status (_SELF);
  return self;
}

static VALUE
cr_surface_set_device_offset (VALUE self, VALUE x_offset, VALUE y_offset)
{
  cairo_surface_set_device_offset (_SELF,
                                   NUM2DBL (x_offset),
                                   NUM2DBL (y_offset));
  cr_surface_check_status (_SELF);
  return self;
}

static VALUE
cr_surface_get_device_offset (VALUE self)
{
  double x_offset, y_offset;

  cairo_surface_get_device_offset (_SELF, &x_offset, &y_offset);
  cr_surface_check_status (_SELF);
  return rb_ary_new3 (2, rb_float_new (x_offset), rb_float_new (y_offset));
}

static VALUE
cr_surface_set_fallback_resolution (VALUE self,
                                    VALUE x_pixels_per_inch,
                                    VALUE y_pixels_per_inch)
{
  cairo_surface_set_fallback_resolution (_SELF,
                                         NUM2DBL (x_pixels_per_inch),
                                         NUM2DBL (y_pixels_per_inch));
  cr_surface_check_status (_SELF);
  return self;
}


/* Image-surface functions */
#if CAIRO_HAS_PNG_FUNCTIONS
static cairo_surface_t *
cr_image_surface_create_from_png_stream (VALUE target)
{
  cr_io_callback_closure_t closure;
  cairo_surface_t *surface;

  closure.target = target;
  closure.error = Qnil;

  surface = cairo_image_surface_create_from_png_stream (cr_surface_read_func,
                                                        (void *)&closure);
  if (!NIL_P (closure.error))
    rb_exc_raise (closure.error);
  
  return surface;
}

static cairo_surface_t *
cr_image_surface_create_from_png (VALUE filename)
{
  return cairo_image_surface_create_from_png (StringValueCStr (filename));
}

static VALUE
cr_image_surface_create_from_png_generic (VALUE klass, VALUE target)
{
  VALUE rb_surface;
  cairo_surface_t *surface;

  if (rb_respond_to (target, cr_id_read))
    surface = cr_image_surface_create_from_png_stream (target);
  else
    surface = cr_image_surface_create_from_png (target);

  cr_surface_check_status (surface);
  cr_surface_set_klass (surface, klass);
  rb_surface = cr_surface_allocate (klass);
  DATA_PTR (rb_surface) = surface;
  return rb_surface;
}
#endif


static cairo_surface_t *
cr_image_surface_create (VALUE self, VALUE format, VALUE width, VALUE height)
{
  cairo_format_t cr_format;
  cr_format = NIL_P (format) ? CAIRO_FORMAT_ARGB32 : RVAL2CRFORMAT (format);
  return cairo_image_surface_create (cr_format,
                                     NUM2INT (width),
                                     NUM2INT (height));
}

static cairo_surface_t *
cr_image_surface_create_for_data (VALUE self, VALUE rb_data, VALUE format,
                                  VALUE width, VALUE height, VALUE stride)
{
  unsigned char *data;

  data = (unsigned char *)StringValuePtr (rb_data);
  
  return cairo_image_surface_create_for_data (data,
                                              RVAL2CRFORMAT (format),
                                              NUM2INT (width),
                                              NUM2INT (height),
                                              NUM2INT (stride));
}

static VALUE
cr_image_surface_initialize (int argc, VALUE *argv, VALUE self)
{
  cairo_surface_t *surface;
  VALUE arg1, arg2, arg3, arg4, arg5;
  int n;
  
  n = rb_scan_args (argc, argv, "23", &arg1, &arg2, &arg3, &arg4, &arg5);

  if (n == 2)
    surface = cr_image_surface_create (self, Qnil, arg1, arg2);
  else if (n == 3)
    surface = cr_image_surface_create (self, arg1, arg2, arg3);
  else if (n == 5)
    surface =
      cr_image_surface_create_for_data (self, arg1, arg2, arg3, arg4, arg5);
  else
    rb_raise (rb_eArgError,
              "invalid argument (expect "
              "(width, height) or "
              "(format, width, height) or "
              "(data, format, width, height, stride))");

  cr_surface_check_status (surface);
  DATA_PTR (self) = surface;
  return Qnil;
}

static VALUE
cr_image_surface_get_data (VALUE self)
{
  unsigned char *data;
  cairo_surface_t *surface;

  surface = _SELF;
  data = cairo_image_surface_get_data (surface);

  if (data)
    return rb_str_new ((const char *)data,
                       cairo_image_surface_get_stride (surface) *
                       cairo_image_surface_get_height (surface));
  else
    return Qnil;
}

static VALUE
cr_image_surface_get_format (VALUE self)
{
  return INT2NUM (cairo_image_surface_get_format (_SELF));
}

static VALUE
cr_image_surface_get_width (VALUE self)
{
  return INT2NUM (cairo_image_surface_get_width (_SELF));
}

static VALUE
cr_image_surface_get_height (VALUE self)
{
  return INT2NUM (cairo_image_surface_get_height (_SELF));
}

static VALUE
cr_image_surface_get_stride (VALUE self)
{
  return INT2NUM (cairo_image_surface_get_stride (_SELF));
}


/* Printing surfaces */
#define DEFINE_SURFACE(type)                                            \
static VALUE                                                            \
cr_ ## type ## _surface_initialize (VALUE self, VALUE target,           \
                                    VALUE rb_width_in_points,           \
                                    VALUE rb_height_in_points)          \
{                                                                       \
  cairo_surface_t *surface;                                             \
  double width_in_points, height_in_points;                             \
                                                                        \
  width_in_points = NUM2DBL (rb_width_in_points);                       \
  height_in_points = NUM2DBL (rb_height_in_points);                     \
                                                                        \
  if (rb_respond_to (target, cr_id_write))                              \
    {                                                                   \
      cr_io_callback_closure_t *closure;                                \
                                                                        \
      closure = cr_closure_new (target);                                \
      surface =                                                         \
        cairo_ ## type ## _surface_create_for_stream (                  \
          cr_surface_write_func,                                        \
          (void *) closure,                                             \
          width_in_points,                                              \
          height_in_points);                                            \
                                                                        \
      if (cairo_surface_status (surface))                               \
        {                                                               \
          cr_closure_destroy (closure);                                 \
        }                                                               \
      else                                                              \
        {                                                               \
          rb_ivar_set (self, cr_id_target, target);                     \
          cairo_surface_set_user_data (surface, &cr_closure_key,        \
                                       closure, cr_closure_free);       \
        }                                                               \
    }                                                                   \
  else                                                                  \
    {                                                                   \
      surface =                                                         \
        cairo_ ## type ## _surface_create (StringValueCStr (target),    \
                                           width_in_points,             \
                                           height_in_points);           \
    }                                                                   \
                                                                        \
  cr_surface_check_status (surface);                                    \
  DATA_PTR (self) = surface;                                            \
  return Qnil;                                                          \
}


#if CAIRO_HAS_PS_SURFACE
/* PS-surface functions */
DEFINE_SURFACE(ps)

static VALUE
cr_ps_surface_set_size (VALUE self,
                        VALUE width_in_points,
                        VALUE height_in_points)
{
  cairo_ps_surface_set_size (_SELF,
                             NUM2DBL (width_in_points),
                             NUM2DBL (height_in_points));
  cr_surface_check_status (_SELF);
  return Qnil;
}

static VALUE
cr_ps_surface_dsc_comment (VALUE self, VALUE comment)
{
  cairo_ps_surface_dsc_comment (_SELF, StringValueCStr (comment));
  cr_surface_check_status (_SELF);
  return Qnil;
}

static VALUE
cr_ps_surface_dsc_begin_setup (VALUE self)
{
  cairo_ps_surface_dsc_begin_setup (_SELF);
  cr_surface_check_status (_SELF);
  if (rb_block_given_p ())
    return rb_yield (self);
  else
    return Qnil;
}

static VALUE
cr_ps_surface_dsc_begin_page_setup (VALUE self)
{
  cairo_ps_surface_dsc_begin_page_setup (_SELF);
  cr_surface_check_status (_SELF);
  if (rb_block_given_p ())
    return rb_yield (self);
  else
    return Qnil;
}
#endif

#if CAIRO_HAS_PDF_SURFACE
/* PDF-surface functions */
DEFINE_SURFACE(pdf)

static VALUE
cr_pdf_surface_set_size (VALUE self,
                         VALUE width_in_points,
                         VALUE height_in_points)
{
  cairo_pdf_surface_set_size (_SELF,
                              NUM2DBL (width_in_points),
                              NUM2DBL (height_in_points));
  cr_surface_check_status (_SELF);
  return Qnil;
}
#endif

#if CAIRO_HAS_SVG_SURFACE
/* SVG-surface functions */
DEFINE_SURFACE(svg)

static VALUE
cr_svg_surface_restrict_to_version (VALUE self, VALUE version)
{
  cairo_svg_surface_restrict_to_version (_SELF, RVAL2CRSVGVERSION (version));
  cr_surface_check_status (_SELF);
  return Qnil;
}

static VALUE
cr_svg_get_versions (VALUE self)
{
  VALUE rb_versions;
  int i, num_versions;
  cairo_svg_version_t const *versions;

  cairo_svg_get_versions (&versions, &num_versions);

  rb_versions = rb_ary_new2 (num_versions);

  for (i = 0; i < num_versions; i++)
    {
      rb_ary_push (rb_versions, INT2NUM (versions[i]));
    }

  return rb_versions;
}

static VALUE
cr_svg_version_to_string (VALUE self, VALUE version)
{
  const char *ver_str;
  ver_str = cairo_svg_version_to_string (RVAL2CRSVGVERSION(version));
  return rb_str_new2 (ver_str);
}
#endif


void
Init_cairo_surface (void)
{
  cr_id_target = rb_intern ("target");
  cr_id_read = rb_intern ("read");
  cr_id_write = rb_intern ("write");
  
  rb_cCairo_Surface =
    rb_define_class_under (rb_mCairo, "Surface", rb_cObject);
  rb_define_alloc_func (rb_cCairo_Surface, cr_surface_allocate);
  
  rb_define_method (rb_cCairo_Surface, "create_similar",
                    cr_surface_create_similar, 3);
  rb_define_method (rb_cCairo_Surface, "finish", cr_surface_finish, 0);
  rb_define_method (rb_cCairo_Surface, "type", cr_surface_get_type, 0);
  rb_define_method (rb_cCairo_Surface, "content", cr_surface_get_content, 0);

  rb_define_method (rb_cCairo_Surface, "font_options",
                    cr_surface_get_font_options, 0);
  rb_define_method (rb_cCairo_Surface, "flush", cr_surface_flush, 0);
  rb_define_method (rb_cCairo_Surface, "mark_dirty", cr_surface_mark_dirty, 0);
  rb_define_method (rb_cCairo_Surface, "set_device_offset",
                    cr_surface_set_device_offset, 2);
  rb_define_method (rb_cCairo_Surface, "device_offset",
                    cr_surface_get_device_offset, 0);
  rb_define_method (rb_cCairo_Surface, "set_fallback_resolution",
                    cr_surface_set_fallback_resolution, 2);

#if CAIRO_HAS_PNG_FUNCTIONS
  rb_define_method (rb_cCairo_Surface, "write_to_png",
                    cr_surface_write_to_png_generic, 1);
#endif

  RB_CAIRO_DEF_SETTERS (rb_cCairo_Surface);

  /* Image-surface */
  rb_cCairo_ImageSurface =
    rb_define_class_under (rb_mCairo, "ImageSurface", rb_cCairo_Surface);
  
#if CAIRO_HAS_PNG_FUNCTIONS
  rb_define_singleton_method (rb_cCairo_ImageSurface, "from_png",
                              cr_image_surface_create_from_png_generic, 1);
#endif
  
  rb_define_method (rb_cCairo_ImageSurface, "initialize",
                    cr_image_surface_initialize, -1);

  rb_define_method (rb_cCairo_ImageSurface, "data",
                    cr_image_surface_get_data, 0);
  rb_define_method (rb_cCairo_ImageSurface, "format",
                    cr_image_surface_get_format, 0);
  rb_define_method (rb_cCairo_ImageSurface, "width",
                    cr_image_surface_get_width, 0);
  rb_define_method (rb_cCairo_ImageSurface, "height",
                    cr_image_surface_get_height, 0);
  rb_define_method (rb_cCairo_ImageSurface, "stride",
                    cr_image_surface_get_stride, 0);

#define INIT_SURFACE(type, name)                                        \
  rb_cCairo_ ## name ## Surface =                                       \
    rb_define_class_under (rb_mCairo, # name "Surface",                 \
                           rb_cCairo_Surface);                          \
                                                                        \
  rb_define_method (rb_cCairo_ ## name ## Surface, "initialize",        \
                    cr_ ## type ## _surface_initialize, 3);

#if CAIRO_HAS_PS_SURFACE
  /* PS-surface */
  INIT_SURFACE(ps, PS)

  rb_define_method (rb_cCairo_PSSurface, "set_size", cr_ps_surface_set_size, 2);
  rb_define_method (rb_cCairo_PSSurface, "dsc_comment",
                    cr_ps_surface_dsc_comment, 1);
  rb_define_method (rb_cCairo_PSSurface, "dsc_begin_setup",
                    cr_ps_surface_dsc_begin_setup, 0);
  rb_define_method (rb_cCairo_PSSurface, "dsc_begin_page_setup",
                    cr_ps_surface_dsc_begin_page_setup, 0);

  RB_CAIRO_DEF_SETTERS (rb_cCairo_PSSurface);
#else
  rb_cCairo_PSSurface = Qnil;
#endif

#if CAIRO_HAS_PDF_SURFACE
  /* PDF-surface */
  INIT_SURFACE(pdf, PDF)

  rb_define_method (rb_cCairo_PDFSurface, "set_size",
                    cr_pdf_surface_set_size, 2);

  RB_CAIRO_DEF_SETTERS (rb_cCairo_PDFSurface);
#else
  rb_cCairo_PDFSurface = Qnil;
#endif

#if CAIRO_HAS_SVG_SURFACE
  /* SVG-surface */
  INIT_SURFACE(svg, SVG)

  rb_define_const (rb_cCairo_SVGSurface, "VERSION_1_1",
                   rb_const_get (rb_mCairo, rb_intern ("SVG_VERSION_1_1")));
  rb_define_const (rb_cCairo_SVGSurface, "VERSION_1_2",
                   rb_const_get (rb_mCairo, rb_intern ("SVG_VERSION_1_2")));

  rb_define_singleton_method (rb_cCairo_SVGSurface, "versions",
                              cr_svg_get_versions, 0);
  rb_define_singleton_method (rb_cCairo_SVGSurface, "version_to_string",
                              cr_svg_version_to_string, 1);

  rb_define_method (rb_cCairo_SVGSurface, "restrict_to_version",
                    cr_svg_surface_restrict_to_version, 1);

  RB_CAIRO_DEF_SETTERS (rb_cCairo_SVGSurface);
#else
  rb_cCairo_SVGSurface = Qnil;
#endif
}

--- NEW FILE: rb_cairo_text_extents.c ---
/* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
 * Ruby Cairo Binding
 *
 * $Author: kou $
 * $Date: 2007/03/06 12:17:34 $
 *
 * Copyright 2005 Øyvind Kolås <pippin at freedesktop.org>
 * Copyright 2004-2005 MenTaLguY <mental at rydia.com>
 *
 * This file is made available under the same terms as Ruby
 *
 */

#include "rb_cairo.h"

VALUE rb_cCairo_TextExtents;

#define _SELF(self)  (RVAL2CRTEXTEXTENTS(self))

cairo_text_extents_t *
rb_cairo_text_extents_from_ruby_object (VALUE obj)
{
  cairo_text_extents_t *extents;
  if (!RTEST (rb_obj_is_kind_of (obj, rb_cCairo_TextExtents)))
    {
      rb_raise (rb_eTypeError, "not a cairo text_extents");
    }
  Data_Get_Struct (obj, cairo_text_extents_t, extents);
  return extents;
}

VALUE
rb_cairo_text_extents_to_ruby_object (cairo_text_extents_t *extents)
{
  if (extents)
    {
      cairo_text_extents_t *new_extents = ALLOC (cairo_text_extents_t);
      *new_extents = *extents;
      return Data_Wrap_Struct (rb_cCairo_TextExtents, NULL, -1, new_extents);
    }
  else
    {
      return Qnil;
    }
}


static VALUE
cr_text_extents_x_bearing (VALUE self)
{
  return rb_float_new (_SELF(self)->x_bearing);
}

static VALUE
cr_text_extents_y_bearing (VALUE self)
{
  return rb_float_new (_SELF(self)->y_bearing);
}

static VALUE
cr_text_extents_width (VALUE self)
{
  return rb_float_new (_SELF(self)->width);
}

static VALUE
cr_text_extents_height (VALUE self)
{
  return rb_float_new (_SELF(self)->height);
}

static VALUE
cr_text_extents_x_advance (VALUE self)
{
  return rb_float_new (_SELF(self)->x_advance);
}

static VALUE
cr_text_extents_y_advance (VALUE self)
{
  return rb_float_new (_SELF(self)->y_advance);
}

static VALUE
cr_text_extents_to_s (VALUE self)
{
  VALUE ret;

  ret = rb_str_new2 ("#<");
  rb_str_cat2 (ret, rb_class2name (CLASS_OF (self)));
  rb_str_cat2 (ret, ": ");
  rb_str_cat2 (ret, "x_bearing=");
  rb_str_concat (ret, rb_inspect (cr_text_extents_x_bearing (self)));
  rb_str_cat2 (ret, ", ");
  rb_str_cat2 (ret, "y_bearing=");
  rb_str_concat (ret, rb_inspect (cr_text_extents_y_bearing (self)));
  rb_str_cat2 (ret, ", ");
  rb_str_cat2 (ret, "width=");
  rb_str_concat (ret, rb_inspect (cr_text_extents_width (self)));
  rb_str_cat2 (ret, ", ");
  rb_str_cat2 (ret, "height=");
  rb_str_concat (ret, rb_inspect (cr_text_extents_height (self)));
  rb_str_cat2 (ret, ", ");
  rb_str_cat2 (ret, "x_advance=");
  rb_str_concat (ret, rb_inspect (cr_text_extents_x_advance (self)));
  rb_str_cat2 (ret, ", ");
  rb_str_cat2 (ret, "y_advance=");
  rb_str_concat (ret, rb_inspect (cr_text_extents_y_advance (self)));
  rb_str_cat2 (ret, ">");
                 
  return ret;
}


void
Init_cairo_text_extents (void)
{
  rb_cCairo_TextExtents =
    rb_define_class_under (rb_mCairo, "TextExtents", rb_cObject);

  rb_define_method (rb_cCairo_TextExtents, "x_bearing",
                    cr_text_extents_x_bearing, 0);
  rb_define_method (rb_cCairo_TextExtents, "y_bearing",
                    cr_text_extents_y_bearing, 0);
  rb_define_method (rb_cCairo_TextExtents, "width",
                    cr_text_extents_width, 0);
  rb_define_method (rb_cCairo_TextExtents, "height",
                    cr_text_extents_height, 0);
  rb_define_method (rb_cCairo_TextExtents, "x_advance",
                    cr_text_extents_x_advance, 0);
  rb_define_method (rb_cCairo_TextExtents, "y_advance",
                    cr_text_extents_y_advance, 0);

  rb_define_method (rb_cCairo_TextExtents, "to_s",
                    cr_text_extents_to_s, 0);
}



More information about the cairo-commit mailing list