Evince does a bad job of displaying some DVI files, such as ones containing cubed roots. Gnome bug 494736 documents the problem. So I decided that I should just fix this bug, because how hard could it be?
After playing with TeX to create some sample files, it became obvious that the cubed root character was getting covered over. The characters were not being placed with a transparent background, they we being placed with a white background. To confirm this, I placed the characters transparently and lo and behold the cube root character was being covered up.
dvi_cairo_draw_glyph in backend/dvi/cairo-device.c does all of the drawing. This is the relevant change to confirm the problem.
This is a simple TeX file that causes the problem.
And this is how the TeX above looks like as a DVI file in Evince with the changes above. Notice how the 3 is lighter than the root symbol, this is because the root symbol is being placed on top of it and it's white background is on top of the 3.
Diagnosis complete, time to fix.
The glyph->data above is a bitmap image of the glyph to place. Some debugging shows that it is stored as a CAIRO_FORMAT_RGB24, a format with no transparency information. Now to find where the bitmap is being created and store it as CAIRO_FORMAT_ARGB32 a format with 8 bits for each of red, green, blue and alpha/transparency.
mdvi_cairo_device_render creates an image surface with CAIRO_FORMAT_RGB24, lets change this to ARGB32. This still doesn't fix things, perhaps transparency is never being set when loading the glyphs in the first place. The bitmaps are loaded from font files in backend/dvi/mdvi-lib/pk.c get_packed. METAFONT uses a compressed format for it's font files called Packed File Font Format. I found the following reference on PK files Packed Font File Format. The upshot is that each character is encoded as a sequence of black or white pixels. Something like 3 pixels of black followed by 10 pixels of white, followed by 6 pixels of black might draw one row of the character. backend/dvi/mdvi-lib/bitmap.c bitmap_set_row is called to draw a sequence of these black or white bits.
The code above reads in where the ink goes, it doesn't specify the color of the ink, that happens later. backend/dvi/mdvi-lib/bitmap.c mdvi_shrink_glyph_grey appears to do the work of converting a bitmap into an image of the proper size. This function calls backend/dvi/cairo_device.c dvi_cairo_put_pixel to draw each pixel of the image to be placed. A quick fix is to intercept pixels colored non-transparent white, and make them fully transparent. The complete patch against evince 2.30.3 from Ubuntu 10.04 is below.
Is this an acceptable solution? I imagine that most DVI documents are black text on white "paper". Also, Evince does not appear to support colored DVI documents so in that sense no functionality is lost. I think that most users will benefit from being able to view all of the document's glyphs as intended.