For PostScript versions < 2.015 we need to explicitly allocate space for the 'glyf' array. To conserve VM, we only allow up to two fonts to be downloaded before reclaiming their VM.
diff --git a/dlls/wineps/type42.c b/dlls/wineps/type42.c index f195a17..afca1df 100644 --- a/dlls/wineps/type42.c +++ b/dlls/wineps/type42.c
@@ -45,11 +45,6 @@ ( (DWORD)_x2 << 8 ) | \ (DWORD)_x1 ) -/* undef this to download the metrics in one go in the hmtx table. - Most printers seem unable to use incremental metrics unfortunately */ -#define USE_SEPARATE_METRICS -#undef USE_SEPARATE_METRICS - typedef struct { DWORD MS_tag; DWORD len, check; @@ -64,12 +59,8 @@ { MS_MAKE_TAG('g','l','y','f'), 0, 0, NULL, FALSE }, { MS_MAKE_TAG('h','e','a','d'), 0, 0, NULL, TRUE }, { MS_MAKE_TAG('h','h','e','a'), 0, 0, NULL, TRUE }, -#ifdef USE_SEPARATE_METRICS - { MS_MAKE_TAG('h','m','t','x'), 0, 0, NULL, FALSE }, -#else { MS_MAKE_TAG('h','m','t','x'), 0, 0, NULL, TRUE }, -#endif - { MS_MAKE_TAG('l','o','c','a'), 0, 0, NULL, FALSE }, + { MS_MAKE_TAG('l','o','c','a'), 0, 0, NULL, TRUE }, { MS_MAKE_TAG('m','a','x','p'), 0, 0, NULL, TRUE }, { MS_MAKE_TAG('p','r','e','p'), 0, 0, NULL, TRUE }, { 0, 0, 0, NULL, 0 } @@ -78,10 +69,12 @@ struct tagTYPE42 { OTTable tables[sizeof(tables_templ)/sizeof(tables_templ[0])]; int glyf_tab, loca_tab, head_tab; /* indices of glyf, loca and head tables */ - int hmtx_tab; + int hmtx_tab, maxp_tab; + int num_of_written_tables; DWORD glyph_sent_size; BOOL *glyph_sent; DWORD emsize; + DWORD *glyf_blocks; }; #define GLYPH_SENT_INC 128 @@ -116,13 +109,33 @@ return TRUE; } +static BOOL get_glyf_pos(TYPE42 *t42, DWORD index, DWORD *start, DWORD *end) +{ + WORD loca_format = GET_BE_WORD(t42->tables[t42->head_tab].data + 50); + TRACE("loca_format = %d\n", loca_format); + switch(loca_format) { + case 0: + *start = GET_BE_WORD(((WORD*)t42->tables[t42->loca_tab].data) + index); + *start <<= 1; + *end = GET_BE_WORD(((WORD*)t42->tables[t42->loca_tab].data) + index + 1); + *end <<= 1; + break; + case 1: + *start = GET_BE_DWORD(((DWORD*)t42->tables[t42->loca_tab].data) + index); + *end = GET_BE_DWORD(((DWORD*)t42->tables[t42->loca_tab].data) + index + 1); + break; + default: + ERR("Unknown loca_format %d\n", loca_format); + return FALSE; + } + return TRUE; +} TYPE42 *T42_download_header(PSDRV_PDEVICE *physDev, LPOUTLINETEXTMETRICA potm, char *ps_name) { - DWORD i, j, tablepos; + DWORD i, j, tablepos, nb_blocks, glyf_off = 0, loca_off = 0, cur_off; WORD num_of_tables = sizeof(tables_templ) / sizeof(tables_templ[0]) - 1; - WORD num_of_write_tables = 0; char *buf; TYPE42 *t42; char start[] = /* name, fontbbox */ @@ -137,14 +150,13 @@ " /CharStrings 256 dict begin\n" " /.notdef 0 def\n" " currentdict end def\n" - " /GlyphDirectory 256 dict def\n" -#ifdef USE_SEPARATE_METRICS - " /Metrics 256 dict def\n" -#endif " /sfnts [\n"; char TT_offset_table[] = "<00010000%04x%04x%04x%04x\n"; char TT_table_dir_entry[] = "%08lx%08lx%08lx%08lx\n"; + char storage[] ="]\nhavetype42gdir{pop}{{string} forall}ifelse\n"; char end[] = "] def\n" + "havetype42gdir{/GlyphDirectory 256 dict def\n" + " sfnts 0 get dup %d (x) putinterval %d (x) putinterval}if\n" "currentdict end dup /FontName get exch definefont pop\n"; @@ -152,11 +164,12 @@ memcpy(t42->tables, tables_templ, sizeof(tables_templ)); t42->loca_tab = t42->glyf_tab = t42->head_tab = t42->hmtx_tab = -1; t42->emsize = potm->otmEMSquare; + t42->num_of_written_tables = 0; for(i = 0; i < num_of_tables; i++) { LoadTable(physDev->hdc, t42->tables + i); if(t42->tables[i].len > 0xffff && t42->tables[i].write) break; - if(t42->tables[i].write) num_of_write_tables++; + if(t42->tables[i].write) t42->num_of_written_tables++; if(t42->tables[i].MS_tag == MS_MAKE_TAG('l','o','c','a')) t42->loca_tab = i; else if(t42->tables[i].MS_tag == MS_MAKE_TAG('g','l','y','f')) @@ -165,6 +178,8 @@ t42->head_tab = i; else if(t42->tables[i].MS_tag == MS_MAKE_TAG('h','m','t','x')) t42->hmtx_tab = i; + else if(t42->tables[i].MS_tag == MS_MAKE_TAG('m','a','x','p')) + t42->maxp_tab = i; } if(i < num_of_tables) { TRACE("Table %ld has length %ld. Will use Type 1 font instead.\n", i, t42->tables[i].len); @@ -188,12 +203,14 @@ PSDRV_WriteSpool(physDev, buf, strlen(buf)); - sprintf(buf, TT_offset_table, num_of_write_tables, - num_of_write_tables, num_of_write_tables, num_of_write_tables); + t42->num_of_written_tables++; /* explicitly add glyf */ + sprintf(buf, TT_offset_table, t42->num_of_written_tables, + t42->num_of_written_tables, t42->num_of_written_tables, t42->num_of_written_tables); PSDRV_WriteSpool(physDev, buf, strlen(buf)); - tablepos = 12 + num_of_write_tables * 16; + tablepos = 12 + t42->num_of_written_tables * 16; + cur_off = 12; for(i = 0; i < num_of_tables; i++) { if(!t42->tables[i].write) continue; sprintf(buf, TT_table_dir_entry, FLIP_ORDER(t42->tables[i].MS_tag), @@ -201,8 +218,15 @@ t42->tables[i].len); PSDRV_WriteSpool(physDev, buf, strlen(buf)); tablepos += ((t42->tables[i].len + 3) & ~3); + if(t42->tables[i].MS_tag == MS_MAKE_TAG('l','o','c','a')) + loca_off = cur_off; + cur_off += 16; } - PSDRV_WriteSpool(physDev, ">\n", 2); + sprintf(buf, TT_table_dir_entry, FLIP_ORDER(t42->tables[t42->glyf_tab].MS_tag), + t42->tables[t42->glyf_tab].check, tablepos, t42->tables[t42->glyf_tab].len); + PSDRV_WriteSpool(physDev, buf, strlen(buf)); + PSDRV_WriteSpool(physDev, "00>\n", 4); /* add an extra byte for old PostScript rips */ + glyf_off = cur_off; for(i = 0; i < num_of_tables; i++) { if(t42->tables[i].len == 0 || !t42->tables[i].write) continue; @@ -212,10 +236,36 @@ PSDRV_WriteSpool(physDev, buf, strlen(buf)); if(j % 16 == 15) PSDRV_WriteSpool(physDev, "\n", 1); } - PSDRV_WriteSpool(physDev, ">\n", 2); + PSDRV_WriteSpool(physDev, "00>\n", 4); /* add an extra byte for old PostScript rips */ + } + + /* glyf_blocks is a 0 terminated list, holding the start offset of each block. For simplicity + glyf_blocks[0] is 0 */ + nb_blocks = 2; + t42->glyf_blocks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (nb_blocks + 1) * sizeof(DWORD)); + for(i = 0; i < GET_BE_WORD(t42->tables[t42->maxp_tab].data + 4); i++) { + DWORD start, end, size; + get_glyf_pos(t42, i, &start, &end); + size = end - t42->glyf_blocks[nb_blocks-2]; + if(size > 0x2000 && t42->glyf_blocks[nb_blocks-1] % 4 == 0) { + nb_blocks++; + t42->glyf_blocks = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + t42->glyf_blocks, (nb_blocks + 1) * sizeof(DWORD)); + } + t42->glyf_blocks[nb_blocks-1] = end; } - PSDRV_WriteSpool(physDev, end, sizeof(end) - 1); + PSDRV_WriteSpool(physDev, "[ ", 2); + for(i = 1; t42->glyf_blocks[i]; i++) { + sprintf(buf,"%ld ", t42->glyf_blocks[i] - t42->glyf_blocks[i-1] + 1); + /* again add one byte for old PostScript rips */ + PSDRV_WriteSpool(physDev, buf, strlen(buf)); + if(i % 8 == 0) + PSDRV_WriteSpool(physDev, "\n", 1); + } + PSDRV_WriteSpool(physDev, storage, sizeof(storage) - 1); + sprintf(buf, end, loca_off, glyf_off); + PSDRV_WriteSpool(physDev, buf, strlen(buf)); HeapFree(GetProcessHeap(), 0, buf); return t42; } @@ -229,35 +279,20 @@ DWORD start, end, i; char *buf; TYPE42 *t42; - WORD loca_format; WORD awidth; short lsb; -#ifdef USE_SEPARATE_METRICS - char glyph_with_Metrics_def[] = - "/%s findfont exch 1 index /GlyphDirectory get\n" - "begin\n" - " %d exch def\n" - "end\n" - "dup /CharStrings get\n" - "begin\n" - " /%s %d def\n" - "end\n" - "/Metrics get\n" - "begin\n" - " /%s [%f %f] def\n" - "end\n"; -#else char glyph_def[] = - "/%s findfont exch 1 index /GlyphDirectory get\n" - "begin\n" - " %d exch def\n" - "end\n" + "/%s findfont exch 1 index\n" + "havetype42gdir\n" + "{/GlyphDirectory get begin %d exch def end}\n" + "{/sfnts get 4 index get 3 index 2 index putinterval pop}\n" + "ifelse\n" "/CharStrings get\n" "begin\n" " /%s %d def\n" - "end\n"; -#endif + "end\n" + "pop pop\n"; TRACE("%ld %s\n", index, glyph_name); assert(pdl->type == Type42); @@ -276,23 +311,7 @@ buf = HeapAlloc(GetProcessHeap(), 0, sizeof(glyph_def) + strlen(pdl->ps_name) + 100); - loca_format = GET_BE_WORD(t42->tables[t42->head_tab].data + 50); - TRACE("loca_format = %d\n", loca_format); - switch(loca_format) { - case 0: - start = GET_BE_WORD(((WORD*)t42->tables[t42->loca_tab].data) + index); - start <<= 1; - end = GET_BE_WORD(((WORD*)t42->tables[t42->loca_tab].data) + index + 1); - end <<= 1; - break; - case 1: - start = GET_BE_DWORD(((DWORD*)t42->tables[t42->loca_tab].data) + index); - end = GET_BE_DWORD(((DWORD*)t42->tables[t42->loca_tab].data) + index + 1); - break; - default: - ERR("Unknown loca_format %d\n", loca_format); - return FALSE; - } + if(!get_glyf_pos(t42, index, &start, &end)) return FALSE; TRACE("start = %lx end = %lx\n", start, end); awidth = GET_BE_WORD(t42->tables[t42->hmtx_tab].data + index * 4); @@ -325,8 +344,13 @@ } while(sg_flags & MORE_COMPONENTS); } - sprintf(buf, "%%%%glyph %04lx\n", index); + for(i = 1; t42->glyf_blocks[i]; i++) + if(start < t42->glyf_blocks[i]) break; + /* we don't have a string for the gdir and glyf tables, but we do have a + string for the TT header. So the offset we need is tables - 2 */ + sprintf(buf, "%ld %ld\n", t42->num_of_written_tables - 2 + i, start - t42->glyf_blocks[i-1]); PSDRV_WriteSpool(physDev, buf, strlen(buf)); + PSDRV_WriteSpool(physDev, "<", 1); for(i = start; i < end; i++) { sprintf(buf, "%02x", *(t42->tables[t42->glyf_tab].data + i)); @@ -335,12 +359,7 @@ PSDRV_WriteSpool(physDev, "\n", 1); } PSDRV_WriteSpool(physDev, ">\n", 2); -#if USE_SEPARATE_METRICS - sprintf(buf, glyph_with_Metrics_def, pdl->ps_name, index, glyph_name, index, - glyph_name, (float)lsb / t42->emsize, (float)awidth / t42->emsize); -#else sprintf(buf, glyph_def, pdl->ps_name, index, glyph_name, index); -#endif PSDRV_WriteSpool(physDev, buf, strlen(buf)); t42->glyph_sent[index] = TRUE; @@ -354,6 +373,7 @@ for(table = t42->tables; table->MS_tag; table++) if(table->data) HeapFree(GetProcessHeap(), 0, table->data); if(t42->glyph_sent) HeapFree(GetProcessHeap(), 0, t42->glyph_sent); + if(t42->glyf_blocks) HeapFree(GetProcessHeap(), 0, t42->glyf_blocks); HeapFree(GetProcessHeap(), 0, t42); return; }