[cairo-commit] cairomm/cairomm Makefile.am, 1.2, 1.3 context.cc, 1.7, 1.8 context.h, 1.6, 1.7 fontface.cc, 1.3, 1.4 fontface.h, 1.3, 1.4 pattern.cc, 1.3, 1.4 pattern.h, 1.3, 1.4 refptr.h, NONE, 1.1 surface.cc, 1.3, 1.4 surface.h, 1.2, 1.3

Murray Cumming commit at pdx.freedesktop.org
Tue Dec 20 01:17:55 PST 2005


Committed by: murrayc

Update of /cvs/cairo/cairomm/cairomm
In directory gabe:/tmp/cvs-serv6437/cairomm

Modified Files:
	Makefile.am context.cc context.h fontface.cc fontface.h 
	pattern.cc pattern.h surface.cc surface.h 
Added Files:
	refptr.h 
Log Message:
2005-12-17  Murray Cumming  <murrayc at murrayc.com>

        * cairomm/Makefile.am:
        * cairomm/refptr.h: Add shared
        reference-counting smartpointer, using
        the reference-count in the object. A copy
        of the tried and tested glibmm RefPtr.
        * cairomm/context.cc:
        * cairomm/context.h:
        * cairomm/fontface.cc:
        * cairomm/fontface.h:
        * cairomm/pattern.cc:
        * cairomm/pattern.h:
        * cairomm/surface.cc:
        * cairomm/surface.h: Make constructors protected
        and add public static create() methods that return
        instances in RefPtr<>s. This allows reference-counted
        objects to be clearly const or non-const, and allows
        casting between related types.


Index: Makefile.am
===================================================================
RCS file: /cvs/cairo/cairomm/cairomm/Makefile.am,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Makefile.am	2 Dec 2005 16:11:18 -0000	1.2
+++ Makefile.am	20 Dec 2005 09:17:53 -0000	1.3
@@ -2,7 +2,7 @@
 
 INCLUDES = -I$(top_srcdir) @CAIROMM_CFLAGS@
 
-h_sources_public = cairomm.h context.h enums.h fontface.h fontoptions.h path.h pattern.h surface.h exception.h
+h_sources_public = cairomm.h context.h enums.h fontface.h fontoptions.h path.h pattern.h surface.h exception.h refptr.h
 h_sources_private = private.h
 cc_sources = context.cc fontface.cc fontoptions.cc path.cc pattern.cc surface.cc exception.cc
 cc_sources_private = private.cc

Index: context.cc
===================================================================
RCS file: /cvs/cairo/cairomm/cairomm/context.cc,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- context.cc	17 Dec 2005 15:21:24 -0000	1.7
+++ context.cc	20 Dec 2005 09:17:53 -0000	1.8
@@ -21,13 +21,18 @@
 namespace Cairo
 {
 
-Context::Context(Surface& target)
+Context::Context(const RefPtr<Surface>& target)
 : m_cobject(0)
 {
-  m_cobject = cairo_create(target.cobj());
+  m_cobject = cairo_create(target->cobj());
   check_object_status_and_throw_exception(*this);
 }
 
+RefPtr<Context> Context::create(const RefPtr<Surface>& target)
+{
+  return RefPtr<Context>(new Context(target));
+}
+
 Context::Context(cairo_t* cobject, bool has_reference)
 : m_cobject(0)
 {
@@ -37,15 +42,6 @@
     m_cobject = cairo_reference(cobject);
 }
 
-Context::Context(const Context& src)
-{
-  //Reference-counting, instead of copying by value:
-  if(!src.m_cobject)
-    m_cobject = 0;
-  else
-    m_cobject = cairo_reference(src.m_cobject);
-}
-
 Context::~Context()
 {
   if(m_cobject)
@@ -53,30 +49,15 @@
 }
 
 
-Context& Context::operator=(const Context& src)
+void Context::reference() const
 {
-  //Reference-counting, instead of copying by value:
-
-  if(this == &src)
-    return *this;
-
-  if(m_cobject == src.m_cobject)
-    return *this;
-
-  if(m_cobject)
-  {
-    cairo_destroy(m_cobject);
-    m_cobject = 0;
-  }
-
-  if(!src.m_cobject)
-    return *this;
-
-  m_cobject = cairo_reference(src.m_cobject);
-
-  return *this;
+ cairo_reference(m_cobject);
 }
 
+void Context::unreference() const
+{
+  cairo_destroy(m_cobject);
+}
 
 void Context::save()
 {
@@ -96,9 +77,9 @@
   check_object_status_and_throw_exception(*this);
 }
 
-void Context::set_source(const Pattern& source)
+void Context::set_source(const RefPtr<const Pattern>& source)
 {
-  cairo_set_source(m_cobject, const_cast<cairo_pattern_t*>(source.cobj()));
+  cairo_set_source(m_cobject, const_cast<cairo_pattern_t*>(source->cobj()));
   check_object_status_and_throw_exception(*this);
 }
 
@@ -115,9 +96,9 @@
   check_object_status_and_throw_exception(*this);
 }
 
-void Context::set_source(Surface& surface, double x, double y)
+void Context::set_source(const RefPtr<Surface>& surface, double x, double y)
 {
-  cairo_set_source_surface(m_cobject, surface.cobj(), x, y);
+  cairo_set_source_surface(m_cobject, surface->cobj(), x, y);
   check_object_status_and_throw_exception(*this);
 }
 
@@ -319,15 +300,15 @@
   check_object_status_and_throw_exception(*this);
 }
 
-void Context::mask(Pattern& pattern)
+void Context::mask(const RefPtr<Pattern>& pattern)
 {
-  cairo_mask(m_cobject, pattern.cobj());
+  cairo_mask(m_cobject, pattern->cobj());
   check_object_status_and_throw_exception(*this);
 }
 
-void Context::mask(Surface& surface, double surface_x, double surface_y)
+void Context::mask(const RefPtr<Surface>& surface, double surface_x, double surface_y)
 {
-  cairo_mask_surface(m_cobject, surface.cobj(), surface_x, surface_y);
+  cairo_mask_surface(m_cobject, surface->cobj(), surface_x, surface_y);
   check_object_status_and_throw_exception(*this);
 }
 
@@ -411,7 +392,7 @@
   check_object_status_and_throw_exception(*this);
 }
 
-void Context::select_font_face (const std::string& family, FontSlant slant, FontWeight weight)
+void Context::select_font_face(const std::string& family, FontSlant slant, FontWeight weight)
 {
   cairo_select_font_face (m_cobject, family.c_str(), (cairo_font_slant_t)slant, (cairo_font_weight_t)weight);
   check_object_status_and_throw_exception(*this);
@@ -453,11 +434,18 @@
   check_object_status_and_throw_exception(*this);
 }
 
-FontFace Context::get_font_face() const
+RefPtr<FontFace> Context::get_font_face()
 {
   cairo_font_face_t* cfontface = cairo_get_font_face(m_cobject);
   check_object_status_and_throw_exception(*this);
-  return FontFace(cfontface, false /* does not have reference */);
+  return RefPtr<FontFace>(new FontFace(cfontface, false /* does not have reference */));
+}
+
+RefPtr<const FontFace> Context::get_font_face() const
+{
+  cairo_font_face_t* cfontface = cairo_get_font_face(m_cobject);
+  check_object_status_and_throw_exception(*this);
+  return RefPtr<const FontFace>(new FontFace(cfontface, false /* does not have reference */));
 }
 
 void Context::get_font_extents(FontExtents& extents) const
@@ -466,9 +454,9 @@
   check_object_status_and_throw_exception(*this);
 }
 
-void Context::set_font_face(const FontFace& font_face)
+void Context::set_font_face(const RefPtr<const FontFace>& font_face)
 {
-  cairo_set_font_face(m_cobject, const_cast<cairo_font_face_t*>(font_face.cobj()));
+  cairo_set_font_face(m_cobject, const_cast<cairo_font_face_t*>(font_face->cobj()));
   check_object_status_and_throw_exception(*this);
 }
 
@@ -503,11 +491,18 @@
   return result;
 }
 
-Pattern Context::get_source() const
+RefPtr<Pattern> Context::get_source()
 {
   cairo_pattern_t* pattern = cairo_get_source(m_cobject);
   check_object_status_and_throw_exception(*this);
-  return Pattern(pattern, false /* does not have reference */);
+  return RefPtr<Pattern>(new Pattern(pattern, false /* does not have reference */));
+}
+
+RefPtr<const Pattern> Context::get_source() const
+{
+  cairo_pattern_t* pattern = cairo_get_source(m_cobject);
+  check_object_status_and_throw_exception(*this);
+  return RefPtr<const Pattern>(new Pattern(pattern, false /* does not have reference */));
 }
 
 double Context::get_tolerance() const
@@ -571,18 +566,18 @@
   check_object_status_and_throw_exception(*this);
 }
 
-Surface Context::get_target()
+RefPtr<Surface> Context::get_target()
 {
-  cairo_surface_t* surface = cairo_get_target(m_cobject);
+  cairo_surface_t* surface = cairo_get_target(const_cast<cairo_t*>(m_cobject));
   check_object_status_and_throw_exception(*this);
-  return Surface(surface, false /* does not have reference */);
+  return RefPtr<Surface>(new Surface(surface, false /* does not have reference */));
 }
 
-const Surface Context::get_target() const
+RefPtr<const Surface> Context::get_target() const
 {
   cairo_surface_t* surface = cairo_get_target(const_cast<cairo_t*>(m_cobject));
   check_object_status_and_throw_exception(*this);
-  return Surface(surface, false /* does not have reference */);
+  return RefPtr<const Surface>(new Surface(surface, false /* does not have reference */));
 }
 
 Path* Context::copy_path() const

Index: context.h
===================================================================
RCS file: /cvs/cairo/cairomm/cairomm/context.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- context.h	17 Dec 2005 15:21:24 -0000	1.6
+++ context.h	20 Dec 2005 09:17:53 -0000	1.7
@@ -53,36 +53,28 @@
  */
 class Context
 {
+protected:
+  explicit Context(const RefPtr<Surface>& target);
+
 public:
-  Context();
-  explicit Context(Surface& src);
 
-  /** Create a C++ wrapper for the C instance.
+  /** Create a C++ wrapper for the C instance. This C++ instance should then be given to a RefPtr.
    * @param cobject The C instance.
    * @param has_reference Whether we already have a reference. Otherwise, the constructor will take an extra reference.
    */
   explicit Context(cairo_t* cobject, bool has_reference = false);
 
-  /** Create a second reference to the context.
-   * Changing this instance will change the original instance.
-   */
-  Context(const Context& src);
+  static RefPtr<Context> create(const RefPtr<Surface>& target);
 
-  //TODO?: Context(cairo_surface_t *target);
   virtual ~Context();
 
-  /** Create a second reference to the context.
-   * Changing this instance will change the original instance.
-   */
-  Context& operator=(const Context& src);
-
   void save();
   void restore();
   void set_operator(Operator op);
-  void set_source(const Pattern& source);
+  void set_source(const RefPtr<const Pattern>& source);
   void set_source_rgb(double red, double green, double blue);
   void set_source_rgba(double red, double green, double blue, double alpha);
-  void set_source(Surface& surface, double x, double y);
+  void set_source(const RefPtr<Surface>& surface, double x, double y);
   void set_tolerance(double tolerance);
   void set_antialias(Antialias antialias);
   void set_fill_rule(FillRule fill_rule);
@@ -116,8 +108,8 @@
   void close_path();
   void paint();
   void paint_with_alpha(double alpha);
-  void mask(Pattern& pattern);
-  void mask(Surface& surface, double surface_x, double surface_y);
+  void mask(const RefPtr<Pattern>& pattern);
+  void mask(const RefPtr<Surface>& surface, double surface_x, double surface_y);
   void stroke();
   void stroke_preserve();
   void fill();
@@ -138,15 +130,17 @@
   void set_font_options(const FontOptions& options);
   void show_text(const std::string& utf8);
   void show_glyphs(const std::vector<Glyph>& glyphs);
-  FontFace get_font_face() const;
+  RefPtr<FontFace> get_font_face();
+  RefPtr<const FontFace> get_font_face() const;
   void get_font_extents(FontExtents& extents) const;
-  void set_font_face(const FontFace& font_face);
+  void set_font_face(const RefPtr<const FontFace>& font_face);
   void get_text_extents(const std::string& utf8, TextExtents& extents) const;
   void get_glyph_extents(const std::vector<Glyph>& glyphs, TextExtents& extents) const;
   void text_path(const std::string& utf8);
   void glyph_path(const std::vector<Glyph>& glyphs);
   Operator get_operator() const;
-  Pattern get_source() const;
+  RefPtr<Pattern> get_source();
+  RefPtr<const Pattern> get_source() const;
   double get_tolerance() const;
   Antialias get_antialias() const;
   void get_current_point (double& x, double& y) const;
@@ -158,8 +152,8 @@
   double get_miter_limit() const;
   void get_matrix(Matrix& matrix);
 
-  Surface get_target();
-  const Surface get_target() const;
+  RefPtr<Surface> get_target();
+  RefPtr<const Surface> get_target() const;
   
   //TODO: Copy or reference-count a Path somethow instead of asking the caller to delete it?
   Path* copy_path() const;
@@ -177,6 +171,9 @@
   { return cairo_status(const_cast<cairo_t*>(cobj())); }
   #endif //DOXYGEN_IGNORE_THIS
 
+  void reference() const;
+  void unreference() const;
+
 protected:
 
  

Index: fontface.cc
===================================================================
RCS file: /cvs/cairo/cairomm/cairomm/fontface.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- fontface.cc	17 Dec 2005 15:21:24 -0000	1.3
+++ fontface.cc	20 Dec 2005 09:17:53 -0000	1.4
@@ -30,44 +30,20 @@
     m_cobject = cairo_font_face_reference(cobject);
 }
 
-FontFace::FontFace(const FontFace& src)
-{
-  //Reference-counting, instead of copying by value:
-  if(!src.m_cobject)
-    m_cobject = 0;
-  else
-    m_cobject = cairo_font_face_reference(src.m_cobject);
-}
-
 FontFace::~FontFace()
 {
   if(m_cobject)
     cairo_font_face_destroy(m_cobject);
 }
 
-
-FontFace& FontFace::operator=(const FontFace& src)
+void FontFace::reference() const
 {
-  //Reference-counting, instead of copying by value:
-
-  if(this == &src)
-    return *this;
-
-  if(m_cobject == src.m_cobject)
-    return *this;
-
-  if(m_cobject)
-  {
-    cairo_font_face_destroy(m_cobject);
-    m_cobject = 0;
-  }
-
-  if(!src.m_cobject)
-    return *this;
-
-  m_cobject = cairo_font_face_reference(src.m_cobject);
+ cairo_font_face_reference(m_cobject);
+}
 
-  return *this;
+void FontFace::unreference() const
+{
+  cairo_font_face_destroy(m_cobject);
 }
 
 /*

Index: fontface.h
===================================================================
RCS file: /cvs/cairo/cairomm/cairomm/fontface.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- fontface.h	17 Dec 2005 15:21:24 -0000	1.3
+++ fontface.h	20 Dec 2005 09:17:53 -0000	1.4
@@ -31,28 +31,21 @@
  */
 class FontFace
 {
+protected:
+
+  //TODO?: FontFace(cairo_font_face_t *target);
+
 public:
-  FontFace();
 
-  /** Create a C++ wrapper for the C instance.
+  /** Create a C++ wrapper for the C instance. This C++ instance should then be given to a RefPtr.
    * @param cobject The C instance.
    * @param has_reference Whether we already have a reference. Otherwise, the constructor will take an extra reference.
    */
   explicit FontFace(cairo_font_face_t* cobject, bool has_reference = false);
 
-  /** Create a second reference to the FontFace.
-  * Changing this instance will change the original instance.
-  */
-  FontFace(const FontFace& src);
 
-  //TODO?: FontFace(cairo_font_face_t *target);
   virtual ~FontFace();
 
-  /** Create a second reference to the FontFace.
-  * Changing this instance will change the original instance.
-  */
-  FontFace& operator=(const FontFace& src);
-
   /* Don't wrap these until we know what they are good for.
   void* get_user_data(const cairo_user_data_key_t *key);
 
@@ -70,6 +63,9 @@
   { return cairo_font_face_status(const_cast<cairo_font_face_t*>(cobj())); }
   #endif //DOXYGEN_IGNORE_THIS
 
+  void reference() const;
+  void unreference() const;
+
 protected:
 
   cobject* m_cobject;

Index: pattern.cc
===================================================================
RCS file: /cvs/cairo/cairomm/cairomm/pattern.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- pattern.cc	8 Dec 2005 15:07:55 -0000	1.3
+++ pattern.cc	20 Dec 2005 09:17:53 -0000	1.4
@@ -35,48 +35,21 @@
     m_cobject = cairo_pattern_reference(cobject);
 }
 
-Pattern::Pattern(const Pattern& src)
-{
-  //Reference-counting, instead of copying by value:
-  if(!src.m_cobject)
-    m_cobject = 0;
-  else
-    m_cobject = cairo_pattern_reference(src.m_cobject);
-}
-
 Pattern::~Pattern()
 {
   if(m_cobject)
     cairo_pattern_destroy(m_cobject);
 }
 
-
-Pattern& Pattern::operator=(const Pattern& src)
+void Pattern::reference() const
 {
-  //Reference-counting, instead of copying by value:
-
-  if(this == &src)
-    return *this;
-
-  if(m_cobject == src.m_cobject)
-    return *this;
-
-  if(m_cobject)
-  {
-    cairo_pattern_destroy(m_cobject);
-    m_cobject = 0;
-  }
-
-  if(!src.m_cobject)
-    return *this;
-
-  m_cobject = cairo_pattern_reference(src.m_cobject);
-
-  return *this;
+ cairo_pattern_reference(m_cobject);
 }
 
-
-
+void Pattern::unreference() const
+{
+  cairo_pattern_destroy(m_cobject);
+}
 
 void Pattern::set_matrix(const cairo_matrix_t &matrix)
 {
@@ -97,42 +70,34 @@
 {
 }
 
-SolidPattern::SolidPattern(const SolidPattern& src)
-: Pattern(src)
-{
-}
-
 SolidPattern::~SolidPattern()
 {
 }
 
-SolidPattern SolidPattern::create_rgb(double red, double green, double blue)
+RefPtr<SolidPattern> SolidPattern::create_rgb(double red, double green, double blue)
 {
   cairo_pattern_t* cobject = cairo_pattern_create_rgb(red, green, blue);
   check_status_and_throw_exception(cairo_pattern_status(cobject)); 
-  return SolidPattern(cobject, true /* has reference */);
+  return RefPtr<SolidPattern>(new SolidPattern(cobject, true /* has reference */));
 }
 
-SolidPattern SolidPattern::create_rgba(double red, double green, double blue, double alpha)
+RefPtr<SolidPattern> SolidPattern::create_rgba(double red, double green, double blue, double alpha)
 {
   cairo_pattern_t* cobject  = cairo_pattern_create_rgba(red, green, blue, alpha);
   check_status_and_throw_exception(cairo_pattern_status(cobject));
-  return SolidPattern(cobject, true /* has reference */);
+  return RefPtr<SolidPattern>(new SolidPattern(cobject, true /* has reference */));
 }
 
 
-SolidPattern& SolidPattern::operator=(const SolidPattern& src)
+SurfacePattern::SurfacePattern(const RefPtr<Surface>& surface)
 {
-  Pattern::operator=(src);
-
-  return *this;
+  m_cobject = cairo_pattern_create_for_surface(surface->cobj());
+  check_object_status_and_throw_exception(*this); 
 }
 
-
-SurfacePattern::SurfacePattern(Surface& surface)
+RefPtr<SurfacePattern> SurfacePattern::create(const RefPtr<Surface>& surface)
 {
-  m_cobject = cairo_pattern_create_for_surface(surface.cobj());
-  check_object_status_and_throw_exception(*this); 
+  return RefPtr<SurfacePattern>(new SurfacePattern(surface));
 }
 
 SurfacePattern::SurfacePattern(cairo_pattern_t* cobject, bool has_reference)
@@ -140,23 +105,10 @@
 {
 }
 
-SurfacePattern::SurfacePattern(const SurfacePattern& src)
-: Pattern(src)
-{
-}
-
 SurfacePattern::~SurfacePattern()
 {
 }
 
-
-SurfacePattern& SurfacePattern::operator=(const SurfacePattern& src)
-{
-  Pattern::operator=(src);
-
-  return *this;
-}
-
 void SurfacePattern::set_extend(Extend extend)
 {
   cairo_pattern_set_extend(m_cobject, (cairo_extend_t)extend);
@@ -194,22 +146,10 @@
 {
 }
 
-Gradient::Gradient(const Gradient& src)
-: Pattern(src)
-{
-}
-
 Gradient::~Gradient()
 {
 }
 
-Gradient& Gradient::operator=(const Gradient& src)
-{
-  Pattern::operator=(src);
-
-  return *this;
-}
-
 void Gradient::add_color_stop_rgb(double offset, double red, double green, double blue)
 {
   cairo_pattern_add_color_stop_rgb(m_cobject, offset, red, green, blue);
@@ -230,13 +170,13 @@
   check_object_status_and_throw_exception(*this); 
 }
 
-LinearGradient::LinearGradient(cairo_pattern_t* cobject, bool has_reference)
-: Gradient(cobject, has_reference)
+RefPtr<LinearGradient> LinearGradient::create(double x0, double y0, double x1, double y1)
 {
+  return RefPtr<LinearGradient>(new LinearGradient(x0, y0, x1, y1));
 }
 
-LinearGradient::LinearGradient(const LinearGradient& src)
-: Gradient(src)
+LinearGradient::LinearGradient(cairo_pattern_t* cobject, bool has_reference)
+: Gradient(cobject, has_reference)
 {
 }
 
@@ -245,27 +185,19 @@
 }
 
 
-LinearGradient& LinearGradient::operator=(const LinearGradient& src)
-{
-  Gradient::operator=(src);
-
-  return *this;
-}
-
-
 RadialGradient::RadialGradient(double cx0, double cy0, double radius0, double cx1, double cy1, double radius1)
 {
   m_cobject = cairo_pattern_create_radial(cx0, cy0, radius0, cx1, cy1, radius1);
   check_object_status_and_throw_exception(*this); 
 }
 
-RadialGradient::RadialGradient(cairo_pattern_t* cobject, bool has_reference)
-: Gradient(cobject, has_reference)
+RefPtr<RadialGradient> RadialGradient::create(double cx0, double cy0, double radius0, double cx1, double cy1, double radius1)
 {
+  return RefPtr<RadialGradient>(new RadialGradient(cx0, cy0, radius0, cx1, cy1, radius1));
 }
 
-RadialGradient::RadialGradient(const RadialGradient& src)
-: Gradient(src)
+RadialGradient::RadialGradient(cairo_pattern_t* cobject, bool has_reference)
+: Gradient(cobject, has_reference)
 {
 }
 
@@ -274,12 +206,6 @@
 }
 
 
-RadialGradient& RadialGradient::operator=(const RadialGradient& src)
-{
-  Gradient::operator=(src);
-
-  return *this;
-}
 
 
 

Index: pattern.h
===================================================================
RCS file: /cvs/cairo/cairomm/cairomm/pattern.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- pattern.h	8 Dec 2005 15:07:55 -0000	1.3
+++ pattern.h	20 Dec 2005 09:17:53 -0000	1.4
@@ -35,28 +35,21 @@
  */
 class Pattern
 {
-public:
+protected:
   //Use derived constructors.
 
-  /** Create a C++ wrapper for the C instance.
+  //TODO?: Pattern(cairo_pattern_t *target);
+
+public:
+
+  /** Create a C++ wrapper for the C instance. This C++ instance should then be given to a RefPtr.
    * @param cobject The C instance.
    * @param has_reference Whether we already have a reference. Otherwise, the constructor will take an extra reference.
    */
   explicit Pattern(cairo_pattern_t* cobject, bool has_reference = false);
 
-  /** Create a second reference to the Pattern.
-  * Changing this instance will change the original instance.
-  */
-  Pattern(const Pattern& src);
-
-  //TODO?: Pattern(cairo_pattern_t *target);
   virtual ~Pattern();
 
-  /** Create a second reference to the Pattern.
-  * Changing this instance will change the original instance.
-  */
-  Pattern& operator=(const Pattern& src);
-
   void set_matrix(const cairo_matrix_t &matrix);
   void get_matrix(cairo_matrix_t &matrix) const;
 
@@ -70,6 +63,9 @@
   { return cairo_pattern_status(const_cast<cairo_pattern_t*>(cobj())); }
   #endif //DOXYGEN_IGNORE_THIS
 
+  void reference() const;
+  void unreference() const;
+
 protected:
   //Used by derived types only.
   Pattern();
@@ -79,10 +75,9 @@
 
 class SolidPattern : public Pattern
 {
-public:
+protected:
 
-  static SolidPattern create_rgb(double red, double green, double blue);
-  static SolidPattern create_rgba(double red, double green, double blue, double alpha);
+public:
 
   /** Create a C++ wrapper for the C instance.
    * @param cobject The C instance.
@@ -90,44 +85,33 @@
    */
   explicit SolidPattern(cairo_pattern_t* cobject, bool has_reference = false);
 
-  /** Create a second reference to the Pattern.
-  * Changing this instance will change the original instance.
-  */
-  SolidPattern(const SolidPattern& src);
+  static RefPtr<SolidPattern> create_rgb(double red, double green, double blue);
+  static RefPtr<SolidPattern> create_rgba(double red, double green, double blue, double alpha);
 
   //TODO?: SolidPattern(cairo_pattern_t *target);
   virtual ~SolidPattern();
-
-  /** Create a second reference to the Pattern.
-  * Changing this instance will change the original instance.
-  */
-  SolidPattern& operator=(const SolidPattern& src);
 };
 
 class SurfacePattern : public Pattern
 {
-public:
+protected:
 
-  explicit SurfacePattern(Surface& surface);
+  explicit SurfacePattern(const RefPtr<Surface>& surface);
 
-  /** Create a C++ wrapper for the C instance.
+  //TODO?: SurfacePattern(cairo_pattern_t *target);
+
+public:
+
+  /** Create a C++ wrapper for the C instance. This C++ instance should then be given to a RefPtr.
    * @param cobject The C instance.
    * @param has_reference Whether we already have a reference. Otherwise, the constructor will take an extra reference.
    */
   explicit SurfacePattern(cairo_pattern_t* cobject, bool has_reference = false);
 
-  /** Create a second reference to the Pattern.
-  * Changing this instance will change the original instance.
-  */
-  SurfacePattern(const SurfacePattern& src);
 
-  //TODO?: SurfacePattern(cairo_pattern_t *target);
   virtual ~SurfacePattern();
 
-  /** Create a second reference to the Pattern.
-  * Changing this instance will change the original instance.
-  */
-  SurfacePattern& operator=(const SurfacePattern& src);
+  static RefPtr<SurfacePattern> create(const RefPtr<Surface>& surface);
 
   void set_extend(Extend extend);
   Extend get_extend() const;
@@ -137,28 +121,21 @@
 
 class Gradient : public Pattern
 {
-public:
+protected:
   //Use derived constructors.
 
-  /** Create a C++ wrapper for the C instance.
+  //TODO?: Gradient(cairo_pattern_t *target);
+
+public:
+
+  /** Create a C++ wrapper for the C instance. This C++ instance should then be given to a RefPtr.
    * @param cobject The C instance.
    * @param has_reference Whether we already have a reference. Otherwise, the constructor will take an extra reference.
    */
   explicit Gradient(cairo_pattern_t* cobject, bool has_reference = false);
 
-  /** Create a second reference to the Pattern.
-  * Changing this instance will change the original instance.
-  */
-  Gradient(const Gradient& src);
-
-  //TODO?: Gradient(cairo_pattern_t *target);
   virtual ~Gradient();
 
-  /** Create a second reference to the Pattern.
-  * Changing this instance will change the original instance.
-  */
-  Gradient& operator=(const Gradient& src);
-
   void add_color_stop_rgb(double offset, double red, double green, double blue);
   void add_color_stop_rgba(double offset, double red, double green, double blue, double alpha);
 
@@ -168,54 +145,43 @@
 
 class LinearGradient : public Gradient
 {
-public:
+protected:
 
   LinearGradient(double x0, double y0, double x1, double y1);
 
-  /** Create a C++ wrapper for the C instance.
+public:
+
+  /** Create a C++ wrapper for the C instance. This C++ instance should then be given to a RefPtr.
    * @param cobject The C instance.
    * @param has_reference Whether we already have a reference. Otherwise, the constructor will take an extra reference.
    */
   explicit LinearGradient(cairo_pattern_t* cobject, bool has_reference = false);
 
-  /** Create a second reference to the Pattern.
-  * Changing this instance will change the original instance.
-  */
-  LinearGradient(const LinearGradient& src);
-
   //TODO?: LinearGradient(cairo_pattern_t *target);
   virtual ~LinearGradient();
 
-  /** Create a second reference to the Pattern.
-  * Changing this instance will change the original instance.
-  */
-  LinearGradient& operator=(const LinearGradient& src);
+  static RefPtr<LinearGradient> create(double x0, double y0, double x1, double y1);
 };
 
 class RadialGradient : public Gradient
 {
-public:
+protected:
 
   RadialGradient(double cx0, double cy0, double radius0, double cx1, double cy1, double radius1);
 
-  /** Create a C++ wrapper for the C instance.
+public:
+
+  /** Create a C++ wrapper for the C instance. This C++ instance should then be given to a RefPtr.
    * @param cobject The C instance.
    * @param has_reference Whether we already have a reference. Otherwise, the constructor will take an extra reference.
    */
   explicit RadialGradient(cairo_pattern_t* cobject, bool has_reference = false);
 
-  /** Create a second reference to the Pattern.
-  * Changing this instance will change the original instance.
-  */
-  RadialGradient(const RadialGradient& src);
 
   //TODO?: RadialGradient(cairo_pattern_t *target);
   virtual ~RadialGradient();
 
-  /** Create a second reference to the Pattern.
-  * Changing this instance will change the original instance.
-  */
-  RadialGradient& operator=(const RadialGradient& src);
+  static RefPtr<RadialGradient> create(double cx0, double cy0, double radius0, double cx1, double cy1, double radius1);
 };
 
 } // namespace Cairo

--- NEW FILE: refptr.h ---
// -*- c++ -*-
#ifndef _cairo_REFPTR_H
#define _cairo_REFPTR_H

/* $Id: refptr.h,v 1.1 2005/12/20 09:17:53 murrayc Exp $ */

/* Copyright 2005 The cairomm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */


namespace Cairo
{

/** RefPtr<> is a reference-counting shared smartpointer.
 *
 * Some objects in gtkmm are obtained from a shared
 * store. Consequently you cannot instantiate them yourself. Instead they
 * return a RefPtr which behaves much like an ordinary pointer in that members
 * can be reached with the usual <code>object_ptr->member</code> notation.
 * Unlike most other smart pointers, RefPtr doesn't support dereferencing
 * through <code>*object_ptr</code>.
 *
 * Reference counting means that a shared reference count is incremented each
 * time a RefPtr is copied, and decremented each time a RefPtr is destroyed,
 * for instance when it leaves its scope. When the reference count reaches
 * zero, the contained object is deleted, meaning  you don't need to remember
 * to delete the object.
 *
 * RefPtr<> can store any class that has reference() and unreference() methods.
 */
template <class T_CppObject>
class RefPtr
{
public:
  /** Default constructor
   *
   * Afterwards it will be null and use of -> will cause a segmentation fault.
   */
  inline RefPtr();
  
  /// Destructor - decrements reference count.
  inline ~RefPtr();

  /// For use only by the ::create() methods.
  explicit inline RefPtr(T_CppObject* pCppObject);

  /** Copy constructor
   *
   * This increments the shared reference count.
   */
  inline RefPtr(const RefPtr<T_CppObject>& src);

  /** Copy constructor (from different, but castable type).
   *
   * Increments the reference count.
   */
  template <class T_CastFrom>
  inline RefPtr(const RefPtr<T_CastFrom>& src);

  /** Swap the contents of two RefPtr<>.
   * This method swaps the internal pointers to T_CppObject.  This can be
   * done safely without involving a reference/unreference cycle and is
   * therefore highly efficient.
   */
  inline void swap(RefPtr<T_CppObject>& other);

  /// Copy from another RefPtr:
  inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CppObject>& src);

  /** Copy from different, but castable type).
   *
   * Increments the reference count.
   */
  template <class T_CastFrom>
  inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CastFrom>& src);

  /// Tests whether the RefPtr<> point to the same underlying instance.
  inline bool operator==(const RefPtr<T_CppObject>& src) const;
  
  /// See operator==().
  inline bool operator!=(const RefPtr<T_CppObject>& src) const;

  /** Dereferencing.
   *
   * Use the methods of the underlying instance like so:
   * <code>refptr->memberfun()</code>.
   */
  inline T_CppObject* operator->() const;

  /** Test whether the RefPtr<> points to any underlying instance.
   *
   * Mimics usage of ordinary pointers:
   * @code
   *   if (ptr)
   *     do_something();
   * @endcode
   */
  inline operator bool() const;

  /// Set underlying instance to 0, decrementing reference count of existing instance appropriately.
  inline void clear();


  /** Dynamic cast to derived class.
   *
   * The RefPtr can't be cast with the usual notation so instead you can use
   * @code
   *   ptr_derived = RefPtr<Derived>::cast_dynamic(ptr_base);
   * @endcode
   */
  template <class T_CastFrom>
  static inline RefPtr<T_CppObject> cast_dynamic(const RefPtr<T_CastFrom>& src);

  /** Static cast to derived class.
   *
   * Like the dynamic cast; the notation is 
   * @code
   *   ptr_derived = RefPtr<Derived>::cast_static(ptr_base);
   * @endcode
   */
  template <class T_CastFrom>
  static inline RefPtr<T_CppObject> cast_static(const RefPtr<T_CastFrom>& src);

  /** Cast to non-const.
   *
   * The RefPtr can't be cast with the usual notation so instead you can use
   * @code
   *   ptr_unconst = RefPtr<UnConstType>::cast_const(ptr_const);
   * @endcode
   */
  template <class T_CastFrom>
  static inline RefPtr<T_CppObject> cast_const(const RefPtr<T_CastFrom>& src);

private:
  T_CppObject* pCppObject_;
};


#ifndef DOXYGEN_SHOULD_SKIP_THIS

// RefPtr<>::operator->() comes first here since it's used by other methods.
// If it would come after them it wouldn't be inlined.

template <class T_CppObject> inline
T_CppObject* RefPtr<T_CppObject>::operator->() const
{
  return pCppObject_;
}

template <class T_CppObject> inline
RefPtr<T_CppObject>::RefPtr()
:
  pCppObject_ (0)
{}

template <class T_CppObject> inline
RefPtr<T_CppObject>::~RefPtr()
{
  if(pCppObject_)
    pCppObject_->unreference(); // This could cause pCppObject to be deleted.
}

template <class T_CppObject> inline
RefPtr<T_CppObject>::RefPtr(T_CppObject* pCppObject)
:
  pCppObject_ (pCppObject)
{}

template <class T_CppObject> inline
RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CppObject>& src)
:
  pCppObject_ (src.pCppObject_)
{
  if(pCppObject_)
    pCppObject_->reference();
}

// The templated ctor allows copy construction from any object that's
// castable.  Thus, it does downcasts:
//   base_ref = derived_ref
template <class T_CppObject>
  template <class T_CastFrom>
inline
RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CastFrom>& src)
:
  // A different RefPtr<> will not allow us access to pCppObject_.  We need
  // to add a get_underlying() for this, but that would encourage incorrect
  // use, so we use the less well-known operator->() accessor:
  pCppObject_ (src.operator->())
{
  if(pCppObject_)
    pCppObject_->reference();
}

template <class T_CppObject> inline
void RefPtr<T_CppObject>::swap(RefPtr<T_CppObject>& other)
{
  T_CppObject *const temp = pCppObject_;
  pCppObject_ = other.pCppObject_;
  other.pCppObject_ = temp;
}

template <class T_CppObject> inline
RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CppObject>& src)
{
  // In case you haven't seen the swap() technique to implement copy
  // assignment before, here's what it does:
  //
  // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
  //    increasing the reference count of the source object.
  //
  // 2) Swap the internal object pointers of *this and the temporary
  //    RefPtr<>.  After this step, *this already contains the new pointer,
  //    and the old pointer is now managed by temp.
  //
  // 3) The destructor of temp is executed, thereby unreferencing the
  //    old object pointer.
  //
  // This technique is described in Herb Sutter's "Exceptional C++", and
  // has a number of advantages over conventional approaches:
  //
  // - Code reuse by calling the copy ctor.
  // - Strong exception safety for free.
  // - Self assignment is handled implicitely.
  // - Simplicity.
  // - It just works and is hard to get wrong; i.e. you can use it without
  //   even thinking about it to implement copy assignment whereever the
  //   object data is managed indirectly via a pointer, which is very common.

  RefPtr<T_CppObject> temp (src);
  this->swap(temp);
  return *this;
}

template <class T_CppObject>
  template <class T_CastFrom>
inline
RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CastFrom>& src)
{
  RefPtr<T_CppObject> temp (src);
  this->swap(temp);
  return *this;
}

template <class T_CppObject> inline
bool RefPtr<T_CppObject>::operator==(const RefPtr<T_CppObject>& src) const
{
  return (pCppObject_ == src.pCppObject_);
}

template <class T_CppObject> inline
bool RefPtr<T_CppObject>::operator!=(const RefPtr<T_CppObject>& src) const
{
  return (pCppObject_ != src.pCppObject_);
}

template <class T_CppObject> inline
RefPtr<T_CppObject>::operator bool() const
{
  return (pCppObject_ != 0);
}

template <class T_CppObject> inline
void RefPtr<T_CppObject>::clear()
{
  RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
  this->swap(temp);
}

template <class T_CppObject>
  template <class T_CastFrom>
inline
RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_dynamic(const RefPtr<T_CastFrom>& src)
{
  T_CppObject *const pCppObject = dynamic_cast<T_CppObject*>(src.operator->());

  if(pCppObject)
    pCppObject->reference();

  return RefPtr<T_CppObject>(pCppObject);
}

template <class T_CppObject>
  template <class T_CastFrom>
inline
RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_static(const RefPtr<T_CastFrom>& src)
{
  T_CppObject *const pCppObject = static_cast<T_CppObject*>(src.operator->());

  if(pCppObject)
    pCppObject->reference();

  return RefPtr<T_CppObject>(pCppObject);
}

template <class T_CppObject>
  template <class T_CastFrom>
inline
RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_const(const RefPtr<T_CastFrom>& src)
{
  T_CppObject *const pCppObject = const_cast<T_CppObject*>(src.operator->());

  if(pCppObject)
    pCppObject->reference();

  return RefPtr<T_CppObject>(pCppObject);
}

#endif /* DOXYGEN_SHOULD_SKIP_THIS */

/** @relates Glib::RefPtr */
template <class T_CppObject> inline
void swap(RefPtr<T_CppObject>& lhs, RefPtr<T_CppObject>& rhs)
{
  lhs.swap(rhs);
}

} // namespace Cairo


#endif /* _cairo_REFPTR_H */


Index: surface.cc
===================================================================
RCS file: /cvs/cairo/cairomm/cairomm/surface.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- surface.cc	7 Dec 2005 14:41:10 -0000	1.3
+++ surface.cc	20 Dec 2005 09:17:53 -0000	1.4
@@ -21,7 +21,7 @@
 namespace Cairo
 {
 
-Surface::Surface(cairo_surface_t*  cobject, bool has_reference)
+Surface::Surface(cairo_surface_t* cobject, bool has_reference)
 : m_cobject(0)
 {
   if(has_reference)
@@ -30,65 +30,31 @@
     m_cobject = cairo_surface_reference(cobject);
 }
 
-Surface::Surface(const Surface& src)
-{
-  //Reference-counting, instead of copying by value:
-  if(!src.m_cobject)
-    m_cobject = 0;
-  else
-    m_cobject = cairo_surface_reference(src.m_cobject);
-}
-
 Surface::~Surface()
 {
   if(m_cobject)
     cairo_surface_destroy(m_cobject);
 }
 
-
-Surface& Surface::operator=(const Surface& src)
-{
-  //Reference-counting, instead of copying by value:
-
-  if(this == &src)
-    return *this;
-
-  if(m_cobject == src.m_cobject)
-    return *this;
-
-  if(m_cobject)
-  {
-    cairo_surface_destroy(m_cobject);
-    m_cobject = 0;
-  }
-
-  if(!src.m_cobject)
-    return *this;
-
-  m_cobject = cairo_surface_reference(src.m_cobject);
-
-  return *this;
-}
-
-Surface Surface::create(Format format, int width, int height)
+RefPtr<Surface> Surface::create(Format format, int width, int height)
 {
   cairo_surface_t* cobject = cairo_image_surface_create((cairo_format_t)format, width, height);
   check_status_and_throw_exception(cairo_surface_status(cobject));
-  return Surface(cobject, true /* has reference */);
+  return RefPtr<Surface>(new Surface(cobject, true /* has reference */));
 }
 
-Surface Surface::create(unsigned char* data, Format format, int width, int height, int stride)
+RefPtr<Surface> Surface::create(unsigned char* data, Format format, int width, int height, int stride)
 {
   cairo_surface_t* cobject = cairo_image_surface_create_for_data(data, (cairo_format_t)format, width, height, stride);
   check_status_and_throw_exception(cairo_surface_status(cobject));
-  return Surface(cobject, true /* has reference */);
+  return RefPtr<Surface>(new Surface(cobject, true /* has reference */));
 }
 
-Surface Surface::create(const Surface& other, Content content, int width, int height)
+RefPtr<Surface> Surface::create(const Surface& other, Content content, int width, int height)
 {
   cairo_surface_t* cobject = cairo_surface_create_similar(other.m_cobject, (cairo_content_t)content, width, height);
   check_status_and_throw_exception(cairo_surface_status(cobject));
-  return Surface(cobject, true /* has reference */);
+  return RefPtr<Surface>(new Surface(cobject, true /* has reference */));
 }
 
 void Surface::finish()

Index: surface.h
===================================================================
RCS file: /cvs/cairo/cairomm/cairomm/surface.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- surface.h	2 Dec 2005 14:05:17 -0000	1.2
+++ surface.h	20 Dec 2005 09:17:53 -0000	1.3
@@ -20,6 +20,7 @@
 
 #include <cairomm/fontoptions.h>
 #include <cairomm/enums.h>
+#include <cairomm/refptr.h>
 #include <cairo/cairo.h>
 
 
@@ -37,34 +38,22 @@
  */
 class Surface
 {
+protected:
+  //TODO?: Surface(cairo_surface_t *target);
+
 public:
-  Surface();
 
-  /** Create a C++ wrapper for the C instance.
+  /** Create a C++ wrapper for the C instance. This C++ instance should then be given to a RefPtr.
    * @param cobject The C instance.
    * @param has_reference Whether we already have a reference. Otherwise, the constructor will take an extra reference.
    */
   explicit Surface(cairo_surface_t* cobject, bool has_reference = false);
 
-  /** Create a second reference to the surface.
-  * Changing this instance will change the original instance.
-  */
-  Surface(const Surface& src);
-
-  //TODO?: Surface(cairo_surface_t *target);
   virtual ~Surface();
 
-  /** Create a second reference to the surface.
-  * Changing this instance will change the original instance.
-  */
-  Surface& operator=(const Surface& src);
-
-  //We use create_*() methods, instead of constructors, because
-  //a) We want to make it clear that these are new instance, not just new references to the same instances.
-  //b) Overloading on parameter types are not always enough to distinguish them.
-  static Surface create(const Surface& other, Content content, int width, int height);
-  static Surface create(Format format, int width, int height);
-  static Surface create(unsigned char* data, Format format, int width, int height, int stride);
+  static RefPtr<Surface> create(const Surface& other, Content content, int width, int height);
+  static RefPtr<Surface> create(Format format, int width, int height);
+  static RefPtr<Surface> create(unsigned char* data, Format format, int width, int height, int stride);
 
   //void write_to_png(const std::string& filename);
   //void write_to_png_stream(cairo_write_func_t write_func, void *closure); //TODO: Use a sigc::slot?
@@ -98,6 +87,9 @@
   { return cairo_surface_status(const_cast<cairo_surface_t*>(cobj())); }
   #endif //DOXYGEN_IGNORE_THIS
 
+  void reference() const;
+  void unreference() const;
+
 protected:
   cobject* m_cobject;
 };



More information about the cairo-commit mailing list