[cairo] SVG to EMF quality
Adrian Johnson
ajohnson at redneon.com
Wed Sep 9 07:07:35 PDT 2009
Shixin Zeng wrote:
> Hi,
>
> I've produced some pictures with matplotlib for my paper, which
> prefers enhanced MetaFile (EMF). However, current maplotlib doesn't
> support EMF output, but svg. So I tried to convert svg to emf via
> cairo, as mentioned in this
> thread:http://lists.cairographics.org/archives/cairo/2009-January/016215.html
>
> But the problem is that the quality of the output emf file is pretty
> low. Is this caused by my badly programming or the limitation of this
> method itself? Thanks
After discovering EMFexplorer [1] and examining some different EMF files
I have found the cause of the low quality EMF output from the
win32-printing surface.
In GDI all path functions use integer coordinates. For small drawings
this causes rounding problems. Using EMFexplorer I could see that other
applications were scaling down the GDI current transformation matrix and
scaling up path coordinates to increase the precision.
This was something I previously tried with the win32-printing surface
without success. Using EMFexplorer to check the output I could
immediately see what the problem is. The win32-print surface is
resetting the GDI CTM to identity to preventing rounding errors when
printing where the GDI units are in dpi.
The patch on my emf branch [2] is an initial attempt at fixing this. It
needs further testing to ensure I have not caused any regressions when
printing. With this patch it is possible to get good EMF output with the
following code:
void create_emf (char *filename)
{
HDC dc;
HDC ref_dc;
XFORM xform;
cairo_surface_t *surface;
cairo_t *cr;
ref_dc = GetDC (NULL);
dc = CreateEnhMetaFile (ref_dc, filename, NULL, NULL);
ReleaseDC (NULL, dc);
/* Scale the GDI CTM by 1/16. This allows all coordinates to
* be scaled up by 16 to increase precision */
SetGraphicsMode (dc, GM_ADVANCED);
xform.eM11 = 1.0/16;
xform.eM12 = 0;
xform.eM21 = 0;
xform.eM22 = 1.0/16;
xform.eDx = 0;
xform.eDy = 0;
SetWorldTransform (dc, &xform);
surface = cairo_win32_printing_surface_create (dc);
cr = cairo_create (surface);
/* Undo the scale applied to the GDI CTM */
cairo_scale (cr, 16, 16);
draw (cr);
cairo_destroy (cr);
cairo_surface_destroy (surface);
CloseEnhMetaFile (dc);
}
[1] http://frazmitic.free.fr/emfexplorer/
[2] http://cgit.freedesktop.org/~ajohnson/cairo/log/?h=emf
More information about the cairo
mailing list