+wxRegion::wxRegion( size_t n, const wxPoint *points,
+ wxPolygonFillMode fillStyle )
+{
+#ifdef __WXGTK3__
+ // Make a cairo path from the points, draw it onto an image surface, use
+ // gdk_cairo_region_create_from_surface() to get a cairo region
+
+ // need at least 3 points to make a useful polygon
+ if (n < 3)
+ return;
+ // get bounding rect
+ int min_x = points[0].x;
+ int max_x = min_x;
+ int min_y = points[0].y;
+ int max_y = min_y;
+ size_t i;
+ for (i = 1; i < n; i++)
+ {
+ const int x = points[i].x;
+ if (min_x > x)
+ min_x = x;
+ else if (max_x < x)
+ max_x = x;
+ const int y = points[i].y;
+ if (min_y > y)
+ min_y = y;
+ else if (max_y < y)
+ max_y = y;
+ }
+ const int w = max_x - min_x + 1;
+ const int h = max_y - min_y + 1;
+ // make surface just big enough to contain polygon (A1 is native format
+ // for gdk_cairo_region_create_from_surface)
+ cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_A1, w, h);
+ memset(cairo_image_surface_get_data(surface), 0, cairo_image_surface_get_stride(surface) * h);
+ cairo_surface_mark_dirty(surface);
+ cairo_surface_set_device_offset(surface, -min_x, -min_y);
+ cairo_t* cr = cairo_create(surface);
+ cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
+ if (fillStyle == wxODDEVEN_RULE)
+ cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
+ // make path
+ cairo_move_to(cr, points[0].x, points[0].y);
+ for (i = 1; i < n; i++)
+ cairo_line_to(cr, points[i].x, points[i].y);
+ cairo_close_path(cr);
+ cairo_fill(cr);
+ cairo_destroy(cr);
+ cairo_surface_flush(surface);
+ m_refData = new wxRegionRefData;
+ M_REGIONDATA->m_region = gdk_cairo_region_create_from_surface(surface);
+ cairo_surface_destroy(surface);
+#else
+ GdkPoint *gdkpoints = new GdkPoint[n];
+ for ( size_t i = 0 ; i < n ; i++ )
+ {
+ gdkpoints[i].x = points[i].x;
+ gdkpoints[i].y = points[i].y;
+ }