+static void InitFontClipmasks()
+{
+ static boolean clipmasks_initialized = FALSE;
+ XGCValues clip_gc_values;
+ unsigned long clip_gc_valuemask;
+ GC copy_clipmask_gc;
+ int i, j;
+
+ if (gfx.num_fonts == 0 || gfx.font_bitmap_info[0].bitmap == NULL)
+ return;
+
+ if (!clipmasks_initialized)
+ {
+ for (i=0; i < gfx.num_fonts; i++)
+ gfx.font_bitmap_info[i].clip_mask = NULL;
+
+ clipmasks_initialized = TRUE;
+ }
+
+ for (i=0; i < gfx.num_fonts; i++)
+ {
+ if (gfx.font_bitmap_info[i].clip_mask)
+ for (j=0; j < NUM_FONT_CHARS; j++)
+ XFreePixmap(display, gfx.font_bitmap_info[i].clip_mask[j]);
+ free(gfx.font_bitmap_info[i].clip_mask);
+
+ gfx.font_bitmap_info[i].clip_mask = NULL;
+ }
+
+ if (font_clip_gc)
+ XFreeGC(display, font_clip_gc);
+ font_clip_gc = None;
+
+ /* This stuff is needed because X11 (XSetClipOrigin(), to be precise) is
+ often very slow when preparing a masked XCopyArea() for big Pixmaps.
+ To prevent this, create small (tile-sized) mask Pixmaps which will then
+ be set much faster with XSetClipOrigin() and speed things up a lot. */
+
+ clip_gc_values.graphics_exposures = False;
+ clip_gc_valuemask = GCGraphicsExposures;
+ font_clip_gc = XCreateGC(display, window->drawable,
+ clip_gc_valuemask, &clip_gc_values);
+
+ /* create graphic context structures needed for clipping */
+ clip_gc_values.graphics_exposures = False;
+ clip_gc_valuemask = GCGraphicsExposures;
+ copy_clipmask_gc = XCreateGC(display,
+ gfx.font_bitmap_info[0].bitmap->clip_mask,
+ clip_gc_valuemask, &clip_gc_values);
+
+ /* create only those clipping Pixmaps we really need */
+ for (i=0; i < gfx.num_fonts; i++)
+ {
+ if (gfx.font_bitmap_info[i].bitmap == NULL)
+ continue;
+
+ gfx.font_bitmap_info[i].clip_mask =
+ checked_calloc(NUM_FONT_CHARS * sizeof(Pixmap));
+
+ for (j=0; j < NUM_FONT_CHARS; j++)
+ {
+ Bitmap *src_bitmap = gfx.font_bitmap_info[i].bitmap;
+ Pixmap src_pixmap = src_bitmap->clip_mask;
+ int xpos = j % FONT_CHARS_PER_LINE;
+ int ypos = j / FONT_CHARS_PER_LINE;
+ int width = gfx.font_bitmap_info[i].width;
+ int height = gfx.font_bitmap_info[i].height;
+ int src_x = gfx.font_bitmap_info[i].src_x + xpos * width;
+ int src_y = gfx.font_bitmap_info[i].src_y + ypos * height;
+
+ gfx.font_bitmap_info[i].clip_mask[j] =
+ XCreatePixmap(display, window->drawable, width, height, 1);
+
+ XCopyArea(display, src_pixmap, gfx.font_bitmap_info[i].clip_mask[j],
+ copy_clipmask_gc, src_x, src_y, width, height, 0, 0);
+ }
+ }
+
+ XFreeGC(display, copy_clipmask_gc);
+}
+#endif /* TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND */
+
+void InitFontInfo(struct FontBitmapInfo *font_bitmap_info, int num_fonts,
+ int (*select_font_function)(int))
+{
+ gfx.num_fonts = num_fonts;
+ gfx.font_bitmap_info = font_bitmap_info;
+ gfx.select_font_function = select_font_function;
+
+#if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
+ InitFontClipmasks();
+#endif
+}