#import "jwxyz-timers.h"
#import "yarandom.h"
+#ifdef USE_IPHONE
+# define USE_BACKBUFFER /* must be in sync with XScreenSaverView.h */
+#endif
+
#undef Assert
#define Assert(C,S) do { if (!(C)) jwxyz_abort ("%s",(S)); } while(0)
void *
jwxyz_window_view (Window w)
{
- Assert (w->type == WINDOW, "not a window");
+ Assert (w && w->type == WINDOW, "not a window");
return w->window.view;
}
void *cgc_arg)
{
CGContextRef cgc = (CGContextRef) cgc_arg;
- Assert (w->type == WINDOW, "not a window");
+ Assert (w && w->type == WINDOW, "not a window");
w->frame.origin.x = new_x;
w->frame.origin.y = new_y;
w->frame.size.width = new_width;
void
jwxyz_mouse_moved (Display *dpy, Window w, int x, int y)
{
- Assert (w->type == WINDOW, "not a window");
+ Assert (w && w->type == WINDOW, "not a window");
w->window.last_mouse_x = x;
w->window.last_mouse_y = y;
}
*/
#define XDRAWPOINTS_IMAGES
+/* Update, 2012: Kurt Revis <krevis@snoize.com> points out that diddling
+ the bitmap data directly is faster. This only works on Pixmaps, though,
+ not Windows. (Fortunately, on iOS, the Window is really a Pixmap.)
+ */
+#define XDRAWPOINTS_CGDATA
+
int
XDrawPoints (Display *dpy, Drawable d, GC gc,
XPoint *points, int count, int mode)
push_fg_gc (d, gc, YES);
-# ifdef XDRAWPOINTS_IMAGES
+# ifdef XDRAWPOINTS_CGDATA
+
+# ifdef USE_BACKBUFFER
+ if (1) // Because of the backbuffer, all iPhone Windows work like Pixmaps.
+# else
+ if (d->type == PIXMAP)
+# endif
+ {
+ CGContextRef cgc = d->cgc;
+ void *data = CGBitmapContextGetData (cgc);
+ size_t bpr = CGBitmapContextGetBytesPerRow (cgc);
+ size_t w = CGBitmapContextGetWidth (cgc);
+ size_t h = CGBitmapContextGetHeight (cgc);
- unsigned int argb = gc->gcv.foreground;
- validate_pixel (argb, gc->depth, gc->gcv.alpha_allowed_p);
- if (gc->depth == 1)
- argb = (gc->gcv.foreground ? WhitePixel(0,0) : BlackPixel(0,0));
-
- CGDataProviderRef prov = CGDataProviderCreateWithData (NULL, &argb, 4, NULL);
- CGImageRef cgi = CGImageCreate (1, 1,
- 8, 32, 4,
- dpy->colorspace,
- /* Host-ordered, since we're using the
- address of an int as the color data. */
- (kCGImageAlphaNoneSkipFirst |
- kCGBitmapByteOrder32Host),
- prov,
- NULL, /* decode[] */
- NO, /* interpolate */
- kCGRenderingIntentDefault);
- CGDataProviderRelease (prov);
+ Assert (data, "no bitmap data in Drawable");
- CGContextRef cgc = d->cgc;
- CGRect rect;
- rect.size.width = rect.size.height = 1;
- for (i = 0; i < count; i++) {
- if (i > 0 && mode == CoordModePrevious) {
- rect.origin.x += points->x;
- rect.origin.x -= points->y;
+ unsigned int argb = gc->gcv.foreground;
+ validate_pixel (argb, gc->depth, gc->gcv.alpha_allowed_p);
+ if (gc->depth == 1)
+ argb = (gc->gcv.foreground ? WhitePixel(0,0) : BlackPixel(0,0));
+
+ CGFloat x0 = wr.origin.x;
+ CGFloat y0 = wr.origin.y + wr.size.height;
+
+ // It's uglier, but faster, to hoist the conditional out of the loop.
+ if (mode == CoordModePrevious) {
+ CGFloat x = x0, y = y0;
+ for (i = 0; i < count; i++, points++) {
+ x += points->x;
+ y -= points->y;
+
+ if (0 <= x && x < w && 0 <= y && y < h) {
+ unsigned int *p = (unsigned int *)
+ ((char *) data + (size_t) y * bpr + (size_t) x * 4);
+ *p = argb;
+ }
+ }
} else {
- rect.origin.x = wr.origin.x + points->x;
- rect.origin.y = wr.origin.y + wr.size.height - points->y - 1;
+ for (i = 0; i < count; i++, points++) {
+ CGFloat x = x0 + points->x;
+ CGFloat y = y0 - points->y;
+
+ if (0 <= x && x < w && 0 <= y && y < h) {
+ unsigned int *p = (unsigned int *)
+ ((char *) data + (size_t) y * bpr + (size_t) x * 4);
+ *p = argb;
+ }
+ }
}
- //Assert (CGImageGetColorSpace (cgi) == dpy->colorspace, "bad colorspace");
- CGContextDrawImage (cgc, rect, cgi);
- points++;
- }
+ } else /* d->type == WINDOW */
+
+# endif /* XDRAWPOINTS_CGDATA */
+ {
+
+# ifdef XDRAWPOINTS_IMAGES
+
+ unsigned int argb = gc->gcv.foreground;
+ validate_pixel (argb, gc->depth, gc->gcv.alpha_allowed_p);
+ if (gc->depth == 1)
+ argb = (gc->gcv.foreground ? WhitePixel(0,0) : BlackPixel(0,0));
+
+ CGDataProviderRef prov = CGDataProviderCreateWithData (NULL, &argb, 4,
+ NULL);
+ CGImageRef cgi = CGImageCreate (1, 1,
+ 8, 32, 4,
+ dpy->colorspace,
+ /* Host-ordered, since we're using the
+ address of an int as the color data. */
+ (kCGImageAlphaNoneSkipFirst |
+ kCGBitmapByteOrder32Host),
+ prov,
+ NULL, /* decode[] */
+ NO, /* interpolate */
+ kCGRenderingIntentDefault);
+ CGDataProviderRelease (prov);
- CGImageRelease (cgi);
+ CGContextRef cgc = d->cgc;
+ CGRect rect;
+ rect.size.width = rect.size.height = 1;
+ for (i = 0; i < count; i++) {
+ if (i > 0 && mode == CoordModePrevious) {
+ rect.origin.x += points->x;
+ rect.origin.x -= points->y;
+ } else {
+ rect.origin.x = wr.origin.x + points->x;
+ rect.origin.y = wr.origin.y + wr.size.height - points->y - 1;
+ }
+
+ //Assert(CGImageGetColorSpace (cgi) == dpy->colorspace,"bad colorspace");
+ CGContextDrawImage (cgc, rect, cgi);
+ points++;
+ }
+
+ CGImageRelease (cgi);
# else /* ! XDRAWPOINTS_IMAGES */
- CGRect *rects = (CGRect *) malloc (count * sizeof(CGRect));
- CGRect *r = rects;
+ CGRect *rects = (CGRect *) malloc (count * sizeof(CGRect));
+ CGRect *r = rects;
- for (i = 0; i < count; i++) {
- r->size.width = r->size.height = 1;
- if (i > 0 && mode == CoordModePrevious) {
- r->origin.x = r[-1].origin.x + points->x;
- r->origin.y = r[-1].origin.x - points->y;
- } else {
- r->origin.x = wr.origin.x + points->x;
- r->origin.y = wr.origin.y + wr.size.height - points->y;
+ for (i = 0; i < count; i++) {
+ r->size.width = r->size.height = 1;
+ if (i > 0 && mode == CoordModePrevious) {
+ r->origin.x = r[-1].origin.x + points->x;
+ r->origin.y = r[-1].origin.x - points->y;
+ } else {
+ r->origin.x = wr.origin.x + points->x;
+ r->origin.y = wr.origin.y + wr.size.height - points->y;
+ }
+ points++;
+ r++;
}
- points++;
- r++;
- }
- CGContextFillRects (d->cgc, rects, count);
- free (rects);
+ CGContextFillRects (d->cgc, rects, count);
+ free (rects);
# endif /* ! XDRAWPOINTS_IMAGES */
+ }
pop_gc (d, gc);
invalidate_drawable_cache (d);
BOOL free_cgi_p = NO;
-#ifndef USE_IPHONE
+#ifndef USE_BACKBUFFER
// Because of the backbuffer, all iPhone Windows work like Pixmaps.
if (src->type == PIXMAP)
# endif
if (src->type == PIXMAP && src->pixmap.depth == 1)
mask_p = YES;
-# ifndef USE_IPHONE
+# ifndef USE_BACKBUFFER
} else { /* (src->type == WINDOW) */
NSRect nsfrom; // NSRect != CGRect on 10.4
CGDataProviderRelease (prov);
}
-# endif // !USE_IPHONE
+# endif // !USE_BACKBUFFER
}
CGContextRef cgc = dst->cgc;
} else {
// No cgi means src == dst, and both are Windows.
-# ifdef USE_IPHONE
+# ifdef USE_BACKBUFFER
Assert (0, "NSCopyBits unimplemented"); // shouldn't be reached anyway
return 0;
-# else // !USE_IPHONE
+# else // !USE_BACKBUFFER
NSRect nsfrom;
nsfrom.origin.x = src_rect.origin.x; // NSRect != CGRect on 10.4
nsfrom.origin.y = src_rect.origin.y;
nsto.x = dst_rect.origin.x;
nsto.y = dst_rect.origin.y;
NSCopyBits (0, nsfrom, nsto);
-# endif // !USE_IPHONE
+# endif // !USE_BACKBUFFER
}
pop_gc (dst, gc);
int
XClearWindow (Display *dpy, Window win)
{
- Assert (win->type == WINDOW, "not a window");
+ Assert (win && win->type == WINDOW, "not a window");
CGRect wr = win->frame;
return XClearArea (dpy, win, 0, 0, wr.size.width, wr.size.height, 0);
}
int
XSetWindowBackground (Display *dpy, Window w, unsigned long pixel)
{
- Assert (w->type == WINDOW, "not a window");
+ Assert (w && w->type == WINDOW, "not a window");
validate_pixel (pixel, 32, NO);
w->window.background = pixel;
return 0;
int
XClearArea (Display *dpy, Window win, int x, int y, int w, int h, Bool exp)
{
- Assert (win->type == WINDOW, "not a window");
+ Assert (win && win->type == WINDOW, "not a window");
CGContextRef cgc = win->cgc;
set_color (cgc, win->window.background, 32, NO, YES);
draw_rect (dpy, win, 0, x, y, w, h, NO, YES);
Status
XGetWindowAttributes (Display *dpy, Window w, XWindowAttributes *xgwa)
{
- Assert (w->type == WINDOW, "not a window");
+ Assert (w && w->type == WINDOW, "not a window");
memset (xgwa, 0, sizeof(*xgwa));
xgwa->x = w->frame.origin.x;
xgwa->y = w->frame.origin.y;
{
const unsigned char *data = 0;
int depth, ibpp, ibpl, alpha_first_p;
-# ifndef USE_IPHONE
+# ifndef USE_BACKBUFFER
NSBitmapImageRep *bm = 0;
# endif
CGContextRef cgc = d->cgc;
-#ifndef USE_IPHONE
+#ifndef USE_BACKBUFFER
// Because of the backbuffer, all iPhone Windows work like Pixmaps.
if (d->type == PIXMAP)
# endif
data = CGBitmapContextGetData (cgc);
Assert (data, "CGBitmapContextGetData failed");
-# ifndef USE_IPHONE
+# ifndef USE_BACKBUFFER
} else { /* (d->type == WINDOW) */
// get the bits (desired sub-rectangle) out of the NSView
ibpl = [bm bytesPerRow];
data = [bm bitmapData];
Assert (data, "NSBitmapImageRep initWithFocusedViewRect failed");
-# endif // !USE_IPHONE
+# endif // !USE_BACKBUFFER
}
// data points at (x,y) with ibpl rowstride. ignore x,y from now on.
}
}
-# ifndef USE_IPHONE
+# ifndef USE_BACKBUFFER
if (bm) [bm release];
# endif
int
XFreePixmap (Display *d, Pixmap p)
{
- Assert (p->type == PIXMAP, "not a pixmap");
+ Assert (p && p->type == PIXMAP, "not a pixmap");
invalidate_drawable_cache (p);
CGContextRelease (p->cgc);
if (p->pixmap.cgc_buffer)
int *root_x_ret, int *root_y_ret,
int *win_x_ret, int *win_y_ret, unsigned int *mask_ret)
{
- Assert (w->type == WINDOW, "not a window");
+ Assert (w && w->type == WINDOW, "not a window");
# ifdef USE_IPHONE
int x = w->window.last_mouse_x;
int *dest_x_ret, int *dest_y_ret,
Window *child_ret)
{
- Assert (w->type == WINDOW, "not a window");
+ Assert (w && w->type == WINDOW, "not a window");
# ifdef USE_IPHONE