[Rd] win.metafile() resolution too low (PR#9337)

From: <pkampst=rbugspam_at_few.vu.nl>
Date: Fri 03 Nov 2006 - 10:33:54 GMT

Full_Name: Peter Kampstra
Version: 2.4.0
OS: Windows
Submission from: (NULL) (


If you use win.metafile(), "Save as metafile...", or "Copy as metafile" on Windows, the metafile is rendered at screen resolution. Therefore, the output of curves like


does not look smooth. I tracked the problem down to https://svn.r-project.org/R/trunk/src/gnuwin32/graphapp/metafile.c , to

    hDC = CreateEnhMetaFile(NULL, strlen(name) ? name : NULL, &wr,

If NULL is passed as reference HDC to this function, the metafile will be at screen resolution. If you use such a picture in Word/Powerpoint/etc, it is visible that curved lines are not smooth...

Therefore, I suggest using a printer as the reference HDC instead. The following function can be used:


        EnumPrinters(PRINTER_ENUM_CONNECTIONS|PRINTER_ENUM_LOCAL, NULL, 5, NULL, 0, &neededsize, &noprinters);

         printerinfo = (LPPRINTER_INFO_5) malloc(neededsize);

        if (EnumPrinters(PRINTER_ENUM_CONNECTIONS|PRINTER_ENUM_LOCAL, NULL, 5, (LPBYTE)printerinfo, neededsize, &neededsize, &noprinters)) {

		//init best resolution for hdc=0, which is screen resolution:    
		HDC curhdc = GetDC(NULL);
		if (curhdc) {
			bestres = GetDeviceCaps(curhdc, LOGPIXELSX) + GetDeviceCaps(curhdc,
			bestres = ReleaseDC(NULL, curhdc); 

for (int i = 0; i < noprinters; i++) { curhdc = CreateDC("WINSPOOL", printerinfo[i].pPrinterName, NULL, NULL); if (curhdc) { int curres = GetDeviceCaps(curhdc, LOGPIXELSX) + GetDeviceCaps(curhdc, LOGPIXELSY); if (curres > bestres) { if (besthdc) DeleteDC(besthdc); bestres = curres; besthdc = curhdc; } else { DeleteDC(curhdc); } }
} free(printerinfo); return besthdc;


This function can be used like:

        HDC refhdc=createbestmetafilehdc();

	hDC = CreateEnhMetaFile(refhdc, strlen(name) ? name : NULL, &wr, 
	if (refhdc)

And cppix,ppix, etc. can be calculated like (this is a workaround for buggy drivers??):

	HDC forhdc=refhdc;
	if (!(forhdc))
	cppix = 25.40 * GetDeviceCaps(forhdc,HORZRES) /
	ppix  = 100 * GetDeviceCaps(forhdc, LOGPIXELSX);
	cppiy = 25.40 * GetDeviceCaps(forhdc, VERTRES) / GetDeviceCaps(forhdc,
	ppiy  = 100 * GetDeviceCaps(forhdc, LOGPIXELSY);
	if (!(refhdc))

And probably some other changes will be necessary...

Keep up the good work,

Peter Kampstra
pkampst=rbugspam_at_cs.vu.nl / http://peter.kampstra.net

R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel Received on Sat Nov 04 10:29:41 2006

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.1.8, at Sat 04 Nov 2006 - 00:30:33 GMT.

Mailing list information is available at https://stat.ethz.ch/mailman/listinfo/r-devel. Please read the posting guide before posting to the list.