+#if wxUSE_IMAGE
+// ----------------------------------------------------------------------------
+// wxCairoImageContext: context associated with a wxImage.
+// ----------------------------------------------------------------------------
+
+class wxCairoImageContext : public wxCairoContext
+{
+public:
+ wxCairoImageContext(wxGraphicsRenderer* renderer, wxImage& image) :
+ wxCairoContext(renderer),
+ m_image(image),
+ m_data(renderer, image)
+ {
+ Init(cairo_create(m_data.GetCairoSurface()));
+ }
+
+ virtual ~wxCairoImageContext()
+ {
+ m_image = m_data.ConvertToImage();
+ }
+
+private:
+ wxImage& m_image;
+ wxCairoBitmapData m_data;
+
+ wxDECLARE_NO_COPY_CLASS(wxCairoImageContext);
+};
+#endif // wxUSE_IMAGE
+
+// ----------------------------------------------------------------------------
+// wxCairoPenBrushBaseData implementation
+//-----------------------------------------------------------------------------
+
+wxCairoPenBrushBaseData::wxCairoPenBrushBaseData(wxGraphicsRenderer* renderer,
+ const wxColour& col,
+ bool isTransparent)
+ : wxGraphicsObjectRefData(renderer)
+{
+ m_hatchStyle = wxHATCHSTYLE_INVALID;
+ m_pattern = NULL;
+ m_bmpdata = NULL;
+
+ if ( isTransparent )
+ {
+ m_red =
+ m_green =
+ m_blue =
+ m_alpha = 0;
+ }
+ else // non-transparent
+ {
+ m_red = col.Red()/255.0;
+ m_green = col.Green()/255.0;
+ m_blue = col.Blue()/255.0;
+ m_alpha = col.Alpha()/255.0;
+ }
+}
+
+wxCairoPenBrushBaseData::~wxCairoPenBrushBaseData()
+{
+ if (m_bmpdata)
+ {
+ // Deleting the bitmap data also deletes the pattern referenced by
+ // m_pattern, so set it to NULL to avoid deleting it twice.
+ delete m_bmpdata;
+ m_pattern = NULL;
+ }
+ if (m_pattern)
+ cairo_pattern_destroy(m_pattern);
+}
+
+void wxCairoPenBrushBaseData::InitHatchPattern(cairo_t* ctext)
+{
+ cairo_surface_t* const
+ surface = cairo_surface_create_similar(
+ cairo_get_target(ctext), CAIRO_CONTENT_COLOR_ALPHA, 10, 10
+ );
+
+ cairo_t* const cr = cairo_create(surface);
+ cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
+ cairo_set_line_width(cr, 1);
+ cairo_set_line_join(cr,CAIRO_LINE_JOIN_MITER);
+
+ switch ( m_hatchStyle )
+ {
+ case wxHATCHSTYLE_CROSS:
+ cairo_move_to(cr, 5, 0);
+ cairo_line_to(cr, 5, 10);
+ cairo_move_to(cr, 0, 5);
+ cairo_line_to(cr, 10, 5);
+ break;
+
+ case wxHATCHSTYLE_BDIAGONAL:
+ cairo_move_to(cr, 0, 10);
+ cairo_line_to(cr, 10, 0);
+ break;
+
+ case wxHATCHSTYLE_FDIAGONAL:
+ cairo_move_to(cr, 0, 0);
+ cairo_line_to(cr, 10, 10);
+ break;
+
+ case wxHATCHSTYLE_CROSSDIAG:
+ cairo_move_to(cr, 0, 0);
+ cairo_line_to(cr, 10, 10);
+ cairo_move_to(cr, 10, 0);
+ cairo_line_to(cr, 0, 10);
+ break;
+
+ case wxHATCHSTYLE_HORIZONTAL:
+ cairo_move_to(cr, 0, 5);
+ cairo_line_to(cr, 10, 5);
+ break;
+
+ case wxHATCHSTYLE_VERTICAL:
+ cairo_move_to(cr, 5, 0);
+ cairo_line_to(cr, 5, 10);
+ break;
+
+ default:
+ wxFAIL_MSG(wxS("Invalid hatch pattern style."));
+ }
+
+ cairo_set_source_rgba(cr, m_red, m_green, m_blue, m_alpha);
+ cairo_stroke(cr);
+
+ cairo_destroy(cr);
+
+ m_pattern = cairo_pattern_create_for_surface(surface);
+ cairo_surface_destroy(surface);
+ cairo_pattern_set_extend(m_pattern, CAIRO_EXTEND_REPEAT);
+}
+
+void wxCairoPenBrushBaseData::InitStipple(wxBitmap* bmp)
+{
+ wxCHECK_RET( bmp && bmp->IsOk(), wxS("Invalid stippled bitmap") );
+
+ m_bmpdata = new wxCairoBitmapData(GetRenderer(), *bmp);
+ m_pattern = m_bmpdata->GetCairoPattern();
+ cairo_pattern_set_extend(m_pattern, CAIRO_EXTEND_REPEAT);
+}
+
+void wxCairoPenBrushBaseData::InitHatch(wxHatchStyle hatchStyle)
+{
+ // We can't create m_pattern right now as we don't have the Cairo context
+ // needed for it, so just remember that we need to do it.
+ m_hatchStyle = hatchStyle;
+}
+
+void wxCairoPenBrushBaseData::Apply( wxGraphicsContext* context )
+{
+ cairo_t* const ctext = (cairo_t*) context->GetNativeContext();
+
+ if ( m_hatchStyle != wxHATCHSTYLE_INVALID && !m_pattern )
+ InitHatchPattern(ctext);
+
+ if ( m_pattern )
+ cairo_set_source(ctext, m_pattern);
+ else
+ cairo_set_source_rgba(ctext, m_red, m_green, m_blue, m_alpha);
+}
+