2 * PostScript driver initialization functions
4 * Copyright 1998 Huw D M Davies
11 #include "debugtools.h"
18 DEFAULT_DEBUG_CHANNEL(psdrv
);
20 static BOOL
PSDRV_CreateDC( DC
*dc
, LPCSTR driver
, LPCSTR device
,
21 LPCSTR output
, const DEVMODEA
* initData
);
22 static BOOL
PSDRV_DeleteDC( DC
*dc
);
24 static const DC_FUNCTIONS PSDRV_Funcs
=
27 NULL
, /* pAbortPath */
31 NULL
, /* pBeginPath */
33 NULL
, /* pBitmapBits */
34 NULL
, /* pChoosePixelFormat */
35 PSDRV_Chord
, /* pChord */
36 NULL
, /* pCloseFigure */
37 NULL
, /* pCreateBitmap */
38 PSDRV_CreateDC
, /* pCreateDC */
39 NULL
, /* pCreateDIBSection */
40 NULL
, /* pCreateDIBSection16 */
41 PSDRV_DeleteDC
, /* pDeleteDC */
42 NULL
, /* pDeleteObject */
43 NULL
, /* pDescribePixelFormat */
44 PSDRV_DeviceCapabilities
, /* pDeviceCapabilities */
45 PSDRV_Ellipse
, /* pEllipse */
46 PSDRV_EndDoc
, /* pEndDoc */
47 PSDRV_EndPage
, /* pEndPage */
49 PSDRV_EnumDeviceFonts
, /* pEnumDeviceFonts */
50 PSDRV_Escape
, /* pEscape */
51 NULL
, /* pExcludeClipRect */
52 PSDRV_ExtDeviceMode
, /* pExtDeviceMode */
53 NULL
, /* pExtFloodFill */
54 PSDRV_ExtTextOut
, /* pExtTextOut */
57 NULL
, /* pFlattenPath */
59 PSDRV_GetCharWidth
, /* pGetCharWidth */
60 NULL
, /* pGetDCOrgEx */
61 NULL
, /* pGetDeviceGammaRamp */
63 NULL
, /* pGetPixelFormat */
64 PSDRV_GetTextExtentPoint
, /* pGetTextExtentPoint */
65 PSDRV_GetTextMetrics
, /* pGetTextMetrics */
66 NULL
, /* pIntersectClipRect */
67 NULL
, /* pInvertRgn */
68 PSDRV_LineTo
, /* pLineTo */
70 NULL
, /* pOffsetClipRgn */
71 NULL
, /* pOffsetViewportOrg (optional) */
72 NULL
, /* pOffsetWindowOrg (optional) */
74 PSDRV_PatBlt
, /* pPatBlt */
76 NULL
, /* pPolyBezier */
77 NULL
, /* pPolyBezierTo */
79 PSDRV_PolyPolygon
, /* pPolyPolygon */
80 PSDRV_PolyPolyline
, /* pPolyPolyline */
81 PSDRV_Polygon
, /* pPolygon */
82 PSDRV_Polyline
, /* pPolyline */
83 NULL
, /* pPolylineTo */
84 NULL
, /* pRealizePalette */
85 PSDRV_Rectangle
, /* pRectangle */
86 NULL
, /* pRestoreDC */
87 PSDRV_RoundRect
, /* pRoundRect */
89 NULL
, /* pScaleViewportExt (optional) */
90 NULL
, /* pScaleWindowExt (optional) */
91 NULL
, /* pSelectClipPath */
92 NULL
, /* pSelectClipRgn */
93 PSDRV_SelectObject
, /* pSelectObject */
94 NULL
, /* pSelectPalette */
95 PSDRV_SetBkColor
, /* pSetBkColor */
96 NULL
, /* pSetBkMode */
97 PSDRV_SetDeviceClipping
, /* pSetDeviceClipping */
98 NULL
, /* pSetDeviceGammaRamp */
99 NULL
, /* pSetDIBitsToDevice */
100 NULL
, /* pSetMapMode (optional) */
101 NULL
, /* pSetMapperFlags */
102 PSDRV_SetPixel
, /* pSetPixel */
103 NULL
, /* pSetPixelFormat */
104 NULL
, /* pSetPolyFillMode */
106 NULL
, /* pSetRelAbs */
107 NULL
, /* pSetStretchBltMode */
108 NULL
, /* pSetTextAlign */
109 NULL
, /* pSetTextCharacterExtra */
110 PSDRV_SetTextColor
, /* pSetTextColor */
111 NULL
, /* pSetTextJustification */
112 NULL
, /* pSetViewportExt (optional) */
113 NULL
, /* pSetViewportOrg (optional) */
114 NULL
, /* pSetWindowExt (optional) */
115 NULL
, /* pSetWindowOrg (optional) */
116 PSDRV_StartDoc
, /* pStartDoc */
117 PSDRV_StartPage
, /* pStartPage */
118 NULL
, /* pStretchBlt */
119 PSDRV_StretchDIBits
, /* pStretchDIBits */
120 NULL
, /* pStrokeAndFillPath */
121 NULL
, /* pStrokePath */
122 NULL
, /* pSwapBuffers */
123 NULL
/* pWidenPath */
127 /* Default entries for devcaps */
129 static DeviceCaps PSDRV_DevCaps
= {
131 /* technology */ DT_RASPRINTER
,
144 /* curveCaps */ CC_CIRCLES
| CC_PIE
| CC_CHORD
| CC_ELLIPSES
|
145 CC_WIDE
| CC_STYLED
| CC_WIDESTYLED
| CC_INTERIORS
|
147 /* lineCaps */ LC_POLYLINE
| LC_MARKER
| LC_POLYMARKER
| LC_WIDE
|
148 LC_STYLED
| LC_WIDESTYLED
| LC_INTERIORS
,
149 /* polygoalnCaps */ PC_POLYGON
| PC_RECTANGLE
| PC_WINDPOLYGON
|
150 PC_SCANLINE
| PC_WIDE
| PC_STYLED
| PC_WIDESTYLED
|
152 /* textCaps */ TC_CR_ANY
, /* psdrv 0x59f7 */
153 /* clipCaps */ CP_RECTANGLE
,
154 /* rasterCaps */ RC_BITBLT
| RC_BITMAP64
| RC_GDI20_OUTPUT
|
155 RC_DIBTODEV
| RC_STRETCHBLT
|
156 RC_STRETCHDIB
, /* psdrv 0x6e99 */
161 /* logPixelsX */ 600,
162 /* logPixelsY */ 600,
164 /* palette size */ 0,
167 static PSDRV_DEVMODEA DefaultDevmode
=
170 /* dmDeviceName */ "Wine PostScript Driver",
171 /* dmSpecVersion */ 0x30a,
172 /* dmDriverVersion */ 0x001,
173 /* dmSize */ sizeof(DEVMODEA
),
174 /* dmDriverExtra */ 0,
175 /* dmFields */ DM_ORIENTATION
| DM_PAPERSIZE
| DM_SCALE
|
176 DM_COPIES
| DM_DEFAULTSOURCE
| DM_COLOR
|
177 DM_DUPLEX
| DM_YRESOLUTION
| DM_TTOPTION
,
180 /* dmOrientation */ DMORIENT_PORTRAIT
,
181 /* dmPaperSize */ DMPAPER_A4
,
182 /* dmPaperLength */ 2969,
183 /* dmPaperWidth */ 2101
186 /* dmScale */ 100, /* ?? */
188 /* dmDefaultSource */ DMBIN_AUTO
,
189 /* dmPrintQuality */ 0,
190 /* dmColor */ DMCOLOR_MONOCHROME
,
192 /* dmYResolution */ 0,
193 /* dmTTOption */ DMTT_SUBDEV
,
196 /* dmUnusedPadding */ 0,
197 /* dmBitsPerPel */ 0,
199 /* dmPelsHeight */ 0,
200 /* dmDisplayFlags */ 0,
201 /* dmDisplayFrequency */ 0,
205 /* dmDitherType */ 0,
208 /* dmPanningWidth */ 0,
209 /* dmPanningHeight */ 0
215 /* ppdfilename */ "default.ppd",
216 /* numInstalledOptions */ 0
220 HANDLE PSDRV_Heap
= 0;
222 static HANDLE PSDRV_DefaultFont
= 0;
223 static LOGFONTA DefaultLogFont
= {
224 100, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
, 0, 0,
225 DEFAULT_QUALITY
, FIXED_PITCH
| FF_MODERN
, ""
228 /*********************************************************************
231 * Initializes font metrics and registers driver. Called from GDI_Init()
234 BOOL WINAPI
PSDRV_Init( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
236 TRACE("(0x%4x, 0x%08lx, %p)\n", hinst
, reason
, reserved
);
239 case DLL_PROCESS_ATTACH
:
240 /* FIXME: return FALSE if we fail any of these steps */
241 PSDRV_Heap
= HeapCreate(0, 0x10000, 0);
242 PSDRV_GetFontMetrics();
243 PSDRV_DefaultFont
= CreateFontIndirectA(&DefaultLogFont
);
244 /* Register driver as "WINEPS", "WINEPS.DLL" and "WINEPS.DRV"
245 to allow an easy configuring for users */
246 DRIVER_RegisterDriver( "WINEPS", &PSDRV_Funcs
);
247 DRIVER_RegisterDriver( "WINEPS.DLL", &PSDRV_Funcs
);
248 DRIVER_RegisterDriver( "WINEPS.DRV", &PSDRV_Funcs
);
250 case DLL_PROCESS_DETACH
:
251 DeleteObject( PSDRV_DefaultFont
);
252 HeapDestroy( PSDRV_Heap
);
253 DRIVER_UnregisterDriver( "WINEPS" );
254 DRIVER_UnregisterDriver( "WINEPS.DLL" );
255 DRIVER_UnregisterDriver( "WINEPS.DRV" );
263 /**********************************************************************
266 static BOOL
PSDRV_CreateDC( DC
*dc
, LPCSTR driver
, LPCSTR device
,
267 LPCSTR output
, const DEVMODEA
* initData
)
269 PSDRV_PDEVICE
*physDev
;
273 INT width
= 0, height
= 0;
275 /* If no device name was specified, retrieve the device name
276 * from the DEVMODE structure from the DC's physDev.
277 * (See CreateCompatibleDC) */
278 if ( !device
&& dc
->physDev
)
280 physDev
= (PSDRV_PDEVICE
*)dc
->physDev
;
281 device
= physDev
->Devmode
->dmPublic
.dmDeviceName
;
283 pi
= PSDRV_FindPrinterInfo(device
);
285 TRACE("(%s %s %s %p)\n", driver
, device
, output
, initData
);
287 if(!pi
) return FALSE
;
290 MESSAGE("To use WINEPS you need to install some AFM files.\n");
294 physDev
= (PSDRV_PDEVICE
*)HeapAlloc( PSDRV_Heap
, HEAP_ZERO_MEMORY
,
296 if (!physDev
) return FALSE
;
297 dc
->physDev
= physDev
;
301 physDev
->Devmode
= (PSDRV_DEVMODEA
*)HeapAlloc( PSDRV_Heap
, 0,
302 sizeof(PSDRV_DEVMODEA
) );
303 if(!physDev
->Devmode
) {
304 HeapFree( PSDRV_Heap
, 0, physDev
);
308 memcpy( physDev
->Devmode
, pi
->Devmode
, sizeof(PSDRV_DEVMODEA
) );
311 PSDRV_MergeDevmodes(physDev
->Devmode
, (PSDRV_DEVMODEA
*)initData
, pi
);
315 devCaps
= HeapAlloc( PSDRV_Heap
, 0, sizeof(PSDRV_DevCaps
) );
316 memcpy(devCaps
, &PSDRV_DevCaps
, sizeof(PSDRV_DevCaps
));
318 /* Are aspect[XY] and logPixels[XY] correct? */
319 /* Need to handle different res in x and y => fix ppd */
320 devCaps
->aspectX
= devCaps
->logPixelsX
=
321 physDev
->pi
->ppd
->DefaultResolution
;
322 devCaps
->aspectY
= devCaps
->logPixelsY
=
323 physDev
->pi
->ppd
->DefaultResolution
;
324 devCaps
->aspectXY
= (int)hypot( (double)devCaps
->aspectX
,
325 (double)devCaps
->aspectY
);
328 for(page
= pi
->ppd
->PageSizes
; page
; page
= page
->next
) {
329 if(page
->WinPage
== physDev
->Devmode
->dmPublic
.u1
.s1
.dmPaperSize
)
333 FIXME("Can't find page\n");
334 physDev
->PageSize
.left
= 0;
335 physDev
->PageSize
.right
= 0;
336 physDev
->PageSize
.bottom
= 0;
337 physDev
->PageSize
.top
= 0;
338 } else if(page
->ImageableArea
) { /* PageSize is in device units */
339 physDev
->PageSize
.left
= page
->ImageableArea
->llx
*
340 devCaps
->logPixelsX
/ 72;
341 physDev
->PageSize
.right
= page
->ImageableArea
->urx
*
342 devCaps
->logPixelsX
/ 72;
343 physDev
->PageSize
.bottom
= page
->ImageableArea
->lly
*
344 devCaps
->logPixelsY
/ 72;
345 physDev
->PageSize
.top
= page
->ImageableArea
->ury
*
346 devCaps
->logPixelsY
/ 72;
348 physDev
->PageSize
.left
= physDev
->PageSize
.bottom
= 0;
349 physDev
->PageSize
.right
= page
->PaperDimension
->x
*
350 devCaps
->logPixelsX
/ 72;
351 physDev
->PageSize
.top
= page
->PaperDimension
->y
*
352 devCaps
->logPixelsY
/ 72;
354 TRACE("PageSize = (%d,%d - %d,%d)\n", physDev
->PageSize
.left
, physDev
->PageSize
.bottom
, physDev
->PageSize
.right
, physDev
->PageSize
.top
);
356 /* these are in mm */
357 width
= (physDev
->PageSize
.right
- physDev
->PageSize
.left
) * 25.4 /
359 height
= (physDev
->PageSize
.top
- physDev
->PageSize
.bottom
) * 25.4 /
362 if(physDev
->Devmode
->dmPublic
.u1
.s1
.dmOrientation
== DMORIENT_PORTRAIT
) {
363 devCaps
->horzSize
= width
;
364 devCaps
->vertSize
= height
;
366 devCaps
->horzSize
= height
;
367 devCaps
->vertSize
= width
;
370 devCaps
->horzRes
= devCaps
->logPixelsX
* devCaps
->horzSize
/ 25.4;
371 devCaps
->vertRes
= devCaps
->logPixelsY
* devCaps
->vertSize
/ 25.4;
373 TRACE("devcaps: horzSize = %dmm, vertSize = %dmm, "
374 "horzRes = %d, vertRes = %d\n",
375 devCaps
->horzSize
, devCaps
->vertSize
,
376 devCaps
->horzRes
, devCaps
->vertRes
);
378 if(physDev
->pi
->ppd
->ColorDevice
) {
379 devCaps
->bitsPixel
= 8;
380 devCaps
->numColors
= 256;
381 /* FIXME are these values OK? */
386 dc
->devCaps
= devCaps
;
388 dc
->hVisRgn
= CreateRectRgn(0, 0, dc
->devCaps
->horzRes
,
389 dc
->devCaps
->vertRes
);
391 dc
->hFont
= PSDRV_DefaultFont
;
392 physDev
->job
.output
= output
?
393 HEAP_strdupA( PSDRV_Heap
, 0, output
) :
394 HEAP_strdupA( PSDRV_Heap
, 0, "LPT1:" ); /* HACK */
395 physDev
->job
.hJob
= 0;
400 /**********************************************************************
403 static BOOL
PSDRV_DeleteDC( DC
*dc
)
405 PSDRV_PDEVICE
*physDev
= (PSDRV_PDEVICE
*)dc
->physDev
;
409 HeapFree( PSDRV_Heap
, 0, physDev
->Devmode
);
410 HeapFree( PSDRV_Heap
, 0, physDev
->job
.output
);
411 HeapFree( PSDRV_Heap
, 0, (void *)dc
->devCaps
);
412 HeapFree( PSDRV_Heap
, 0, physDev
);
419 /**********************************************************************
420 * PSDRV_FindPrinterInfo
422 PRINTERINFO
*PSDRV_FindPrinterInfo(LPCSTR name
)
424 static PRINTERINFO
*PSDRV_PrinterList
;
425 DWORD type
= REG_BINARY
, needed
, res
, dwPaperSize
;
426 PRINTERINFO
*pi
= PSDRV_PrinterList
, **last
= &PSDRV_PrinterList
;
431 TRACE("'%s'\n", name
);
433 for( ; pi
; last
= &pi
->next
, pi
= pi
->next
) {
434 if(!strcmp(pi
->FriendlyName
, name
))
438 pi
= *last
= HeapAlloc( PSDRV_Heap
, 0, sizeof(*pi
) );
439 pi
->FriendlyName
= HEAP_strdupA( PSDRV_Heap
, 0, name
);
440 res
= DrvGetPrinterData16((LPSTR
)name
, (LPSTR
)INT_PD_DEFAULT_DEVMODE
, &type
,
443 if(res
== ERROR_INVALID_PRINTER_NAME
|| needed
!= sizeof(DefaultDevmode
)) {
444 pi
->Devmode
= HeapAlloc( PSDRV_Heap
, 0, sizeof(DefaultDevmode
) );
445 memcpy(pi
->Devmode
, &DefaultDevmode
, sizeof(DefaultDevmode
) );
446 DrvSetPrinterData16((LPSTR
)name
, (LPSTR
)INT_PD_DEFAULT_DEVMODE
,
447 REG_BINARY
, (LPBYTE
)&DefaultDevmode
, sizeof(DefaultDevmode
) );
449 /* need to do something here AddPrinter?? */
451 pi
->Devmode
= HeapAlloc( PSDRV_Heap
, 0, needed
);
452 DrvGetPrinterData16((LPSTR
)name
, (LPSTR
)INT_PD_DEFAULT_DEVMODE
, &type
,
453 (LPBYTE
)pi
->Devmode
, needed
, &needed
);
456 if (OpenPrinterA (pi
->FriendlyName
, &hPrinter
, NULL
) == 0)
458 ERR ("OpenPrinterA failed with code %li\n", GetLastError ());
459 if (HeapFree (PSDRV_Heap
, 0, pi
->FriendlyName
) == 0)
460 WARN ("HeapFree failed with code %li\n", GetLastError ());
461 if (HeapFree (PSDRV_Heap
, 0, pi
->Devmode
) == 0)
462 WARN ("HeapFree failed with code %li\n", GetLastError ());
463 if (HeapFree (PSDRV_Heap
, 0, pi
) == 0)
464 WARN ("HeapFree failed with code %li\n", GetLastError ());
469 res
= GetPrinterDataA (hPrinter
, "PPD File", NULL
,
470 pi
->Devmode
->dmDrvPrivate
.ppdFileName
, 256, &needed
);
471 if (res
!= ERROR_SUCCESS
)
473 ERR ("Error %li getting PPD file name for printer '%s'\n", res
, name
);
474 if (ClosePrinter (hPrinter
) == 0)
475 WARN ("ClosePrinter failed with code %li\n", GetLastError ());
476 if (HeapFree(PSDRV_Heap
, 0, pi
->FriendlyName
) == 0)
477 WARN ("HeapFree failed with code %li\n", GetLastError ());
478 if (HeapFree(PSDRV_Heap
, 0, pi
->Devmode
) == 0)
479 WARN ("HeapFree failed with code %li\n", GetLastError ());
480 if (HeapFree(PSDRV_Heap
, 0, pi
) == 0)
481 WARN ("HeapFree failed with code %li\n", GetLastError ());
486 res
= GetPrinterDataA (hPrinter
, "Paper Size", NULL
, (LPBYTE
) &dwPaperSize
,
487 sizeof (DWORD
), &needed
);
488 if (res
== ERROR_SUCCESS
)
489 pi
->Devmode
->dmPublic
.u1
.s1
.dmPaperSize
= (SHORT
) dwPaperSize
;
490 else if (res
== ERROR_FILE_NOT_FOUND
)
491 TRACE ("No 'Paper Size' for printer '%s'\n", name
);
494 ERR ("GetPrinterDataA returned %li\n", res
);
495 if (ClosePrinter (hPrinter
) == 0)
496 WARN ("ClosePrinter failed with code %li\n", GetLastError ());
497 if (HeapFree(PSDRV_Heap
, 0, pi
->FriendlyName
) == 0)
498 WARN ("HeapFree failed with code %li\n", GetLastError ());
499 if (HeapFree(PSDRV_Heap
, 0, pi
->Devmode
) == 0)
500 WARN ("HeapFree failed with code %li\n", GetLastError ());
501 if (HeapFree(PSDRV_Heap
, 0, pi
) == 0)
502 WARN ("HeapFree failed with code %li\n", GetLastError ());
507 res
= EnumPrinterDataExA (hPrinter
, "PrinterDriverData\\FontSubTable", NULL
,
508 0, &needed
, &pi
->FontSubTableSize
);
509 if (res
== ERROR_SUCCESS
)
510 TRACE ("No 'FontSubTable' for printer '%s'\n", name
);
511 else if (res
== ERROR_MORE_DATA
)
513 pi
->FontSubTable
= HeapAlloc (PSDRV_Heap
, 0, needed
);
514 if (pi
->FontSubTable
== NULL
)
516 ERR ("Failed to allocate %li bytes from heap\n", needed
);
517 if (ClosePrinter (hPrinter
) == 0)
518 WARN ("ClosePrinter failed with code %li\n", GetLastError ());
519 if (HeapFree(PSDRV_Heap
, 0, pi
->FriendlyName
) == 0)
520 WARN ("HeapFree failed with code %li\n", GetLastError ());
521 if (HeapFree(PSDRV_Heap
, 0, pi
->Devmode
) == 0)
522 WARN ("HeapFree failed with code %li\n", GetLastError ());
523 if (HeapFree(PSDRV_Heap
, 0, pi
) == 0)
524 WARN ("HeapFree failed with code %li\n", GetLastError ());
529 res
= EnumPrinterDataExA (hPrinter
, "PrinterDriverData\\FontSubTable",
530 (LPBYTE
) pi
->FontSubTable
, needed
, &needed
,
531 &pi
->FontSubTableSize
);
532 if (res
!= ERROR_SUCCESS
)
534 ERR ("EnumPrinterDataExA returned %li\n", res
);
535 if (ClosePrinter (hPrinter
) == 0)
536 WARN ("ClosePrinter failed with code %li\n", GetLastError ());
537 if (HeapFree (PSDRV_Heap
, 0, pi
->FontSubTable
) == 0)
538 WARN ("HeapFree failed with code %li\n", GetLastError ());
539 if (HeapFree(PSDRV_Heap
, 0, pi
->FriendlyName
) == 0)
540 WARN ("HeapFree failed with code %li\n", GetLastError ());
541 if (HeapFree(PSDRV_Heap
, 0, pi
->Devmode
) == 0)
542 WARN ("HeapFree failed with code %li\n", GetLastError ());
543 if (HeapFree(PSDRV_Heap
, 0, pi
) == 0)
544 WARN ("HeapFree failed with code %li\n", GetLastError ());
549 else /* error in 1st call to EnumPrinterDataExA */
551 ERR ("EnumPrinterDataExA returned %li\n", res
);
552 if (ClosePrinter (hPrinter
) == 0)
553 WARN ("ClosePrinter failed with code %li\n", GetLastError ());
554 if (HeapFree(PSDRV_Heap
, 0, pi
->FriendlyName
) == 0)
555 WARN ("HeapFree failed with code %li\n", GetLastError ());
556 if (HeapFree(PSDRV_Heap
, 0, pi
->Devmode
) == 0)
557 WARN ("HeapFree failed with code %li\n", GetLastError ());
558 if (HeapFree(PSDRV_Heap
, 0, pi
) == 0)
559 WARN ("HeapFree failed with code %li\n", GetLastError ());
564 if (ClosePrinter (hPrinter
) == 0)
566 ERR ("ClosePrinter failed with code %li\n", GetLastError ());
567 if (ClosePrinter (hPrinter
) == 0)
568 WARN ("ClosePrinter failed with code %li\n", GetLastError ());
569 if (HeapFree (PSDRV_Heap
, 0, pi
->FontSubTable
) == 0)
570 WARN ("HeapFree failed with code %li\n", GetLastError ());
571 if (HeapFree(PSDRV_Heap
, 0, pi
->FriendlyName
) == 0)
572 WARN ("HeapFree failed with code %li\n", GetLastError ());
573 if (HeapFree(PSDRV_Heap
, 0, pi
->Devmode
) == 0)
574 WARN ("HeapFree failed with code %li\n", GetLastError ());
575 if (HeapFree(PSDRV_Heap
, 0, pi
) == 0)
576 WARN ("HeapFree failed with code %li\n", GetLastError ());
581 pi
->ppd
= PSDRV_ParsePPD(pi
->Devmode
->dmDrvPrivate
.ppdFileName
);
583 HeapFree(PSDRV_Heap
, 0, pi
->FontSubTable
);
584 HeapFree(PSDRV_Heap
, 0, pi
->FriendlyName
);
585 HeapFree(PSDRV_Heap
, 0, pi
->Devmode
);
586 HeapFree(PSDRV_Heap
, 0, pi
);
588 MESSAGE("Couldn't find PPD file '%s', expect a crash now!\n",
589 pi
->Devmode
->dmDrvPrivate
.ppdFileName
);
596 for(font
= pi
->ppd
->InstalledFonts
; font
; font
= font
->next
) {
597 afm
= PSDRV_FindAFMinList(PSDRV_AFMFontList
, font
->Name
);
600 "Couldn't find AFM file for installed printer font '%s' - ignoring\n",
603 PSDRV_AddAFMtoList(&pi
->Fonts
, afm
);