The patch presented in the last post was for Ubuntu 10.04. Since 10.10 just came out, I decided to test the patch against 10.10 and unfortunately it doesn't work. It seems that the change to ARGB32 is what is causing the problem, nothing appears in the document except for the horizontal line of the root symbol. After a week of debugging here and there, it turns out that the new version of cario expects you to tell it when you modify it's internal structures without it's knowledge.

Here is the relevant change to backends/dvi/cairo_device.c that fixes this problem.

static void
dvi_cairo_put_pixel (void *image, int x, int y, Ulong color)
{
	cairo_surface_t *surface;
	gint             rowstride;
	guint32         *p;
	surface = (cairo_surface_t *) image;
	rowstride = cairo_image_surface_get_stride (surface);
	p = (guint32*) (cairo_image_surface_get_data (surface) + y * rowstride + x * 4);
    /* per cairo docs, must flush before modifying outside of cairo */
    cairo_surface_flush(surface);
	*p = color;
    /* tell cairo we did something */
    cairo_surface_mark_dirty(glyph_surf);
}

Switching gears, the fix discussed in my last post was no good. Sometimes we do want to place white pixels (for example when placing white text on a black background). Fortunately, there is still a way to fix the problem when placing glyphs. Evince's dvi backend loads a bitmap of the glyph to display. From this bitmap it creates an anti-aliased image of the appropriate size. To determine what color to place in the image, the backend samples the number of bits that fall in a region of the bitmap. The more bits sampled, the darker the color. A quick fix is to realize that if no bits are in the sample region then that region is not part of the glyph and should be transparent. So the new fix for the issue is to change the lightest color (zero samples) to transparent from white.

Here's the change from backends/dvi/mdvi_lib/bitmap.c

	samplemax = vs * hs;
	npixels = samplemax + 1;
	pixels = get_color_table(&;dvi->device, npixels, pk->fg, pk->bg,
			dvi->params.gamma, dvi->params.density);
	if(pixels == NULL) {
		npixels = 2;
		colortab[0] = pk->fg;
		colortab[1] = pk->bg;
		pixels = &colortab[0];
	}
    /* a sample with a count of zero should be fully transparent */
    pixels[0] = 0;

The pixels array maps sample numbers to colors. pixels[sample_number] stores the correct color for the given sample number. To make sure that this fix works with non-white backgounds I created a test dvi with colors (it is posted with the gnome bug if you are curious). Here is how a snippet of it looks with the fix.

Before


After


Of course this fix could be better still. Instead of fading out from the foreground color towards white and then becoming fully transparent at the last moment, the colors should just gradually become more and more transparent. The goal is figure out that change for the next post.