- wxBitmap bitmap;
-
- wxCHECK_MSG( Ok(), bitmap, "invalid image" );
-
- int width = GetWidth();
- int height = GetHeight();
-
- bitmap.SetHeight( height );
- bitmap.SetWidth( width );
-
- Display *dpy = (Display*) wxGetDisplay();
- Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
- int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
-
- // Create image
-
- XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
- data_image->data = new char[ data_image->bytes_per_line * data_image->height ];
-
- bitmap.Create( width, height, bpp );
-
- /*
- // Create mask
-
- GdkImage *mask_image = (GdkImage*) NULL;
-
- if (HasMask())
- {
- unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
-
- mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
-
- wxMask *mask = new wxMask();
- mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
-
- bitmap.SetMask( mask );
- }
- */
-
- // Retrieve depth info
-
- XVisualInfo vinfo_template;
- XVisualInfo *vi;
-
- vinfo_template.visual = vis;
- vinfo_template.visualid = XVisualIDFromVisual( vis );
- vinfo_template.depth = bpp;
- int nitem = 0;
-
- vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
-
- if (!vi)
- {
- printf("no visual.\n" );
- return wxNullBitmap;
- }
-
- XFree( vi );
-
- if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
- if (bpp < 8) bpp = 8;
-
- // Render
-
- enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
- byte_order b_o = RGB;
-
- if (bpp >= 24)
+ return (x > 0) ? (int) (x + 0.5) : (int) (x - 0.5);
+}
+
+
+// Auxiliary function to rotate a point (x,y) with respect to point p0
+// make it inline and use a straight return to facilitate optimization
+// also, the function receives the sine and cosine of the angle to avoid
+// repeating the time-consuming calls to these functions -- sin/cos can
+// be computed and stored in the calling function.
+
+inline wxRealPoint rotated_point (const wxRealPoint & p, double cos_angle, double sin_angle, const wxRealPoint & p0)
+{
+ return wxRealPoint (p0.x + (p.x - p0.x) * cos_angle - (p.y - p0.y) * sin_angle,
+ p0.y + (p.y - p0.y) * cos_angle + (p.x - p0.x) * sin_angle);
+}
+
+inline wxRealPoint rotated_point (double x, double y, double cos_angle, double sin_angle, const wxRealPoint & p0)
+{
+ return rotated_point (wxRealPoint(x,y), cos_angle, sin_angle, p0);
+}
+
+wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool interpolating, wxPoint * offset_after_rotation) const
+{
+ int i;
+ angle = -angle; // screen coordinates are a mirror image of "real" coordinates
+
+ // Create pointer-based array to accelerate access to wxImage's data
+ unsigned char ** data = new unsigned char * [GetHeight()];
+
+ data[0] = GetData();
+
+ for (i = 1; i < GetHeight(); i++)
+ data[i] = data[i - 1] + (3 * GetWidth());
+
+ // precompute coefficients for rotation formula
+ // (sine and cosine of the angle)
+ const double cos_angle = cos(angle);
+ const double sin_angle = sin(angle);
+
+ // Create new Image to store the result
+ // First, find rectangle that covers the rotated image; to do that,
+ // rotate the four corners
+
+ const wxRealPoint p0(centre_of_rotation.x, centre_of_rotation.y);
+
+ wxRealPoint p1 = rotated_point (0, 0, cos_angle, sin_angle, p0);
+ wxRealPoint p2 = rotated_point (0, GetHeight(), cos_angle, sin_angle, p0);
+ wxRealPoint p3 = rotated_point (GetWidth(), 0, cos_angle, sin_angle, p0);
+ wxRealPoint p4 = rotated_point (GetWidth(), GetHeight(), cos_angle, sin_angle, p0);
+
+ int x1 = (int) floor (wxMin (wxMin(p1.x, p2.x), wxMin(p3.x, p4.x)));
+ int y1 = (int) floor (wxMin (wxMin(p1.y, p2.y), wxMin(p3.y, p4.y)));
+ int x2 = (int) ceil (wxMax (wxMax(p1.x, p2.x), wxMax(p3.x, p4.x)));
+ int y2 = (int) ceil (wxMax (wxMax(p1.y, p2.y), wxMax(p3.y, p4.y)));
+
+ wxImage rotated (x2 - x1 + 1, y2 - y1 + 1);
+
+ if (offset_after_rotation != NULL)