pkampst=rbugspam at few.vu.nl
2006-Nov-03 10:33 UTC
[Rd] win.metafile() resolution too low (PR#9337)
Full_Name: Peter Kampstra Version: 2.4.0 OS: Windows Submission from: (NULL) (130.37.20.20) Hi, 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 win.metafile("resolution.emf") x=seq(1,10,0.001) y=1/x plot(x,y,type="l") dev.off() 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, "GraphApp\0\0"); 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: /* * Creates a HDC to the best printer to be used as a reference for CreateEnhMetaFile */ HDC createbestmetafilehdc() { DWORD neededsize; DWORD noprinters; DWORD printer; LPPRINTER_INFO_5 printerinfo = NULL; int bestres = 0; HDC besthdc = 0; 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, LOGPIXELSY); 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, "GraphApp\0\0"); if (refhdc) DeleteDC(refhdc); And cppix,ppix, etc. can be calculated like (this is a workaround for buggy drivers??): HDC forhdc=refhdc; if (!(forhdc)) forhdc=GetDC(NULL); cppix = 25.40 * GetDeviceCaps(forhdc,HORZRES) / GetDeviceCaps(forhdc,HORZSIZE); ppix = 100 * GetDeviceCaps(forhdc, LOGPIXELSX); cppiy = 25.40 * GetDeviceCaps(forhdc, VERTRES) / GetDeviceCaps(forhdc, VERTSIZE); ppiy = 100 * GetDeviceCaps(forhdc, LOGPIXELSY); if (!(refhdc)) ReleaseDC(NULL,forhdc); 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