-/* xscreensaver, Copyright (c) 1991-2016 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1991-2017 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
#include "yarandom.h"
#include "utf8wc.h"
#include "xft.h"
+#include "pow2.h"
#if defined HAVE_COCOA
# include <CoreGraphics/CGGeometry.h>
struct jwxyz_Display {
Window main_window;
Screen *screen;
- int screen_count;
struct jwxyz_sources_data *timers_data;
Bool gl_texture_npot_p;
GLenum pixel_format, pixel_type;
unsigned long black, white;
Visual *visual;
- int screen_number;
};
struct jwxyz_GC {
// CGImageRef clip_mask; // CGImage copy of the Pixmap in gcv.clip_mask
};
-struct jwxyz_Font {
- Display *dpy;
- char *ps_name;
- void *native_font;
- int refcount; // for deciding when to release the native font
- float size; // points
- int ascent, descent;
- char *xa_font;
-
- // In X11, "Font" is just an ID, and "XFontStruct" contains the metrics.
- // But we need the metrics on both of them, so they go here.
- XFontStruct metrics;
-};
-
struct jwxyz_XFontSet {
XFontStruct *font;
};
+struct jwxyz_linked_point {
+ short x, y;
+ linked_point *next;
+};
/* XGetImage in CoreGraphics JWXYZ has to deal with funky pixel formats
necessitating fast & flexible pixel conversion. OpenGL does image format
jwxyz_set_matrices (Display *dpy, unsigned width, unsigned height,
Bool window_p)
{
+ Assert (width, "no width");
+ Assert (height, "no height");
+
/* TODO: Check registration pattern from Interference with rectangles instead of points. */
// The projection matrix is always set as follows. The modelview matrix is
// NSOpenGLContext *jwxyz_debug_context;
-/* We keep a list of all of the Displays that have been created and not
- yet freed so that they can have sensible display numbers. If three
- displays are created (0, 1, 2) and then #1 is closed, then the fourth
- display will be given the now-unused display number 1. (Everything in
- here assumes a 1:1 Display/Screen mapping.)
-
- The size of this array is the most number of live displays at one time.
- So if it's 20, then we'll blow up if the system has 19 monitors and also
- has System Preferences open (the small preview window).
-
- Note that xlockmore-style savers tend to allocate big structures, so
- setting this to 1000 will waste a few megabytes. Also some of them assume
- that the number of screens never changes, so dynamically expanding this
- array won't work.
- */
-# ifndef USE_IPHONE
-static Display *jwxyz_live_displays[20] = { 0, };
-# endif
-
Display *
jwxyz_make_display (Window w)
Display *d = (Display *) calloc (1, sizeof(*d));
d->screen = (Screen *) calloc (1, sizeof(Screen));
d->screen->dpy = d;
-
- d->screen_count = 1;
- d->screen->screen_number = 0;
-# ifndef USE_IPHONE
- {
- // Find the first empty slot in live_displays and plug us in.
- int size = sizeof(jwxyz_live_displays) / sizeof(*jwxyz_live_displays);
- int i;
- for (i = 0; i < size; i++) {
- if (! jwxyz_live_displays[i])
- break;
- }
- if (i >= size) abort();
- jwxyz_live_displays[i] = d;
- d->screen_count = size;
- d->screen->screen_number = i;
- }
-# endif // !USE_IPHONE
# ifndef HAVE_JWZGLES
struct gl_version version;
v->red_mask = jwxyz_alloc_color (d, 0xFFFF, 0x0000, 0x0000, 0x0000);
v->green_mask = jwxyz_alloc_color (d, 0x0000, 0xFFFF, 0x0000, 0x0000);
v->blue_mask = jwxyz_alloc_color (d, 0x0000, 0x0000, 0xFFFF, 0x0000);
- v->bits_per_rgb = 8;
d->screen->visual = v;
d->timers_data = jwxyz_sources_init (XtDisplayToApplicationContext (d));
jwxyz_sources_free (dpy->timers_data);
-# ifndef USE_IPHONE
- {
- // Find us in live_displays and clear that slot.
- int size = ScreenCount(dpy);
- int i;
- for (i = 0; i < size; i++) {
- if (dpy == jwxyz_live_displays[i]) {
- jwxyz_live_displays[i] = 0;
- break;
- }
- }
- if (i >= size) abort();
- }
-# endif // !USE_IPHONE
-
free (dpy->screen->visual);
free (dpy->screen);
free (dpy);
int
XScreenNumberOfScreen (Screen *s)
{
- return s? s->screen_number : 0;
-}
-
-int
-jwxyz_ScreenCount (Display *dpy)
-{
- return dpy ? dpy->screen_count : 0;
+ return 0;
}
unsigned long
}
-static GLsizei to_pow2 (size_t x);
-
-
void
-jwxyz_gl_copy_area_copy_tex_image (Display *dpy, Drawable src, Drawable dst,
- GC gc, int src_x, int src_y,
+jwxyz_gl_copy_area_read_tex_image (Display *dpy, unsigned src_height,
+ int src_x, int src_y,
unsigned int width, unsigned int height,
int dst_x, int dst_y)
{
- const XRectangle *src_frame = jwxyz_frame (src);
-
- Assert(gc->gcv.function == GXcopy, "XCopyArea: Unknown function");
-
- jwxyz_bind_drawable (dpy, dpy->main_window, src);
-
# if defined HAVE_COCOA && !defined USE_IPHONE
/* TODO: Does this help? */
/* glFinish(); */
# endif
+ /* TODO: Fix TestX11 + mode_preserve with this one. */
+
unsigned tex_w = width, tex_h = height;
if (!dpy->gl_texture_npot_p) {
tex_w = to_pow2(tex_w);
if (tex_w == width && tex_h == height) {
glCopyTexImage2D (dpy->gl_texture_target, 0, internalformat,
- src_x, src_frame->height - src_y - height,
- width, height, 0);
+ src_x, src_height - src_y - height, width, height, 0);
} else {
glTexImage2D (dpy->gl_texture_target, 0, internalformat, tex_w, tex_h,
0, dpy->screen->pixel_format, gl_pixel_type(dpy), NULL);
glCopyTexSubImage2D (dpy->gl_texture_target, 0, 0, 0,
- src_x, src_frame->height - src_y - height,
- width, height);
+ src_x, src_height - src_y - height, width, height);
+ }
+}
+
+void
+jwxyz_gl_copy_area_write_tex_image (Display *dpy, GC gc, int src_x, int src_y,
+ unsigned int width, unsigned int height,
+ int dst_x, int dst_y)
+{
+ Assert(gc->gcv.function == GXcopy, "XCopyArea: Unknown function");
+
+ /* TODO: Copy-pasted from read_tex_image. */
+ unsigned tex_w = width, tex_h = height;
+ if (!dpy->gl_texture_npot_p) {
+ tex_w = to_pow2(tex_w);
+ tex_h = to_pow2(tex_h);
}
- jwxyz_bind_drawable (dpy, dpy->main_window, dst);
- set_white ();
glBindTexture (dpy->gl_texture_target, dpy->rect_texture);
- glEnable (dpy->gl_texture_target);
+
+ jwxyz_gl_draw_image (dpy->gl_texture_target, tex_w, tex_h, 0, 0,
+ width, height, dst_x, dst_y);
+
+ clear_texture (dpy);
+}
+
+
+void
+jwxyz_gl_draw_image (GLenum gl_texture_target,
+ unsigned int tex_w, unsigned int tex_h,
+ int src_x, int src_y,
+ unsigned int width, unsigned int height,
+ int dst_x, int dst_y)
+{
+ set_white ();
+ glEnable (gl_texture_target);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
glEnableClientState (GL_VERTEX_ARRAY);
{dst_x + width, dst_y + height},
{dst_x + width, dst_y}
};
-
-#ifdef HAVE_JWZGLES
- static const GLshort tex_coords[4][2] = {{0, 1}, {0, 0}, {1, 0}, {1, 1}};
-#else
- GLshort tex_coords[4][2] = {{0, height}, {0, 0}, {width, 0}, {width, height}};
-#endif
+
+ GLfloat
+ tex_x0 = src_x, tex_y0 = src_y + height,
+ tex_x1 = src_x + width, tex_y1 = src_y;
+
+# ifndef HAVE_JWZGLES
+ if (gl_texture_target != GL_TEXTURE_RECTANGLE_EXT)
+# endif
+ {
+ GLfloat mx = 1.0f / tex_w, my = 1.0f / tex_h;
+ tex_x0 *= mx;
+ tex_y0 *= my;
+ tex_x1 *= mx;
+ tex_y1 *= my;
+ }
+
+ GLfloat tex_coords[4][2] =
+ {
+ {tex_x0, tex_y0},
+ {tex_x0, tex_y1},
+ {tex_x1, tex_y1},
+ {tex_x1, tex_y0}
+ };
glVertexPointer (2, GL_FLOAT, 0, vertices);
- glTexCoordPointer (2, GL_SHORT, 0, tex_coords);
+ glTexCoordPointer (2, GL_FLOAT, 0, tex_coords);
glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
-
- clear_texture (dpy);
-
- glDisable (dpy->gl_texture_target);
+
+ glDisable (gl_texture_target);
}
void
unsigned int width, unsigned int height,
int dst_x, int dst_y)
{
-# if 1
XImage *img = XGetImage (dpy, src, src_x, src_y, width, height, ~0, ZPixmap);
XPutImage (dpy, dst, gc, img, 0, 0, dst_x, dst_y, width, height);
XDestroyImage (img);
-# endif
-
-# if 0
- /* Something may or may not be broken in here. (shrug) */
- bind_drawable(dpy, src);
-
- /* Error checking would be nice. */
- void *pixels = malloc (src_rect.size.width * 4 * src_rect.size.height);
-
- glPixelStorei (GL_PACK_ROW_LENGTH, 0);
- glPixelStorei (GL_PACK_ALIGNMENT, 4);
-
- glReadPixels (src_rect.origin.x, dst_frame.size.height - (src_rect.origin.y + src_rect.size.height),
- src_rect.size.width, src_rect.size.height,
- GL_RGBA, GL_UNSIGNED_BYTE, // TODO: Pick better formats.
- pixels);
-
- bind_drawable (dpy, dst);
-
- glPixelZoom (1.0f, 1.0f);
-
- glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
- glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
-
- glRasterPos2i (dst_rect.origin.x, dst_rect.origin.y + dst_rect.size.height);
- glDrawPixels (dst_rect.size.width, dst_rect.size.height,
- GL_RGBA, GL_UNSIGNED_BYTE, pixels);
-
- free(pixels);
-# endif
}
/* Complex: Pedal, and for some reason Attraction, Mountain, Qix, SpeedMine, Starfish
* Nonconvex: Goop, Pacman, Rocks, Speedmine
+ *
+ * We currently do Nonconvex with the simple-to-implement ear clipping
+ * algorithm, but in the future we can replace that with an algorithm
+ * with slower big-O growth
+ *
*/
- Assert(shape == Convex, "XFillPolygon: (TODO) Unimplemented shape");
// TODO: Feed vertices straight to OpenGL for CoordModeOrigin.
+
+ if (shape == Convex) {
+
GLshort *vertices = malloc(npoints * sizeof(GLshort) * 2); // TODO: Oh look, another unchecked malloc.
short v[2] = {0, 0};
free(vertices);
- /*
- CGRect wr = d->frame;
- int i;
- push_fg_gc (dpy, d, gc, YES);
- CGContextRef cgc = d->cgc;
- CGContextBeginPath (cgc);
- float x = 0, y = 0;
- for (i = 0; i < npoints; i++) {
- if (i > 0 && mode == CoordModePrevious) {
- x += points[i].x;
- y -= points[i].y;
- } else {
- x = wr.origin.x + points[i].x;
- y = wr.origin.y + wr.size.height - points[i].y;
- }
-
- if (i == 0)
- CGContextMoveToPoint (cgc, x, y);
- else
- CGContextAddLineToPoint (cgc, x, y);
+ } else if (shape == Nonconvex) {
+
+ // TODO: assert that x,y of first and last point match, as that is assumed
+
+ linked_point *root;
+ root = (linked_point *) malloc( sizeof(linked_point) );
+ set_points_list(points,npoints,root);
+ traverse_points_list(root);
+
+ } else {
+ Assert((shape == Convex || shape == Nonconvex), "XFillPolygon: (TODO) Unimplemented shape");
}
- CGContextClosePath (cgc);
- if (gc->gcv.fill_rule == EvenOddRule)
- CGContextEOFillPath (cgc);
- else
- CGContextFillPath (cgc);
- pop_gc (d, gc);
- invalidate_drawable_cache (d);
- */
+
+
return 0;
}
}
*/
-// Copied and pasted from OSX/XScreenSaverView.m
-static GLsizei
-to_pow2 (size_t x)
-{
- if (x <= 1)
- return 1;
-
- size_t mask = (size_t)-1;
- unsigned bits = sizeof(x) * CHAR_BIT;
- unsigned log2 = bits;
-
- --x;
- while (bits) {
- if (!(x & mask)) {
- log2 -= bits;
- x <<= bits;
- }
-
- bits >>= 1;
- mask <<= bits;
- }
-
- return 1 << log2;
-}
-
int
XPutImage (Display *dpy, Drawable d, GC gc, XImage *ximage,
return 0;
}
-/* At the moment nothing actually uses XGetSubImage. */
-/* #### Actually lots of things call XGetImage, which calls XGetSubImage.
- E.g., Twang calls XGetImage on the window intending to get a
+/* At the moment only XGetImage and get_xshm_image use XGetSubImage. */
+/* #### Twang calls XGetImage on the window intending to get a
buffer full of black. This is returning a buffer full of white
instead of black for some reason. */
-static XImage *
+XImage *
XGetSubImage (Display *dpy, Drawable d, int x, int y,
unsigned int width, unsigned int height,
unsigned long plane_mask, int format,
return dest_image;
}
-XImage *
-XGetImage (Display *dpy, Drawable d, int x, int y,
- unsigned int width, unsigned int height,
- unsigned long plane_mask, int format)
-{
- unsigned depth = jwxyz_drawable_depth (d);
- XImage *image = XCreateImage (dpy, 0, depth, format, 0, 0, width, height,
- 0, 0);
- image->data = (char *) malloc (height * image->bytes_per_line);
-
- return XGetSubImage (dpy, d, x, y, width, height, plane_mask, format,
- image, 0, 0);
-}
/* Returns a transformation matrix to do rotation as per the provided
EXIF "Orientation" value.
#endif
-// This is XQueryFont, but for the XFontStruct embedded in 'Font'
-//
-static void
-query_font (Font fid)
-{
- if (!fid || !fid->native_font) {
- Assert (0, "no native font in fid");
- return;
- }
-
- int first = 32;
- int last = 255;
-
- Display *dpy = fid->dpy;
- void *native_font = fid->native_font;
-
- XFontStruct *f = &fid->metrics;
- XCharStruct *min = &f->min_bounds;
- XCharStruct *max = &f->max_bounds;
-
- f->fid = fid;
- f->min_char_or_byte2 = first;
- f->max_char_or_byte2 = last;
- f->default_char = 'M';
- f->ascent = fid->ascent;
- f->descent = fid->descent;
-
- min->width = 32767; // set to smaller values in the loop
- min->ascent = 32767;
- min->descent = 32767;
- min->lbearing = 32767;
- min->rbearing = 32767;
-
- f->per_char = (XCharStruct *) calloc (last-first+2, sizeof (XCharStruct));
-
- for (int i = first; i <= last; i++) {
- XCharStruct *cs = &f->per_char[i-first];
- char s = (char) i;
- jwxyz_render_text (dpy, native_font, &s, 1, GL_FALSE, cs, 0);
-
- max->width = MAX (max->width, cs->width);
- max->ascent = MAX (max->ascent, cs->ascent);
- max->descent = MAX (max->descent, cs->descent);
- max->lbearing = MAX (max->lbearing, cs->lbearing);
- max->rbearing = MAX (max->rbearing, cs->rbearing);
-
- min->width = MIN (min->width, cs->width);
- min->ascent = MIN (min->ascent, cs->ascent);
- min->descent = MIN (min->descent, cs->descent);
- min->lbearing = MIN (min->lbearing, cs->lbearing);
- min->rbearing = MIN (min->rbearing, cs->rbearing);
-/*
- Log (" %3d %c: w=%3d lb=%3d rb=%3d as=%3d ds=%3d\n",
- i, i, cs->width, cs->lbearing, cs->rbearing,
- cs->ascent, cs->descent);
- */
- }
-}
-
-
-// Since 'Font' includes the metrics, this just makes a copy of that.
-//
-XFontStruct *
-XQueryFont (Display *dpy, Font fid)
-{
- // copy XFontStruct
- XFontStruct *f = (XFontStruct *) calloc (1, sizeof(*f));
- *f = fid->metrics;
- f->fid = fid;
-
- // build XFontProps
- f->n_properties = 1;
- f->properties = malloc (sizeof(*f->properties) * f->n_properties);
- f->properties[0].name = XA_FONT;
- Assert (sizeof (f->properties[0].card32) >= sizeof (char *),
- "atoms probably needs a real implementation");
- // If XInternAtom is ever implemented, use it here.
- f->properties[0].card32 = (unsigned long)(char *)fid->xa_font;
-
- // copy XCharStruct array
- int size = (f->max_char_or_byte2 - f->min_char_or_byte2) + 1;
- f->per_char = (XCharStruct *) calloc (size + 2, sizeof (XCharStruct));
-
- memcpy (f->per_char, fid->metrics.per_char,
- size * sizeof (XCharStruct));
-
- return f;
-}
-
-
-static Font
-copy_font (Font fid)
-{
- fid->refcount++;
- return fid;
-}
-
-
-#if 0
-
-
-static NSArray *
-font_family_members (NSString *family_name)
-{
-# ifndef USE_IPHONE
- return [[NSFontManager sharedFontManager]
- availableMembersOfFontFamily:family_name];
-# else
- return [UIFont fontNamesForFamilyName:family_name];
-# endif
-}
-
-
-static NSString *
-default_font_family (NSFontTraitMask require)
-{
- return require & NSFixedPitchFontMask ? @"Courier" : @"Verdana";
-}
-
-
-static NSFont *
-try_font (NSFontTraitMask traits, NSFontTraitMask mask,
- NSString *family_name, float size,
- char **name_ret)
+int
+jwxyz_draw_string (Display *dpy, Drawable d, GC gc, int x, int y,
+ const char *str, size_t len, int utf8_p)
{
- Assert (size > 0, "zero font size");
-
- NSArray *family_members = font_family_members (family_name);
- if (!family_members.count)
- family_members = font_family_members (default_font_family (traits));
+ Font ff = gc->gcv.font;
+ XCharStruct cs;
-# ifndef USE_IPHONE
- for (unsigned k = 0; k != family_members.count; ++k) {
-
- NSArray *member = [family_members objectAtIndex:k];
- NSFontTraitMask font_mask =
- [(NSNumber *)[member objectAtIndex:3] unsignedIntValue];
-
- if ((font_mask & mask) == traits) {
-
- NSString *name = [member objectAtIndex:0];
- NSFont *f = [NSFont fontWithName:name size:size];
- if (!f)
- break;
-
- /* Don't use this font if it (probably) doesn't include ASCII characters.
- */
- NSStringEncoding enc = [f mostCompatibleStringEncoding];
- if (! (enc == NSUTF8StringEncoding ||
- enc == NSISOLatin1StringEncoding ||
- enc == NSNonLossyASCIIStringEncoding ||
- enc == NSISOLatin2StringEncoding ||
- enc == NSUnicodeStringEncoding ||
- enc == NSWindowsCP1250StringEncoding ||
- enc == NSWindowsCP1252StringEncoding ||
- enc == NSMacOSRomanStringEncoding)) {
- // NSLog(@"skipping \"%@\": encoding = %d", name, enc);
- break;
- }
- // NSLog(@"using \"%@\": %d", name, enc);
+ char *data = 0;
+ jwxyz_render_text (dpy, jwxyz_native_font (ff), str, len, utf8_p, &cs, &data);
+ int w = cs.rbearing - cs.lbearing;
+ int h = cs.ascent + cs.descent;
- // *name_ret = strdup ([name cStringUsingEncoding:NSUTF8StringEncoding]);
- *name_ret = strdup (name.UTF8String);
- return f;
- }
- }
-# else // USE_IPHONE
-
- for (NSString *fn in family_members) {
-# define MATCH(X) \
- ([fn rangeOfString:X options:NSCaseInsensitiveSearch].location \
- != NSNotFound)
-
- // The magic invocation for getting font names is
- // [[UIFontDescriptor
- // fontDescriptorWithFontAttributes:@{UIFontDescriptorNameAttribute: name}]
- // symbolicTraits]
- // ...but this only works on iOS 7 and later.
- NSFontTraitMask font_mask = 0;
- if (MATCH(@"Bold"))
- font_mask |= NSBoldFontMask;
- if (MATCH(@"Italic") || MATCH(@"Oblique"))
- font_mask |= NSItalicFontMask;
-
- if ((font_mask & mask) == traits) {
-
- /* Check if it can do ASCII. No good way to accomplish this!
- These are fonts present in iPhone Simulator as of June 2012
- that don't include ASCII.
- */
- if (MATCH(@"AppleGothic") || // Korean
- MATCH(@"Dingbats") || // Dingbats
- MATCH(@"Emoji") || // Emoticons
- MATCH(@"Geeza") || // Arabic
- MATCH(@"Hebrew") || // Hebrew
- MATCH(@"HiraKaku") || // Japanese
- MATCH(@"HiraMin") || // Japanese
- MATCH(@"Kailasa") || // Tibetan
- MATCH(@"Ornaments") || // Dingbats
- MATCH(@"STHeiti") // Chinese
- )
- break;
-
- *name_ret = strdup (fn.UTF8String);
- return [UIFont fontWithName:fn size:size];
- }
-# undef MATCH
+ if (w < 0 || h < 0) abort();
+ if (w == 0 || h == 0) {
+ if (data) free(data);
+ return 0;
}
-# endif
-
- return NULL;
-}
-
-
-
-/* On Cocoa and iOS, fonts may be specified as "Georgia Bold 24" instead
- of XLFD strings; also they can be comma-separated strings with multiple
- font names. First one that exists wins.
- */
-static NSFont *
-try_native_font (const char *name, float scale,
- char **name_ret, float *size_ret, char **xa_font)
-{
- if (!name) return 0;
- const char *spc = strrchr (name, ' ');
- if (!spc) return 0;
-
- NSFont *f = 0;
- char *token = strdup (name);
- char *name2;
-
- while ((name2 = strtok (token, ","))) {
- token = 0;
-
- while (*name2 == ' ' || *name2 == '\t' || *name2 == '\n')
- name2++;
-
- spc = strrchr (name2, ' ');
- if (!spc) continue;
-
- int dsize = 0;
- if (1 != sscanf (spc, " %d ", &dsize))
- continue;
- float size = dsize;
-
- if (size <= 4) continue;
-
- size *= scale;
+ XImage *img = XCreateImage (dpy, dpy->screen->visual, 32,
+ ZPixmap, 0, data, w, h, 0, 0);
- name2[strlen(name2) - strlen(spc)] = 0;
+ /* The image of text is a 32-bit image, in white.
+ Take the red channel for intensity and use that as alpha.
+ replace RGB with the GC's foreground color.
+ This expects that XPutImage respects alpha and only writes
+ the bits that are not masked out.
+ This also assumes that XPutImage expects ARGB.
+ */
+ {
+ char *s = data;
+ char *end = s + (w * h * 4);
+ uint8_t rgba[4];
+ jwxyz_query_color (dpy, gc->gcv.foreground, rgba);
+ while (s < end) {
- NSString *nsname = [NSString stringWithCString:name2
- encoding:NSUTF8StringEncoding];
- f = [NSFont fontWithName:nsname size:size];
- if (f) {
- *name_ret = name2;
- *size_ret = size;
- *xa_font = strdup (name); // Maybe this should be an XLFD?
- break;
- } else {
- NSLog(@"No native font: \"%@\" %.0f", nsname, size);
+ s[3] = s[1];
+ s[0] = rgba[0];
+ s[1] = rgba[1];
+ s[2] = rgba[2];
+ s += 4;
}
}
- free (token);
- return f;
-}
-
-
-/* Returns a random font in the given size and face.
- */
-static NSFont *
-random_font (NSFontTraitMask traits, NSFontTraitMask mask,
- float size, NSString **family_ret, char **name_ret)
-{
-
-# ifndef USE_IPHONE
- // Providing Unbold or Unitalic in the mask for availableFontNamesWithTraits
- // returns an empty list, at least on a system with default fonts only.
- NSArray *families = [[NSFontManager sharedFontManager]
- availableFontFamilies];
- if (!families) return 0;
-# else
- NSArray *families = [UIFont familyNames];
-
- // There are many dups in the families array -- uniquify it.
{
- NSArray *sorted_families =
- [families sortedArrayUsingSelector:@selector(compare:)];
- NSMutableArray *new_families =
- [NSMutableArray arrayWithCapacity:sorted_families.count];
-
- NSString *prev_family = nil;
- for (NSString *family in sorted_families) {
- if ([family compare:prev_family])
- [new_families addObject:family];
- }
-
- families = new_families;
+ Bool old_alpha = gc->gcv.alpha_allowed_p;
+ jwxyz_XSetAlphaAllowed (dpy, gc, True);
+ XPutImage (dpy, d, gc, img, 0, 0,
+ x + cs.lbearing,
+ y - cs.ascent,
+ w, h);
+ jwxyz_XSetAlphaAllowed (dpy, gc, old_alpha);
+ XDestroyImage (img);
}
-# endif // USE_IPHONE
- long n = [families count];
- if (n <= 0) return 0;
-
- int j;
- for (j = 0; j < n; j++) {
- int i = random() % n;
- NSString *family_name = [families objectAtIndex:i];
-
- NSFont *result = try_font (traits, mask, family_name, size, name_ret);
- if (result) {
- [*family_ret release];
- *family_ret = family_name;
- [*family_ret retain];
- return result;
- }
- }
-
- // None of the fonts support ASCII?
return 0;
}
-// Fonts need this. XDisplayHeightMM and friends should probably be consistent
-// with this as well if they're ever implemented.
-static const unsigned dpi = 75;
-
-
-static const char *
-xlfd_field_end (const char *s)
-{
- const char *s2 = strchr(s, '-');
- if (!s2)
- s2 = s + strlen(s);
- return s2;
-}
-
-
-static size_t
-xlfd_next (const char **s, const char **s2)
-{
- if (!**s2) {
- *s = *s2;
- } else {
- Assert (**s2 == '-', "xlfd parse error");
- *s = *s2 + 1;
- *s2 = xlfd_field_end (*s);
- }
-
- return *s2 - *s;
-}
-
-static NSFont *
-try_xlfd_font (const char *name, float scale,
- char **name_ret, float *size_ret, char **xa_font)
-{
- NSFont *nsfont = 0;
- NSString *family_name = nil;
- NSFontTraitMask require = 0, forbid = 0;
- GLboolean rand = GL_FALSE;
- float size = 0;
- char *ps_name = 0;
-
- const char *s = (name ? name : "");
-
- size_t L = strlen (s);
-# define CMP(STR) (L == strlen(STR) && !strncasecmp (s, (STR), L))
-# define UNSPEC (L == 0 || L == 1 && *s == '*')
- if (CMP ("6x10")) size = 8, require |= NSFixedPitchFontMask;
- else if (CMP ("6x10bold")) size = 8, require |= NSFixedPitchFontMask | NSBoldFontMask;
- else if (CMP ("fixed")) size = 12, require |= NSFixedPitchFontMask;
- else if (CMP ("9x15")) size = 12, require |= NSFixedPitchFontMask;
- else if (CMP ("9x15bold")) size = 12, require |= NSFixedPitchFontMask | NSBoldFontMask;
- else if (CMP ("vga")) size = 12, require |= NSFixedPitchFontMask;
- else if (CMP ("console")) size = 12, require |= NSFixedPitchFontMask;
- else if (CMP ("gallant")) size = 12, require |= NSFixedPitchFontMask;
- else {
-
- // Incorrect fields are ignored.
-
- if (*s == '-')
- ++s;
- const char *s2 = xlfd_field_end(s);
-
- // Foundry (ignore)
-
- L = xlfd_next (&s, &s2); // Family name
- // This used to substitute Georgia for Times. Now it doesn't.
- if (CMP ("random")) {
- rand = GL_TRUE;
- } else if (CMP ("fixed")) {
- require |= NSFixedPitchFontMask;
- family_name = @"Courier";
- } else if (!UNSPEC) {
- family_name = [[[NSString alloc] initWithBytes:s
- length:L
- encoding:NSUTF8StringEncoding]
- autorelease];
- }
-
- L = xlfd_next (&s, &s2); // Weight name
- if (CMP ("bold") || CMP ("demibold"))
- require |= NSBoldFontMask;
- else if (CMP ("medium") || CMP ("regular"))
- forbid |= NSBoldFontMask;
-
- L = xlfd_next (&s, &s2); // Slant
- if (CMP ("i") || CMP ("o"))
- require |= NSItalicFontMask;
- else if (CMP ("r"))
- forbid |= NSItalicFontMask;
-
- xlfd_next (&s, &s2); // Set width name (ignore)
- xlfd_next (&s, &s2); // Add style name (ignore)
-
- xlfd_next (&s, &s2); // Pixel size (ignore)
-
- xlfd_next (&s, &s2); // Point size
- char *s3;
- uintmax_t n = strtoumax(s, &s3, 10);
- if (s2 == s3)
- size = n / 10.0;
-
- xlfd_next (&s, &s2); // Resolution X (ignore)
- xlfd_next (&s, &s2); // Resolution Y (ignore)
-
- xlfd_next (&s, &s2); // Spacing
- if (CMP ("p"))
- forbid |= NSFixedPitchFontMask;
- else if (CMP ("m") || CMP ("c"))
- require |= NSFixedPitchFontMask;
-
- // Don't care about average_width or charset registry.
- }
-# undef CMP
-# undef UNSPEC
-
- if (!family_name && !rand)
- family_name = default_font_family (require);
-
- if (size < 6 || size > 1000)
- size = 12;
-
- size *= scale;
-
- NSFontTraitMask mask = require | forbid;
-
- if (rand) {
- nsfont = random_font (require, mask, size, &family_name, &ps_name);
- [family_name autorelease];
- }
-
- if (!nsfont)
- nsfont = try_font (require, mask, family_name, size, &ps_name);
-
- // if that didn't work, turn off attibutes until it does
- // (e.g., there is no "Monaco-Bold".)
- //
- if (!nsfont && (mask & NSItalicFontMask)) {
- require &= ~NSItalicFontMask;
- mask &= ~NSItalicFontMask;
- nsfont = try_font (require, mask, family_name, size, &ps_name);
- }
- if (!nsfont && (mask & NSBoldFontMask)) {
- require &= ~NSBoldFontMask;
- mask &= ~NSBoldFontMask;
- nsfont = try_font (require, mask, family_name, size, &ps_name);
- }
- if (!nsfont && (mask & NSFixedPitchFontMask)) {
- require &= ~NSFixedPitchFontMask;
- mask &= ~NSFixedPitchFontMask;
- nsfont = try_font (require, mask, family_name, size, &ps_name);
- }
-
- if (nsfont) {
- *name_ret = ps_name;
- *size_ret = size;
- float actual_size = size / scale;
- asprintf(xa_font, "-*-%s-%s-%c-*-*-%u-%u-%u-%u-%c-0-iso10646-1",
- family_name.UTF8String,
- (require & NSBoldFontMask) ? "bold" : "medium",
- (require & NSItalicFontMask) ? 'o' : 'r',
- (unsigned)(dpi * actual_size / 72.27 + 0.5),
- (unsigned)(actual_size * 10 + 0.5), dpi, dpi,
- (require & NSFixedPitchFontMask) ? 'm' : 'p');
- return nsfont;
- } else {
- return 0;
- }
-}
-
-#endif
-
-Font
-XLoadFont (Display *dpy, const char *name)
-{
- Font fid = (Font) calloc (1, sizeof(*fid));
- fid->refcount = 1;
- fid->dpy = dpy;
-
- // (TODO) float scale = 1;
-
-# ifdef USE_IPHONE
- /* Since iOS screens are physically smaller than desktop screens, scale up
- the fonts to make them more readable.
-
- Note that X11 apps on iOS also have the backbuffer sized in points
- instead of pixels, resulting in an effective X11 screen size of 768x1024
- or so, even if the display has significantly higher resolution. That is
- unrelated to this hack, which is really about DPI.
- */
- /* scale = 2; */
-# endif
-
- fid->dpy = dpy;
- fid->native_font = jwxyz_load_native_font (dpy, name,
- &fid->ps_name, &fid->size,
- &fid->ascent, &fid->descent);
- if (!fid->native_font) {
- free (fid);
- return 0;
- }
- query_font (fid);
-
- return fid;
-}
-
-
-XFontStruct *
-XLoadQueryFont (Display *dpy, const char *name)
-{
- Font fid = XLoadFont (dpy, name);
- if (!fid) return 0;
- return XQueryFont (dpy, fid);
-}
-
int
-XUnloadFont (Display *dpy, Font fid)
+XSetClipMask (Display *dpy, GC gc, Pixmap m)
{
- if (--fid->refcount < 0) abort();
- if (fid->refcount > 0) return 0;
-
- if (fid->native_font)
- jwxyz_release_native_font (fid->dpy, fid->native_font);
-
- if (fid->ps_name)
- free (fid->ps_name);
- if (fid->metrics.per_char)
- free (fid->metrics.per_char);
-
- // #### DAMMIT! I can't tell what's going wrong here, but I keep getting
- // crashes in [NSFont ascender] <- query_font, and it seems to go away
- // if I never release the nsfont. So, fuck it, we'll just leak fonts.
- // They're probably not very big...
- //
- // [fid->nsfont release];
- // CFRelease (fid->nsfont);
+//#### abort();
+/*
+ TODO
- free (fid);
- return 0;
-}
+ Assert (!!gc->gcv.clip_mask == !!gc->clip_mask, "GC clip mask mixup");
-int
-XFreeFontInfo (char **names, XFontStruct *info, int n)
-{
- int i;
- if (names) {
- for (i = 0; i < n; i++)
- if (names[i]) free (names[i]);
- free (names);
- }
- if (info) {
- for (i = 0; i < n; i++)
- if (info[i].per_char) {
- free (info[i].per_char);
- free (info[i].properties);
- }
- free (info);
+ if (gc->gcv.clip_mask) {
+ XFreePixmap (dpy, gc->gcv.clip_mask);
+ CGImageRelease (gc->clip_mask);
}
- return 0;
-}
-int
-XFreeFont (Display *dpy, XFontStruct *f)
-{
- Font fid = f->fid;
- XFreeFontInfo (0, f, 1);
- XUnloadFont (dpy, fid);
+ gc->gcv.clip_mask = copy_pixmap (dpy, m);
+ if (gc->gcv.clip_mask)
+ gc->clip_mask =
+ CGBitmapContextCreateImage (gc->gcv.clip_mask->cgc);
+ else
+ gc->clip_mask = 0;
+*/
+
return 0;
}
-
int
-XSetFont (Display *dpy, GC gc, Font fid)
+XSetClipOrigin (Display *dpy, GC gc, int x, int y)
{
- Font font2 = copy_font (fid);
- if (gc->gcv.font)
- XUnloadFont (dpy, gc->gcv.font);
- gc->gcv.font = font2;
+ gc->gcv.clip_x_origin = x;
+ gc->gcv.clip_y_origin = y;
return 0;
}
-
-XFontSet
-XCreateFontSet (Display *dpy, char *name,
- char ***missing_charset_list_return,
- int *missing_charset_count_return,
- char **def_string_return)
+void set_points_list(XPoint *points, int npoints, linked_point *root)
{
- char *name2 = strdup (name);
- char *s = strchr (name, ',');
- if (s) *s = 0;
- XFontSet set = 0;
- XFontStruct *f = XLoadQueryFont (dpy, name2);
- if (f)
- {
- set = (XFontSet) calloc (1, sizeof(*set));
- set->font = f;
- }
- free (name2);
- if (missing_charset_list_return) *missing_charset_list_return = 0;
- if (missing_charset_count_return) *missing_charset_count_return = 0;
- if (def_string_return) *def_string_return = 0;
- return set;
-}
-
+ linked_point *current;
-void
-XFreeFontSet (Display *dpy, XFontSet set)
-{
- XFreeFont (dpy, set->font);
- free (set);
+ current = root;
+ for (int i = 0; i < npoints - 2 ; i++) {
+ current->x = points[i].x;
+ current->y = points[i].y;
+ current->next = (linked_point *) malloc(sizeof(linked_point));
+ current = current->next;
+ }
+ current->x = points[npoints-2].x;
+ current->y = points[npoints-2].y;
+ current->next = root;
}
-const char *
-jwxyz_nativeFontName (Font f, float *size)
+double compute_edge_length(linked_point * a, linked_point * b)
{
- if (size) *size = f->size;
- return f->ps_name;
-}
+ int xdiff, ydiff, xsq, ysq, added;
+ double xy_add, edge_length;
-void
-XFreeStringList (char **list)
-{
- int i;
- if (!list) return;
- for (i = 0; list[i]; i++)
- XFree (list[i]);
- XFree (list);
+ xdiff = a->x - b->x;
+ ydiff = a->y - b->y;
+ xsq = xdiff * xdiff;
+ ysq = ydiff * ydiff;
+ added = xsq + ysq;
+ xy_add = (double) added;
+ edge_length = sqrt(xy_add);
+ return edge_length;
}
-
-// Given a UTF8 string, return an NSString. Bogus UTF8 characters are ignored.
-// We have to do this because stringWithCString returns NULL if there are
-// any invalid characters at all.
-//
-/* TODO
-static NSString *
-sanitize_utf8 (const char *in, int in_len, Bool *latin1_pP)
+double get_angle(double a, double b, double c)
{
- int out_len = in_len * 4; // length of string might increase
- char *s2 = (char *) malloc (out_len);
- char *out = s2;
- const char *in_end = in + in_len;
- const char *out_end = out + out_len;
- Bool latin1_p = True;
-
- while (in < in_end)
- {
- unsigned long uc;
- long L1 = utf8_decode ((const unsigned char *) in, in_end - in, &uc);
- long L2 = utf8_encode (uc, out, out_end - out);
- in += L1;
- out += L2;
- if (uc > 255) latin1_p = False;
- }
- *out = 0;
- NSString *nsstr =
- [NSString stringWithCString:s2 encoding:NSUTF8StringEncoding];
- free (s2);
- if (latin1_pP) *latin1_pP = latin1_p;
- return (nsstr ? nsstr : @"");
+ double cos_a, i_cos_a;
+ cos_a = (((b * b) + (c * c)) - (a * a)) / (double) (2.0 * b * c);
+ i_cos_a = acos(cos_a);
+ return i_cos_a;
}
-*/
-int
-XTextExtents (XFontStruct *f, const char *s, int length,
- int *dir_ret, int *ascent_ret, int *descent_ret,
- XCharStruct *cs)
-{
- // Unfortunately, adding XCharStructs together to get the extents for a
- // string doesn't work: Cocoa uses non-integral character advancements, but
- // XCharStruct.width is an integer. Plus that doesn't take into account
- // kerning pairs, alternate glyphs, and fun stuff like the word "Zapfino" in
- // Zapfino.
-
- Font ff = f->fid;
- Display *dpy = ff->dpy;
- jwxyz_render_text (dpy, ff->native_font, s, length, GL_FALSE, cs, 0);
- *dir_ret = 0;
- *ascent_ret = f->ascent;
- *descent_ret = f->descent;
- return 0;
-}
-int
-XTextWidth (XFontStruct *f, const char *s, int length)
+Bool is_same_slope(linked_point * a)
{
- int ascent, descent, dir;
- XCharStruct cs;
- XTextExtents (f, s, length, &dir, &ascent, &descent, &cs);
- return cs.width;
-}
+ int abx, bcx, aby, bcy, aa, bb;
+ linked_point *b;
+ linked_point *c;
-int
-XTextExtents16 (XFontStruct *f, const XChar2b *s, int length,
- int *dir_ret, int *ascent_ret, int *descent_ret,
- XCharStruct *cs)
-{
- // Bool latin1_p = True;
- int i, utf8_len = 0;
- char *utf8 = XChar2b_to_utf8 (s, &utf8_len); // already sanitized
+ b = a->next;
+ c = b->next;
- for (i = 0; i < length; i++)
- if (s[i].byte1 > 0) {
- // latin1_p = False;
- break;
+ // test if slopes are indefinite for both line segments
+ if (a->x == b->x) {
+ return b->x == c->x;
+ } else if (b->x == c->x) {
+ return False; // false, as ax/bx is not indefinite
}
- {
- Font ff = f->fid;
- Display *dpy = ff->dpy;
- jwxyz_render_text (dpy, ff->native_font, utf8, strlen(utf8),
- GL_TRUE, cs, 0);
- }
+ abx = a->x - b->x;
+ bcx = b->x - c->x;
+ aby = a->y - b->y;
+ bcy = b->y - c->y;
+ aa = abx * bcy;
+ bb = bcx * aby;
- *dir_ret = 0;
- *ascent_ret = f->ascent;
- *descent_ret = f->descent;
- free (utf8);
- return 0;
+ return aa == bb;
}
-
-/* "Returns the distance in pixels in the primary draw direction from
- the drawing origin to the origin of the next character to be drawn."
-
- "overall_ink_return is set to the bbox of the string's character ink."
-
- "The overall_ink_return for a nondescending, horizontally drawn Latin
- character is conventionally entirely above the baseline; that is,
- overall_ink_return.height <= -overall_ink_return.y."
-
- [So this means that y is the top of the ink, and height grows down:
- For above-the-baseline characters, y is negative.]
-
- "The overall_ink_return for a nonkerned character is entirely at, and to
- the right of, the origin; that is, overall_ink_return.x >= 0."
-
- [So this means that x is the left of the ink, and width grows right.
- For left-of-the-origin characters, x is negative.]
-
- "A character consisting of a single pixel at the origin would set
- overall_ink_return fields y = 0, x = 0, width = 1, and height = 1."
- */
-int
-Xutf8TextExtents (XFontSet set, const char *str, int len,
- XRectangle *overall_ink_return,
- XRectangle *overall_logical_return)
+void draw_three_vertices(linked_point * a, Bool triangle)
{
-#if 0
- Bool latin1_p;
- NSString *nsstr = sanitize_utf8 (str, len, &latin1_p);
- XCharStruct cs;
- utf8_metrics (set->font->fid, nsstr, &cs);
+ linked_point *b;
+ linked_point *c;
+ GLenum drawType;
- /* "The overall_logical_return is the bounding box that provides minimum
- spacing to other graphical features for the string. Other graphical
- features, for example, a border surrounding the text, should not
- intersect this rectangle."
-
- So I think that means they're the same? Or maybe "ink" is the bounding
- box, and "logical" is the advancement? But then why is the return value
- the advancement?
- */
- if (overall_ink_return)
- XCharStruct_to_XmbRectangle (cs, *overall_ink_return);
- if (overall_logical_return)
- XCharStruct_to_XmbRectangle (cs, *overall_logical_return);
-
- return cs.width;
-#endif
- abort();
-}
+ b = a->next;
+ c = b->next;
+ GLfloat vertices[3][2] = {
+ {a->x, a->y},
+ {b->x, b->y},
+ {c->x, c->y}
+ };
-static int
-draw_string (Display *dpy, Drawable d, GC gc, int x, int y,
- const char *str, size_t len, GLboolean utf8)
-{
- Font ff = gc->gcv.font;
- XCharStruct cs;
-
- char *data = 0;
- jwxyz_render_text (dpy, ff->native_font, str, len, utf8, &cs, &data);
- int w = cs.rbearing - cs.lbearing;
- int h = cs.ascent + cs.descent;
-
- if (w < 0 || h < 0) abort();
- if (w == 0 || h == 0) {
- if (data) free(data);
- return 0;
- }
-
- XImage *img = XCreateImage (dpy, dpy->screen->visual, 32,
- ZPixmap, 0, data, w, h, 0, 0);
-
- /* The image of text is a 32-bit image, in white.
- Take the red channel for intensity and use that as alpha.
- replace RGB with the GC's foreground color.
- This expects that XPutImage respects alpha and only writes
- the bits that are not masked out.
- This also assumes that XPutImage expects ARGB.
- */
- {
- char *s = data;
- char *end = s + (w * h * 4);
- uint8_t rgba[4];
- jwxyz_query_color (dpy, gc->gcv.foreground, rgba);
- while (s < end) {
-
- s[3] = s[1];
- s[0] = rgba[0];
- s[1] = rgba[1];
- s[2] = rgba[2];
- s += 4;
+ if (triangle) {
+ drawType = GL_TRIANGLES;
+ } else {
+ drawType = GL_LINES;
}
- }
-
- XPutImage (dpy, d, gc, img, 0, 0,
- x + cs.lbearing,
- y - cs.ascent,
- w, h);
- XDestroyImage (img);
- return 0;
-}
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ glDrawArrays(drawType, 0, 3);
-int
-XDrawString (Display *dpy, Drawable d, GC gc, int x, int y,
- const char *str, int len)
-{
- return draw_string (dpy, d, gc, x, y, str, len, GL_FALSE);
+ free(b); // cut midpoint off from remaining polygon vertex list
+ a->next = c;
}
-int
-XDrawString16 (Display *dpy, Drawable d, GC gc, int x, int y,
- const XChar2b *str, int len)
+Bool is_an_ear(linked_point * a)
{
- XChar2b *b2 = malloc ((len + 1) * sizeof(*b2));
- char *s2;
- int ret;
- memcpy (b2, str, len * sizeof(*b2));
- b2[len].byte1 = b2[len].byte2 = 0;
- s2 = XChar2b_to_utf8 (b2, 0);
- free (b2);
- ret = draw_string (dpy, d, gc, x, y, s2, strlen(s2), GL_TRUE);
- free (s2);
- return ret;
-}
+ double edge_ab, edge_bc, edge_ac;
+ double angle_a, angle_b, angle_c;
+ double my_pi;
+ linked_point *b, *c;
+ b = a->next;
+ c = b->next;
+ my_pi = (double) M_PI;
-void
-Xutf8DrawString (Display *dpy, Drawable d, XFontSet set, GC gc,
- int x, int y, const char *str, int len)
-{
- draw_string (dpy, d, gc, x, y, str, len, GL_TRUE);
+ edge_ab = compute_edge_length(a, b);
+ edge_bc = compute_edge_length(b, c);
+ edge_ac = compute_edge_length(a, c);
+ angle_a = get_angle(edge_bc, edge_ab, edge_ac);
+ angle_b = get_angle(edge_ac, edge_ab, edge_bc);
+ angle_c = get_angle(edge_ab, edge_ac, edge_bc);
+
+ return angle_a < my_pi && angle_b < my_pi && angle_c < my_pi;
}
-int
-XDrawImageString (Display *dpy, Drawable d, GC gc, int x, int y,
- const char *str, int len)
+Bool is_three_point_loop(linked_point * head)
{
- int ascent, descent, dir;
- XCharStruct cs;
- XTextExtents (&gc->gcv.font->metrics, str, len,
- &dir, &ascent, &descent, &cs);
- jwxyz_fill_rect (dpy, d, gc,
- x + MIN (0, cs.lbearing),
- y - MAX (0, ascent),
- MAX (MAX (0, cs.rbearing) -
- MIN (0, cs.lbearing),
- cs.width),
- MAX (0, ascent) + MAX (0, descent),
- gc->gcv.background);
- return XDrawString (dpy, d, gc, x, y, str, len);
+ return head->x == head->next->next->next->x
+ && head->y == head->next->next->next->y;
}
-int
-XSetClipMask (Display *dpy, GC gc, Pixmap m)
+void traverse_points_list(linked_point * root)
{
-//#### abort();
-/*
- TODO
+ linked_point *head;
+ head = root;
- Assert (!!gc->gcv.clip_mask == !!gc->clip_mask, "GC clip mask mixup");
+ while (!is_three_point_loop(head)) {
+ if (is_an_ear(head)) {
+ draw_three_vertices(head, True);
+ } else if (is_same_slope(head)) {
+ draw_three_vertices(head, False);
+ } else {
+ head = head->next;
+ }
+ }
- if (gc->gcv.clip_mask) {
- XFreePixmap (dpy, gc->gcv.clip_mask);
- CGImageRelease (gc->clip_mask);
- }
+ // handle final three vertices in polygon
+ if (is_an_ear(head)) {
+ draw_three_vertices(head, True);
+ } else if (is_same_slope(head)) {
+ draw_three_vertices(head, False);
+ } else {
+ free(head->next->next);
+ free(head->next);
+ free(head);
+ Assert (False, "traverse_points_list: unknown configuration");
+ }
- gc->gcv.clip_mask = copy_pixmap (dpy, m);
- if (gc->gcv.clip_mask)
- gc->clip_mask =
- CGBitmapContextCreateImage (gc->gcv.clip_mask->cgc);
- else
- gc->clip_mask = 0;
-*/
-
- return 0;
+ free(head->next);
+ free(head);
}
-int
-XSetClipOrigin (Display *dpy, GC gc, int x, int y)
-{
- gc->gcv.clip_x_origin = x;
- gc->gcv.clip_y_origin = y;
- return 0;
-}
+
#endif /* JWXYZ_GL -- entire file */