mstask: Implement ITask::DeleteTrigger().
[wine.git] / dlls / wineps.drv / download.c
blobdc77cf117039fe11055cda6c630f02d2eb626a45
1 /*
2 * PostScript driver downloadable font functions
4 * Copyright 2002 Huw D M Davies for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <string.h>
21 #include <stdlib.h>
22 #include <assert.h>
23 #include <math.h>
24 #include <stdarg.h>
25 #include <stdio.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winnls.h"
32 #include "psdrv.h"
33 #include "data/agl.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
39 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
40 ( ( (DWORD)_x4 << 24 ) | \
41 ( (DWORD)_x3 << 16 ) | \
42 ( (DWORD)_x2 << 8 ) | \
43 (DWORD)_x1 )
45 #define GET_BE_WORD(ptr) MAKEWORD( ((BYTE *)(ptr))[1], ((BYTE *)(ptr))[0] )
46 #define GET_BE_DWORD(ptr) ((DWORD)MAKELONG( GET_BE_WORD(&((WORD *)(ptr))[1]), \
47 GET_BE_WORD(&((WORD *)(ptr))[0]) ))
49 /****************************************************************************
50 * get_download_name
52 static void get_download_name(PHYSDEV dev, LPOUTLINETEXTMETRICA potm, char **str, BOOL vertical)
54 static const char reserved_chars[] = " %/(){}[]<>\n\r\t\b\f";
55 static const char vertical_suffix[] = "_vert";
56 int len;
57 char *p;
58 DWORD size;
60 size = GetFontData(dev->hdc, MS_MAKE_TAG('n','a','m','e'), 0, NULL, 0);
61 if(size != 0 && size != GDI_ERROR)
63 BYTE *name = HeapAlloc(GetProcessHeap(), 0, size);
64 if(name)
66 USHORT count, i;
67 BYTE *strings;
68 struct
70 USHORT platform_id;
71 USHORT encoding_id;
72 USHORT language_id;
73 USHORT name_id;
74 USHORT length;
75 USHORT offset;
76 } *name_record;
78 GetFontData(dev->hdc, MS_MAKE_TAG('n','a','m','e'), 0, name, size);
79 count = GET_BE_WORD(name + 2);
80 strings = name + GET_BE_WORD(name + 4);
81 name_record = (typeof(name_record))(name + 6);
82 for(i = 0; i < count; i++, name_record++)
84 name_record->platform_id = GET_BE_WORD(&name_record->platform_id);
85 name_record->encoding_id = GET_BE_WORD(&name_record->encoding_id);
86 name_record->language_id = GET_BE_WORD(&name_record->language_id);
87 name_record->name_id = GET_BE_WORD(&name_record->name_id);
88 name_record->length = GET_BE_WORD(&name_record->length);
89 name_record->offset = GET_BE_WORD(&name_record->offset);
91 if(name_record->platform_id == 1 && name_record->encoding_id == 0 &&
92 name_record->language_id == 0 && name_record->name_id == 6)
94 TRACE("Got Mac PS name %s\n", debugstr_an((char*)strings + name_record->offset, name_record->length));
95 *str = HeapAlloc(GetProcessHeap(), 0, name_record->length + sizeof(vertical_suffix));
96 memcpy(*str, strings + name_record->offset, name_record->length);
97 *(*str + name_record->length) = '\0';
98 HeapFree(GetProcessHeap(), 0, name);
99 goto done;
101 if(name_record->platform_id == 3 && name_record->encoding_id == 1 &&
102 name_record->language_id == 0x409 && name_record->name_id == 6)
104 WCHAR *unicode = HeapAlloc(GetProcessHeap(), 0, name_record->length + 2);
105 DWORD len;
106 int c;
108 for(c = 0; c < name_record->length / 2; c++)
109 unicode[c] = GET_BE_WORD(strings + name_record->offset + c * 2);
110 unicode[c] = 0;
111 TRACE("Got Windows PS name %s\n", debugstr_w(unicode));
112 len = WideCharToMultiByte(1252, 0, unicode, -1, NULL, 0, NULL, NULL);
113 *str = HeapAlloc(GetProcessHeap(), 0, len + sizeof(vertical_suffix) - 1);
114 WideCharToMultiByte(1252, 0, unicode, -1, *str, len, NULL, NULL);
115 HeapFree(GetProcessHeap(), 0, unicode);
116 HeapFree(GetProcessHeap(), 0, name);
117 goto done;
120 TRACE("Unable to find PostScript name\n");
121 HeapFree(GetProcessHeap(), 0, name);
125 len = strlen((char*)potm + (ptrdiff_t)potm->otmpFaceName) + 1;
126 *str = HeapAlloc(GetProcessHeap(),0,len + sizeof(vertical_suffix) - 1);
127 strcpy(*str, (char*)potm + (ptrdiff_t)potm->otmpFaceName);
129 done:
130 for (p = *str; *p; p++) if (strchr( reserved_chars, *p )) *p = '_';
131 if (vertical)
132 strcat(*str,vertical_suffix);
135 /****************************************************************************
136 * is_font_downloaded
138 static DOWNLOAD *is_font_downloaded(PSDRV_PDEVICE *physDev, char *ps_name)
140 DOWNLOAD *pdl;
142 for(pdl = physDev->downloaded_fonts; pdl; pdl = pdl->next)
143 if(!strcmp(pdl->ps_name, ps_name))
144 break;
145 return pdl;
148 /****************************************************************************
149 * is_room_for_font
151 static BOOL is_room_for_font(PSDRV_PDEVICE *physDev)
153 DOWNLOAD *pdl;
154 int count = 0;
156 /* FIXME: should consider vm usage of each font and available printer memory.
157 For now we allow up to two fonts to be downloaded at a time */
158 for(pdl = physDev->downloaded_fonts; pdl; pdl = pdl->next)
159 count++;
161 if(count > 1)
162 return FALSE;
163 return TRUE;
166 /****************************************************************************
167 * get_bbox
169 * This retrieves the bounding box of the font in font units as well as
170 * the size of the emsquare. To avoid having to worry about mapping mode and
171 * the font size we'll get the data directly from the TrueType HEAD table rather
172 * than using GetOutlineTextMetrics.
174 static UINT get_bbox(HDC hdc, RECT *rc)
176 BYTE head[54]; /* the head table is 54 bytes long */
178 if(GetFontData(hdc, MS_MAKE_TAG('h','e','a','d'), 0, head, sizeof(head)) == GDI_ERROR)
180 ERR("Can't retrieve head table\n");
181 return 0;
183 if(rc)
185 rc->left = (signed short)GET_BE_WORD(head + 36); /* xMin */
186 rc->bottom = (signed short)GET_BE_WORD(head + 38); /* yMin */
187 rc->right = (signed short)GET_BE_WORD(head + 40); /* xMax */
188 rc->top = (signed short)GET_BE_WORD(head + 42); /* yMax */
190 return GET_BE_WORD(head + 18); /* unitsPerEm */
193 /****************************************************************************
194 * PSDRV_SelectDownloadFont
196 * Set up physDev->font for a downloadable font
199 BOOL PSDRV_SelectDownloadFont(PHYSDEV dev)
201 PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
203 physDev->font.fontloc = Download;
204 physDev->font.fontinfo.Download = NULL;
206 return TRUE;
209 static UINT calc_ppem_for_height(HDC hdc, LONG height)
211 BYTE os2[78]; /* size of version 0 table */
212 BYTE hhea[8]; /* just enough to get the ascender and descender */
213 LONG ascent = 0, descent = 0;
214 UINT emsize;
216 if(height < 0) return -height;
218 if(GetFontData(hdc, MS_MAKE_TAG('O','S','/','2'), 0, os2, sizeof(os2)) == sizeof(os2))
220 ascent = GET_BE_WORD(os2 + 74); /* usWinAscent */
221 descent = GET_BE_WORD(os2 + 76); /* usWinDescent */
224 if(ascent + descent == 0)
226 if(GetFontData(hdc, MS_MAKE_TAG('h','h','e','a'), 0, hhea, sizeof(hhea)) == sizeof(hhea))
228 ascent = (signed short)GET_BE_WORD(hhea + 4); /* Ascender */
229 descent = -(signed short)GET_BE_WORD(hhea + 6); /* Descender */
233 if(ascent + descent == 0) return height;
235 emsize = get_bbox(hdc, NULL);
237 return MulDiv(emsize, height, ascent + descent);
240 static inline float ps_round(float f)
242 return (f > 0) ? (f + 0.5) : (f - 0.5);
245 static BOOL is_fake_italic( HDC hdc )
247 TEXTMETRICW tm;
248 BYTE head[54]; /* the head table is 54 bytes long */
249 WORD mac_style;
251 GetTextMetricsW( hdc, &tm );
252 if (!tm.tmItalic) return FALSE;
254 if (GetFontData( hdc, MS_MAKE_TAG('h','e','a','d'), 0, head, sizeof(head) ) == GDI_ERROR)
255 return FALSE;
257 mac_style = GET_BE_WORD( head + 44 );
258 TRACE( "mac style %04x\n", mac_style );
259 return !(mac_style & 2);
262 /****************************************************************************
263 * PSDRV_WriteSetDownloadFont
265 * Write setfont for download font.
268 BOOL PSDRV_WriteSetDownloadFont(PHYSDEV dev, BOOL vertical)
270 PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
271 char *ps_name;
272 LPOUTLINETEXTMETRICA potm;
273 DWORD len = GetOutlineTextMetricsA(dev->hdc, 0, NULL);
274 DOWNLOAD *pdl;
275 LOGFONTW lf;
276 UINT ppem;
277 XFORM xform;
278 INT escapement;
280 assert(physDev->font.fontloc == Download);
282 if (!GetObjectW( GetCurrentObject(dev->hdc, OBJ_FONT), sizeof(lf), &lf ))
283 return FALSE;
285 potm = HeapAlloc(GetProcessHeap(), 0, len);
286 if (!potm)
287 return FALSE;
289 GetOutlineTextMetricsA(dev->hdc, len, potm);
291 get_download_name(dev, potm, &ps_name, vertical);
292 physDev->font.fontinfo.Download = is_font_downloaded(physDev, ps_name);
294 ppem = calc_ppem_for_height(dev->hdc, lf.lfHeight);
296 /* Retrieve the world -> device transform */
297 GetTransform(dev->hdc, 0x204, &xform);
299 if(GetGraphicsMode(dev->hdc) == GM_COMPATIBLE)
301 if (xform.eM22 < 0) physDev->font.escapement = -physDev->font.escapement;
302 xform.eM11 = xform.eM22 = fabs(xform.eM22);
303 xform.eM21 = xform.eM12 = 0;
306 physDev->font.size.xx = ps_round(ppem * xform.eM11);
307 physDev->font.size.xy = ps_round(ppem * xform.eM12);
308 physDev->font.size.yx = -ps_round(ppem * xform.eM21);
309 physDev->font.size.yy = -ps_round(ppem * xform.eM22);
311 physDev->font.underlineThickness = potm->otmsUnderscoreSize;
312 physDev->font.underlinePosition = potm->otmsUnderscorePosition;
313 physDev->font.strikeoutThickness = potm->otmsStrikeoutSize;
314 physDev->font.strikeoutPosition = potm->otmsStrikeoutPosition;
316 if(physDev->font.fontinfo.Download == NULL) {
317 RECT bbox;
318 UINT emsize = get_bbox(dev->hdc, &bbox);
320 if (!emsize) {
321 HeapFree(GetProcessHeap(), 0, ps_name);
322 HeapFree(GetProcessHeap(), 0, potm);
323 return FALSE;
325 if(!is_room_for_font(physDev))
326 PSDRV_EmptyDownloadList(dev, TRUE);
328 pdl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pdl));
329 pdl->ps_name = HeapAlloc(GetProcessHeap(), 0, strlen(ps_name)+1);
330 strcpy(pdl->ps_name, ps_name);
331 pdl->next = NULL;
333 if(physDev->pi->ppd->TTRasterizer == RO_Type42) {
334 pdl->typeinfo.Type42 = T42_download_header(dev, ps_name, &bbox, emsize);
335 pdl->type = Type42;
337 if(pdl->typeinfo.Type42 == NULL) {
338 pdl->typeinfo.Type1 = T1_download_header(dev, ps_name, &bbox, emsize);
339 pdl->type = Type1;
341 pdl->next = physDev->downloaded_fonts;
342 physDev->downloaded_fonts = pdl;
343 physDev->font.fontinfo.Download = pdl;
345 if(pdl->type == Type42) {
346 char g_name[MAX_G_NAME + 1];
347 get_glyph_name(dev->hdc, 0, g_name);
348 T42_download_glyph(dev, pdl, 0, g_name);
352 escapement = physDev->font.escapement;
353 if (vertical)
354 escapement += 900;
356 PSDRV_WriteSetFont(dev, ps_name, physDev->font.size, escapement,
357 is_fake_italic( dev->hdc ));
359 HeapFree(GetProcessHeap(), 0, ps_name);
360 HeapFree(GetProcessHeap(), 0, potm);
361 return TRUE;
364 static void get_standard_glyph_name(WORD index, char *name)
366 static const GLYPHNAME nonbreakingspace = { -1, "nonbreakingspace" };
367 static const GLYPHNAME nonmarkingreturn = { -1, "nonmarkingreturn" };
368 static const GLYPHNAME notdef = { -1, ".notdef" };
369 static const GLYPHNAME null = { -1, ".null" };
370 /* These PostScript Format 1 glyph names are stored by glyph index, do not reorder them. */
371 static const GLYPHNAME *glyph_table[] = {
372 &notdef,
373 &null,
374 &nonmarkingreturn,
375 GN_space,
376 GN_exclam,
377 GN_quotedbl,
378 GN_numbersign,
379 GN_dollar,
380 GN_percent,
381 GN_ampersand,
382 GN_quotesingle,
383 GN_parenleft,
384 GN_parenright,
385 GN_asterisk,
386 GN_plus,
387 GN_comma,
388 GN_hyphen,
389 GN_period,
390 GN_slash,
391 GN_zero,
392 GN_one,
393 GN_two,
394 GN_three,
395 GN_four,
396 GN_five,
397 GN_six,
398 GN_seven,
399 GN_eight,
400 GN_nine,
401 GN_colon,
402 GN_semicolon,
403 GN_less,
404 GN_equal,
405 GN_greater,
406 GN_question,
407 GN_at,
408 GN_A,
409 GN_B,
410 GN_C,
411 GN_D,
412 GN_E,
413 GN_F,
414 GN_G,
415 GN_H,
416 GN_I,
417 GN_J,
418 GN_K,
419 GN_L,
420 GN_M,
421 GN_N,
422 GN_O,
423 GN_P,
424 GN_Q,
425 GN_R,
426 GN_S,
427 GN_T,
428 GN_U,
429 GN_V,
430 GN_W,
431 GN_X,
432 GN_Y,
433 GN_Z,
434 GN_bracketleft,
435 GN_backslash,
436 GN_bracketright,
437 GN_asciicircum,
438 GN_underscore,
439 GN_grave,
440 GN_a,
441 GN_b,
442 GN_c,
443 GN_d,
444 GN_e,
445 GN_f,
446 GN_g,
447 GN_h,
448 GN_i,
449 GN_j,
450 GN_k,
451 GN_l,
452 GN_m,
453 GN_n,
454 GN_o,
455 GN_p,
456 GN_q,
457 GN_r,
458 GN_s,
459 GN_t,
460 GN_u,
461 GN_v,
462 GN_w,
463 GN_x,
464 GN_y,
465 GN_z,
466 GN_braceleft,
467 GN_bar,
468 GN_braceright,
469 GN_asciitilde,
470 GN_Adieresis,
471 GN_Aring,
472 GN_Ccedilla,
473 GN_Eacute,
474 GN_Ntilde,
475 GN_Odieresis,
476 GN_Udieresis,
477 GN_aacute,
478 GN_agrave,
479 GN_acircumflex,
480 GN_adieresis,
481 GN_atilde,
482 GN_aring,
483 GN_ccedilla,
484 GN_eacute,
485 GN_egrave,
486 GN_ecircumflex,
487 GN_edieresis,
488 GN_iacute,
489 GN_igrave,
490 GN_icircumflex,
491 GN_idieresis,
492 GN_ntilde,
493 GN_oacute,
494 GN_ograve,
495 GN_ocircumflex,
496 GN_odieresis,
497 GN_otilde,
498 GN_uacute,
499 GN_ugrave,
500 GN_ucircumflex,
501 GN_udieresis,
502 GN_dagger,
503 GN_degree,
504 GN_cent,
505 GN_sterling,
506 GN_section,
507 GN_bullet,
508 GN_paragraph,
509 GN_germandbls,
510 GN_registered,
511 GN_copyright,
512 GN_trademark,
513 GN_acute,
514 GN_dieresis,
515 GN_notequal,
516 GN_AE,
517 GN_Oslash,
518 GN_infinity,
519 GN_plusminus,
520 GN_lessequal,
521 GN_greaterequal,
522 GN_yen,
523 GN_mu,
524 GN_partialdiff,
525 GN_summation,
526 GN_product,
527 GN_pi,
528 GN_integral,
529 GN_ordfeminine,
530 GN_ordmasculine,
531 GN_Omega,
532 GN_ae,
533 GN_oslash,
534 GN_questiondown,
535 GN_exclamdown,
536 GN_logicalnot,
537 GN_radical,
538 GN_florin,
539 GN_approxequal,
540 GN_Delta,
541 GN_guillemotleft,
542 GN_guillemotright,
543 GN_ellipsis,
544 &nonbreakingspace,
545 GN_Agrave,
546 GN_Atilde,
547 GN_Otilde,
548 GN_OE,
549 GN_oe,
550 GN_endash,
551 GN_emdash,
552 GN_quotedblleft,
553 GN_quotedblright,
554 GN_quoteleft,
555 GN_quoteright,
556 GN_divide,
557 GN_lozenge,
558 GN_ydieresis,
559 GN_Ydieresis,
560 GN_fraction,
561 GN_currency,
562 GN_guilsinglleft,
563 GN_guilsinglright,
564 GN_fi,
565 GN_fl,
566 GN_daggerdbl,
567 GN_periodcentered,
568 GN_quotesinglbase,
569 GN_quotedblbase,
570 GN_perthousand,
571 GN_Acircumflex,
572 GN_Ecircumflex,
573 GN_Aacute,
574 GN_Edieresis,
575 GN_Egrave,
576 GN_Iacute,
577 GN_Icircumflex,
578 GN_Idieresis,
579 GN_Igrave,
580 GN_Oacute,
581 GN_Ocircumflex,
582 GN_apple,
583 GN_Ograve,
584 GN_Uacute,
585 GN_Ucircumflex,
586 GN_Ugrave,
587 GN_dotlessi,
588 GN_circumflex,
589 GN_tilde,
590 GN_macron,
591 GN_breve,
592 GN_dotaccent,
593 GN_ring,
594 GN_cedilla,
595 GN_hungarumlaut,
596 GN_ogonek,
597 GN_caron,
598 GN_Lslash,
599 GN_lslash,
600 GN_Scaron,
601 GN_scaron,
602 GN_Zcaron,
603 GN_zcaron,
604 GN_brokenbar,
605 GN_Eth,
606 GN_eth,
607 GN_Yacute,
608 GN_yacute,
609 GN_Thorn,
610 GN_thorn,
611 GN_minus,
612 GN_multiply,
613 GN_onesuperior,
614 GN_twosuperior,
615 GN_threesuperior,
616 GN_onehalf,
617 GN_onequarter,
618 GN_threequarters,
619 GN_franc,
620 GN_Gbreve,
621 GN_gbreve,
622 GN_Idotaccent,
623 GN_Scedilla,
624 GN_scedilla,
625 GN_Cacute,
626 GN_cacute,
627 GN_Ccaron,
628 GN_ccaron,
629 GN_dcroat
631 snprintf(name, MAX_G_NAME + 1, "%s", glyph_table[index]->sz);
634 static int get_post2_name_index(BYTE *post2header, DWORD size, WORD index)
636 USHORT numberOfGlyphs = GET_BE_WORD(post2header);
637 DWORD offset = (1 + index) * sizeof(USHORT);
639 if(offset + sizeof(USHORT) > size || index >= numberOfGlyphs)
641 FIXME("Index '%d' exceeds PostScript Format 2 table size (%d)\n", index, numberOfGlyphs);
642 return -1;
644 return GET_BE_WORD(post2header + offset);
647 static void get_post2_custom_glyph_name(BYTE *post2header, DWORD size, WORD index, char *name)
649 USHORT numberOfGlyphs = GET_BE_WORD(post2header);
650 int i, name_offset = (1 + numberOfGlyphs) * sizeof(USHORT);
651 BYTE name_length = 0;
653 for(i = 0; i <= index; i++)
655 name_offset += name_length;
656 if(name_offset + sizeof(BYTE) > size)
658 FIXME("Pascal name offset '%d' exceeds PostScript Format 2 table size (%d)\n",
659 name_offset + 1, size);
660 return;
662 name_length = (post2header + name_offset)[0];
663 if(name_offset + name_length > size)
665 FIXME("Pascal name offset '%d' exceeds PostScript Format 2 table size (%d)\n",
666 name_offset + name_length, size);
667 return;
669 name_offset += sizeof(BYTE);
671 name_length = min(name_length, MAX_G_NAME);
672 memcpy(name, post2header + name_offset, name_length);
673 name[name_length] = 0;
676 void get_glyph_name(HDC hdc, WORD index, char *name)
678 struct
680 DWORD format;
681 DWORD italicAngle;
682 SHORT underlinePosition;
683 SHORT underlineThickness;
684 DWORD isFixedPitch;
685 DWORD minMemType42;
686 DWORD maxMemType42;
687 DWORD minMemType1;
688 DWORD maxMemType1;
689 } *post_header;
690 BYTE *post = NULL;
691 DWORD size;
693 /* set a fallback name that is just 'g<index>' */
694 snprintf(name, MAX_G_NAME + 1, "g%04x", index);
696 /* attempt to obtain the glyph name from the 'post' table */
697 size = GetFontData(hdc, MS_MAKE_TAG('p','o','s','t'), 0, NULL, 0);
698 if(size < sizeof(*post_header) || size == GDI_ERROR)
699 return;
700 post = HeapAlloc(GetProcessHeap(), 0, size);
701 if(!post)
702 return;
703 size = GetFontData(hdc, MS_MAKE_TAG('p','o','s','t'), 0, post, size);
704 if(size < sizeof(*post_header) || size == GDI_ERROR)
705 goto cleanup;
706 post_header = (typeof(post_header))(post);
707 /* note: only interested in the format for obtaining glyph names */
708 post_header->format = GET_BE_DWORD(&post_header->format);
710 /* now that we know the format of the 'post' table we can get the glyph name */
711 if(post_header->format == MAKELONG(0, 1))
713 if(index < 258)
714 get_standard_glyph_name(index, name);
715 else
716 WARN("Font uses PostScript Format 1, but non-standard glyph (%d) requested.\n", index);
718 else if(post_header->format == MAKELONG(0, 2))
720 BYTE *post2header = post + sizeof(*post_header);
721 int glyphNameIndex;
723 size -= sizeof(*post_header);
724 if(size < sizeof(USHORT))
726 FIXME("PostScript Format 2 table is invalid (cannot fit header)\n");
727 goto cleanup;
729 glyphNameIndex = get_post2_name_index(post2header, size, index);
730 if(glyphNameIndex == -1)
731 goto cleanup; /* invalid index, use fallback name */
732 else if(glyphNameIndex < 258)
733 get_standard_glyph_name(glyphNameIndex, name);
734 else
735 get_post2_custom_glyph_name(post2header, size, glyphNameIndex - 258, name);
737 else
738 FIXME("PostScript Format %d.%d glyph names are currently unsupported.\n",
739 HIWORD(post_header->format), LOWORD(post_header->format));
741 cleanup:
742 HeapFree(GetProcessHeap(), 0, post);
745 /****************************************************************************
746 * PSDRV_WriteDownloadGlyphShow
748 * Download and write out a number of glyphs
751 BOOL PSDRV_WriteDownloadGlyphShow(PHYSDEV dev, const WORD *glyphs,
752 UINT count)
754 PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
755 UINT i;
756 char g_name[MAX_G_NAME + 1];
757 assert(physDev->font.fontloc == Download);
759 switch(physDev->font.fontinfo.Download->type) {
760 case Type42:
761 for(i = 0; i < count; i++) {
762 get_glyph_name(dev->hdc, glyphs[i], g_name);
763 T42_download_glyph(dev, physDev->font.fontinfo.Download, glyphs[i], g_name);
764 PSDRV_WriteGlyphShow(dev, g_name);
766 break;
768 case Type1:
769 for(i = 0; i < count; i++) {
770 get_glyph_name(dev->hdc, glyphs[i], g_name);
771 T1_download_glyph(dev, physDev->font.fontinfo.Download, glyphs[i], g_name);
772 PSDRV_WriteGlyphShow(dev, g_name);
774 break;
776 default:
777 ERR("Type = %d\n", physDev->font.fontinfo.Download->type);
778 assert(0);
780 return TRUE;
783 /****************************************************************************
784 * PSDRV_EmptyDownloadList
786 * Clear the list of downloaded fonts
789 BOOL PSDRV_EmptyDownloadList(PHYSDEV dev, BOOL write_undef)
791 PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
792 DOWNLOAD *pdl, *old;
793 static const char undef[] = "/%s findfont 40 scalefont setfont /%s undefinefont\n";
794 char buf[sizeof(undef) + 200];
795 const char *default_font = physDev->pi->ppd->DefaultFont ?
796 physDev->pi->ppd->DefaultFont : "Courier";
798 if(physDev->font.fontloc == Download) {
799 physDev->font.set = FALSE;
800 physDev->font.fontinfo.Download = NULL;
803 pdl = physDev->downloaded_fonts;
804 physDev->downloaded_fonts = NULL;
805 while(pdl) {
806 if(write_undef) {
807 sprintf(buf, undef, default_font, pdl->ps_name);
808 PSDRV_WriteSpool(dev, buf, strlen(buf));
811 switch(pdl->type) {
812 case Type42:
813 T42_free(pdl->typeinfo.Type42);
814 break;
816 case Type1:
817 T1_free(pdl->typeinfo.Type1);
818 break;
820 default:
821 ERR("Type = %d\n", pdl->type);
822 assert(0);
825 HeapFree(GetProcessHeap(), 0, pdl->ps_name);
826 old = pdl;
827 pdl = pdl->next;
828 HeapFree(GetProcessHeap(), 0, old);
830 return TRUE;