[Rd] win.metafile() resolution too low (PR#9337)
pkampst=rbugspam at few.vu.nl
pkampst=rbugspam at few.vu.nl
Fri Nov 3 11:33:54 CET 2006
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
More information about the R-devel
mailing list