+wxCairoPathData::~wxCairoPathData()
+{
+ cairo_destroy(m_pathContext);
+}
+
+wxGraphicsObjectRefData *wxCairoPathData::Clone() const
+{
+ cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,1,1);
+ cairo_t* pathcontext = cairo_create(surface);
+ cairo_surface_destroy (surface);
+
+ cairo_path_t* path = cairo_copy_path(m_pathContext);
+ cairo_append_path(pathcontext, path);
+ cairo_path_destroy(path);
+ return new wxCairoPathData( GetRenderer() ,pathcontext);
+}
+
+
+void* wxCairoPathData::GetNativePath() const
+{
+ return cairo_copy_path(m_pathContext) ;
+}
+
+void wxCairoPathData::UnGetNativePath(void *p) const
+{
+ cairo_path_destroy((cairo_path_t*)p);
+}
+
+//
+// The Primitives
+//
+
+void wxCairoPathData::MoveToPoint( wxDouble x , wxDouble y )
+{
+ cairo_move_to(m_pathContext,x,y);
+}
+
+void wxCairoPathData::AddLineToPoint( wxDouble x , wxDouble y )
+{
+ cairo_line_to(m_pathContext,x,y);
+}
+
+void wxCairoPathData::AddPath( const wxGraphicsPathData* path )
+{
+ cairo_path_t* p = (cairo_path_t*)path->GetNativePath();
+ cairo_append_path(m_pathContext, p);
+ UnGetNativePath(p);
+}
+
+void wxCairoPathData::CloseSubpath()
+{
+ cairo_close_path(m_pathContext);
+}
+
+void wxCairoPathData::AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y )
+{
+ cairo_curve_to(m_pathContext,cx1,cy1,cx2,cy2,x,y);
+}
+
+// gets the last point of the current path, (0,0) if not yet set
+void wxCairoPathData::GetCurrentPoint( wxDouble* x, wxDouble* y) const
+{
+ double dx,dy;
+ cairo_get_current_point(m_pathContext,&dx,&dy);
+ if (x)
+ *x = dx;
+ if (y)
+ *y = dy;
+}
+
+void wxCairoPathData::AddArc( wxDouble x, wxDouble y, wxDouble r, double startAngle, double endAngle, bool clockwise )
+{
+ // as clockwise means positive in our system (y pointing downwards)
+ // TODO make this interpretation dependent of the
+ // real device trans
+ if ( clockwise||(endAngle-startAngle)>=2*M_PI)
+ cairo_arc(m_pathContext,x,y,r,startAngle,endAngle);
+ else
+ cairo_arc_negative(m_pathContext,x,y,r,startAngle,endAngle);
+}
+
+// transforms each point of this path by the matrix
+void wxCairoPathData::Transform( const wxGraphicsMatrixData* matrix )
+{
+ // as we don't have a true path object, we have to apply the inverse
+ // matrix to the context
+ cairo_matrix_t m = *((cairo_matrix_t*) matrix->GetNativeMatrix());
+ cairo_matrix_invert( &m );
+ cairo_transform(m_pathContext,&m);
+}
+
+// gets the bounding box enclosing all points (possibly including control points)
+void wxCairoPathData::GetBox(wxDouble *x, wxDouble *y, wxDouble *w, wxDouble *h) const
+{
+ double x1,y1,x2,y2;
+
+ cairo_stroke_extents( m_pathContext, &x1, &y1, &x2, &y2 );
+ if ( x2 < x1 )
+ {
+ *x = x2;
+ *w = x1-x2;
+ }
+ else
+ {
+ *x = x1;
+ *w = x2-x1;
+ }
+
+ if( y2 < y1 )
+ {
+ *y = y2;
+ *h = y1-y2;
+ }
+ else
+ {
+ *y = y1;
+ *h = y2-y1;
+ }
+}
+
+bool wxCairoPathData::Contains( wxDouble x, wxDouble y, wxPolygonFillMode fillStyle ) const
+{
+ cairo_set_fill_rule(m_pathContext,fillStyle==wxODDEVEN_RULE ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
+ return cairo_in_fill( m_pathContext, x, y) != 0;
+}
+
+//-----------------------------------------------------------------------------
+// wxCairoMatrixData implementation
+//-----------------------------------------------------------------------------
+
+wxCairoMatrixData::wxCairoMatrixData(wxGraphicsRenderer* renderer, const cairo_matrix_t* matrix )
+ : wxGraphicsMatrixData(renderer)
+{
+ if ( matrix )
+ m_matrix = *matrix;
+}
+
+wxCairoMatrixData::~wxCairoMatrixData()
+{
+ // nothing to do
+}
+
+wxGraphicsObjectRefData *wxCairoMatrixData::Clone() const
+{
+ return new wxCairoMatrixData(GetRenderer(),&m_matrix);
+}
+
+// concatenates the matrix
+void wxCairoMatrixData::Concat( const wxGraphicsMatrixData *t )
+{
+ cairo_matrix_multiply( &m_matrix, &m_matrix, (cairo_matrix_t*) t->GetNativeMatrix());
+}
+
+// sets the matrix to the respective values
+void wxCairoMatrixData::Set(wxDouble a, wxDouble b, wxDouble c, wxDouble d,
+ wxDouble tx, wxDouble ty)
+{
+ cairo_matrix_init( &m_matrix, a, b, c, d, tx, ty);
+}
+
+// gets the component valuess of the matrix
+void wxCairoMatrixData::Get(wxDouble* a, wxDouble* b, wxDouble* c,
+ wxDouble* d, wxDouble* tx, wxDouble* ty) const
+{
+ if (a) *a = m_matrix.xx;
+ if (b) *b = m_matrix.yx;
+ if (c) *c = m_matrix.xy;
+ if (d) *d = m_matrix.yy;
+ if (tx) *tx= m_matrix.x0;
+ if (ty) *ty= m_matrix.y0;
+}
+
+// makes this the inverse matrix
+void wxCairoMatrixData::Invert()
+{
+ cairo_matrix_invert( &m_matrix );
+}
+
+// returns true if the elements of the transformation matrix are equal ?
+bool wxCairoMatrixData::IsEqual( const wxGraphicsMatrixData* t) const
+{
+ const cairo_matrix_t* tm = (cairo_matrix_t*) t->GetNativeMatrix();
+ return (
+ m_matrix.xx == tm->xx &&
+ m_matrix.yx == tm->yx &&
+ m_matrix.xy == tm->xy &&
+ m_matrix.yy == tm->yy &&
+ m_matrix.x0 == tm->x0 &&
+ m_matrix.y0 == tm->y0 ) ;
+}
+
+// return true if this is the identity matrix
+bool wxCairoMatrixData::IsIdentity() const
+{
+ return ( m_matrix.xx == 1 && m_matrix.yy == 1 &&
+ m_matrix.yx == 0 && m_matrix.xy == 0 && m_matrix.x0 == 0 && m_matrix.y0 == 0);
+}
+
+//
+// transformation
+//
+
+// add the translation to this matrix
+void wxCairoMatrixData::Translate( wxDouble dx , wxDouble dy )
+{
+ cairo_matrix_translate( &m_matrix, dx, dy) ;
+}
+
+// add the scale to this matrix
+void wxCairoMatrixData::Scale( wxDouble xScale , wxDouble yScale )
+{
+ cairo_matrix_scale( &m_matrix, xScale, yScale) ;
+}
+
+// add the rotation to this matrix (radians)
+void wxCairoMatrixData::Rotate( wxDouble angle )
+{
+ cairo_matrix_rotate( &m_matrix, angle) ;
+}
+
+//
+// apply the transforms
+//
+
+// applies that matrix to the point
+void wxCairoMatrixData::TransformPoint( wxDouble *x, wxDouble *y ) const
+{
+ double lx = *x, ly = *y ;
+ cairo_matrix_transform_point( &m_matrix, &lx, &ly);
+ *x = lx;
+ *y = ly;
+}
+
+// applies the matrix except for translations
+void wxCairoMatrixData::TransformDistance( wxDouble *dx, wxDouble *dy ) const
+{
+ double lx = *dx, ly = *dy ;
+ cairo_matrix_transform_distance( &m_matrix, &lx, &ly);
+ *dx = lx;
+ *dy = ly;
+}
+
+// returns the native representation
+void * wxCairoMatrixData::GetNativeMatrix() const
+{
+ return (void*) &m_matrix;
+}
+
+// wxCairoBitmap implementation
+//-----------------------------------------------------------------------------
+
+wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, cairo_surface_t* bitmap ) :
+ wxGraphicsObjectRefData( renderer )
+{
+ m_surface = bitmap;
+ m_pattern = cairo_pattern_create_for_surface(m_surface);
+}
+
+wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitmap& bmp ) : wxGraphicsObjectRefData( renderer )
+{
+ wxCHECK_RET( bmp.IsOk(), wxT("Invalid bitmap in wxCairoContext::DrawBitmap"));
+
+ int bw = m_width = bmp.GetWidth();
+ int bh = m_height = bmp.GetHeight();
+ wxBitmap bmpSource = bmp; // we need a non-const instance
+ m_buffer = new unsigned char[bw*bh*4];
+ wxUint32* data = (wxUint32*)m_buffer;
+
+ // Create a surface object and copy the bitmap pixel data to it. if the
+ // image has alpha (or a mask represented as alpha) then we'll use a
+ // different format and iterator than if it doesn't...
+ if (bmpSource.HasAlpha() || bmpSource.GetMask())
+ {
+ m_surface = cairo_image_surface_create_for_data(
+ m_buffer, CAIRO_FORMAT_ARGB32, bw, bh, bw*4);
+ wxAlphaPixelData pixData(bmpSource, wxPoint(0,0), wxSize(bw, bh));
+ wxCHECK_RET( pixData, wxT("Failed to gain raw access to bitmap data."));
+
+ wxAlphaPixelData::Iterator p(pixData);
+ for (int y=0; y<bh; y++)