2 * PostScript driver Type42 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include "wine/debug.h"
33 #include "wine/port.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(psdrv
);
38 #define GET_BE_WORD(ptr) MAKEWORD( ((BYTE *)(ptr))[1], ((BYTE *)(ptr))[0] )
39 #define GET_BE_DWORD(ptr) ((DWORD)MAKELONG( GET_BE_WORD(&((WORD *)(ptr))[1]), \
40 GET_BE_WORD(&((WORD *)(ptr))[0]) ))
42 #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
43 ( ( (DWORD)_x4 << 24 ) | \
44 ( (DWORD)_x3 << 16 ) | \
45 ( (DWORD)_x2 << 8 ) | \
48 /* undef this to download the metrics in one go in the hmtx table.
49 Most printers seem unable to use incremental metrics unfortunately */
50 #define USE_SEPARATE_METRICS
51 #undef USE_SEPARATE_METRICS
60 const OTTable tables_templ
[] = {
61 { MS_MAKE_TAG('c','v','t',' '), 0, 0, NULL
, TRUE
},
62 { MS_MAKE_TAG('f','p','g','m'), 0, 0, NULL
, TRUE
},
63 { MS_MAKE_TAG('g','d','i','r'), 0, 0, NULL
, TRUE
},
64 { MS_MAKE_TAG('g','l','y','f'), 0, 0, NULL
, FALSE
},
65 { MS_MAKE_TAG('h','e','a','d'), 0, 0, NULL
, TRUE
},
66 { MS_MAKE_TAG('h','h','e','a'), 0, 0, NULL
, TRUE
},
67 #ifdef USE_SEPARATE_METRICS
68 { MS_MAKE_TAG('h','m','t','x'), 0, 0, NULL
, FALSE
},
70 { MS_MAKE_TAG('h','m','t','x'), 0, 0, NULL
, TRUE
},
72 { MS_MAKE_TAG('l','o','c','a'), 0, 0, NULL
, FALSE
},
73 { MS_MAKE_TAG('m','a','x','p'), 0, 0, NULL
, TRUE
},
74 { MS_MAKE_TAG('p','r','e','p'), 0, 0, NULL
, TRUE
},
79 OTTable tables
[sizeof(tables_templ
)/sizeof(tables_templ
[0])];
80 int glyf_tab
, loca_tab
, head_tab
; /* indices of glyf, loca and head tables */
82 DWORD glyph_sent_size
;
87 #define GLYPH_SENT_INC 128
89 #define FLIP_ORDER(x) \
90 ( ( ((x) & 0xff) << 24) | \
91 ( ((x) & 0xff00) << 8) | \
92 ( ((x) & 0xff0000) >> 8) | \
93 ( ((x) & 0xff000000) >> 24) )
96 /* Some flags for composite glyphs. See glyf table in OT spec */
97 #define ARG_1_AND_2_ARE_WORDS (1L << 0)
98 #define WE_HAVE_A_SCALE (1L << 3)
99 #define MORE_COMPONENTS (1L << 5)
100 #define WE_HAVE_AN_X_AND_Y_SCALE (1L << 6)
101 #define WE_HAVE_A_TWO_BY_TWO (1L << 7)
104 static BOOL
LoadTable(HDC hdc
, OTTable
*table
)
108 if(table
->MS_tag
== MS_MAKE_TAG('g','d','i','r')) return TRUE
;
109 table
->len
= GetFontData(hdc
, table
->MS_tag
, 0, NULL
, 0);
110 table
->data
= HeapAlloc(GetProcessHeap(), 0, (table
->len
+ 3) & ~3 );
111 memset(table
->data
+ ((table
->len
- 1) & ~3), 0, sizeof(DWORD
));
112 GetFontData(hdc
, table
->MS_tag
, 0, table
->data
, table
->len
);
114 for(i
= 0; i
< (table
->len
+ 3) / 4; i
++)
115 table
->check
+= FLIP_ORDER(*((DWORD
*)(table
->data
) + i
));
120 TYPE42
*T42_download_header(PSDRV_PDEVICE
*physDev
, LPOUTLINETEXTMETRICA potm
,
123 DWORD i
, j
, tablepos
;
124 WORD num_of_tables
= sizeof(tables_templ
) / sizeof(tables_templ
[0]) - 1;
125 WORD num_of_write_tables
= 0;
128 char start
[] = /* name, fontbbox */
130 " /FontName /%s def\n"
131 " /Encoding 256 array 0 1 255{1 index exch /.notdef put} for\n"
133 " /PaintType 0 def\n"
134 " /FontMatrix [1 0 0 1 0 0] def\n"
135 " /FontBBox [%f %f %f %f] def\n"
136 " /FontType 42 def\n"
137 " /CharStrings 256 dict begin\n"
139 " currentdict end def\n"
140 " /GlyphDirectory 256 dict def\n"
141 #ifdef USE_SEPARATE_METRICS
142 " /Metrics 256 dict def\n"
145 char TT_offset_table
[] = "<00010000%04x%04x%04x%04x\n";
146 char TT_table_dir_entry
[] = "%08lx%08lx%08lx%08lx\n";
147 char end
[] = "] def\n"
148 "currentdict end dup /FontName get exch definefont pop\n";
151 t42
= HeapAlloc(GetProcessHeap(), 0, sizeof(*t42
));
152 memcpy(t42
->tables
, tables_templ
, sizeof(tables_templ
));
153 t42
->loca_tab
= t42
->glyf_tab
= t42
->head_tab
= t42
->hmtx_tab
= -1;
154 t42
->emsize
= potm
->otmEMSquare
;
156 for(i
= 0; i
< num_of_tables
; i
++) {
157 LoadTable(physDev
->hdc
, t42
->tables
+ i
);
158 if(t42
->tables
[i
].len
> 0xffff && t42
->tables
[i
].write
) break;
159 if(t42
->tables
[i
].write
) num_of_write_tables
++;
160 if(t42
->tables
[i
].MS_tag
== MS_MAKE_TAG('l','o','c','a'))
162 else if(t42
->tables
[i
].MS_tag
== MS_MAKE_TAG('g','l','y','f'))
164 else if(t42
->tables
[i
].MS_tag
== MS_MAKE_TAG('h','e','a','d'))
166 else if(t42
->tables
[i
].MS_tag
== MS_MAKE_TAG('h','m','t','x'))
169 if(i
< num_of_tables
) {
170 TRACE("Table %ld has length %ld. Will use Type 1 font instead.\n", i
, t42
->tables
[i
].len
);
175 t42
->glyph_sent_size
= GLYPH_SENT_INC
;
176 t42
->glyph_sent
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
177 t42
->glyph_sent_size
*
178 sizeof(*(t42
->glyph_sent
)));
180 buf
= HeapAlloc(GetProcessHeap(), 0, sizeof(start
) + strlen(ps_name
) +
183 sprintf(buf
, start
, ps_name
,
184 (float)potm
->otmrcFontBox
.left
/ potm
->otmEMSquare
,
185 (float)potm
->otmrcFontBox
.bottom
/ potm
->otmEMSquare
,
186 (float)potm
->otmrcFontBox
.right
/ potm
->otmEMSquare
,
187 (float)potm
->otmrcFontBox
.top
/ potm
->otmEMSquare
);
189 PSDRV_WriteSpool(physDev
, buf
, strlen(buf
));
191 sprintf(buf
, TT_offset_table
, num_of_write_tables
,
192 num_of_write_tables
, num_of_write_tables
, num_of_write_tables
);
194 PSDRV_WriteSpool(physDev
, buf
, strlen(buf
));
196 tablepos
= 12 + num_of_write_tables
* 16;
197 for(i
= 0; i
< num_of_tables
; i
++) {
198 if(!t42
->tables
[i
].write
) continue;
199 sprintf(buf
, TT_table_dir_entry
, FLIP_ORDER(t42
->tables
[i
].MS_tag
),
200 t42
->tables
[i
].check
, t42
->tables
[i
].len
? tablepos
: 0,
202 PSDRV_WriteSpool(physDev
, buf
, strlen(buf
));
203 tablepos
+= ((t42
->tables
[i
].len
+ 3) & ~3);
205 PSDRV_WriteSpool(physDev
, ">\n", 2);
207 for(i
= 0; i
< num_of_tables
; i
++) {
208 if(t42
->tables
[i
].len
== 0 || !t42
->tables
[i
].write
) continue;
209 PSDRV_WriteSpool(physDev
, "<", 1);
210 for(j
= 0; j
< ((t42
->tables
[i
].len
+ 3) & ~3); j
++) {
211 sprintf(buf
, "%02x", t42
->tables
[i
].data
[j
]);
212 PSDRV_WriteSpool(physDev
, buf
, strlen(buf
));
213 if(j
% 16 == 15) PSDRV_WriteSpool(physDev
, "\n", 1);
215 PSDRV_WriteSpool(physDev
, ">\n", 2);
218 PSDRV_WriteSpool(physDev
, end
, sizeof(end
) - 1);
219 HeapFree(GetProcessHeap(), 0, buf
);
226 BOOL
T42_download_glyph(PSDRV_PDEVICE
*physDev
, DOWNLOAD
*pdl
, DWORD index
,
236 #ifdef USE_SEPARATE_METRICS
237 char glyph_with_Metrics_def
[] =
238 "/%s findfont exch 1 index /GlyphDirectory get\n"
242 "dup /CharStrings get\n"
252 "/%s findfont exch 1 index /GlyphDirectory get\n"
262 TRACE("%ld %s\n", index
, glyph_name
);
263 assert(pdl
->type
== Type42
);
264 t42
= pdl
->typeinfo
.Type42
;
266 if(index
< t42
->glyph_sent_size
) {
267 if(t42
->glyph_sent
[index
])
270 t42
->glyph_sent_size
= (index
/ GLYPH_SENT_INC
+ 1) * GLYPH_SENT_INC
;
271 t42
->glyph_sent
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
273 t42
->glyph_sent_size
* sizeof(*(t42
->glyph_sent
)));
276 buf
= HeapAlloc(GetProcessHeap(), 0, sizeof(glyph_def
) +
277 strlen(pdl
->ps_name
) + 100);
279 loca_format
= GET_BE_WORD(t42
->tables
[t42
->head_tab
].data
+ 50);
280 TRACE("loca_format = %d\n", loca_format
);
281 switch(loca_format
) {
283 start
= GET_BE_WORD(((WORD
*)t42
->tables
[t42
->loca_tab
].data
) + index
);
285 end
= GET_BE_WORD(((WORD
*)t42
->tables
[t42
->loca_tab
].data
) + index
+ 1);
289 start
= GET_BE_DWORD(((DWORD
*)t42
->tables
[t42
->loca_tab
].data
) + index
);
290 end
= GET_BE_DWORD(((DWORD
*)t42
->tables
[t42
->loca_tab
].data
) + index
+ 1);
293 ERR("Unknown loca_format %d\n", loca_format
);
296 TRACE("start = %lx end = %lx\n", start
, end
);
298 awidth
= GET_BE_WORD(t42
->tables
[t42
->hmtx_tab
].data
+ index
* 4);
299 lsb
= GET_BE_WORD(t42
->tables
[t42
->hmtx_tab
].data
+ index
* 4 + 2);
301 if(GET_BE_WORD(t42
->tables
[t42
->glyf_tab
].data
+ start
) == 0xffff) {
302 /* Composite glyph */
303 char *sg_start
= t42
->tables
[t42
->glyf_tab
].data
+ start
+ 10;
304 DWORD sg_flags
, sg_index
;
305 char sg_name
[MAX_G_NAME
+ 1];
308 sg_flags
= GET_BE_WORD(sg_start
);
309 sg_index
= GET_BE_WORD(sg_start
+ 2);
311 TRACE("Sending subglyph %04lx for glyph %04lx\n", sg_index
, index
);
312 get_glyph_name(physDev
->hdc
, sg_index
, sg_name
);
313 T42_download_glyph(physDev
, pdl
, sg_index
, sg_name
);
315 if(sg_flags
& ARG_1_AND_2_ARE_WORDS
)
319 if(sg_flags
& WE_HAVE_A_SCALE
)
321 else if(sg_flags
& WE_HAVE_AN_X_AND_Y_SCALE
)
323 else if(sg_flags
& WE_HAVE_A_TWO_BY_TWO
)
325 } while(sg_flags
& MORE_COMPONENTS
);
328 sprintf(buf
, "%%%%glyph %04lx\n", index
);
329 PSDRV_WriteSpool(physDev
, buf
, strlen(buf
));
330 PSDRV_WriteSpool(physDev
, "<", 1);
331 for(i
= start
; i
< end
; i
++) {
332 sprintf(buf
, "%02x", *(t42
->tables
[t42
->glyf_tab
].data
+ i
));
333 PSDRV_WriteSpool(physDev
, buf
, strlen(buf
));
334 if((i
- start
) % 16 == 15)
335 PSDRV_WriteSpool(physDev
, "\n", 1);
337 PSDRV_WriteSpool(physDev
, ">\n", 2);
338 #if USE_SEPARATE_METRICS
339 sprintf(buf
, glyph_with_Metrics_def
, pdl
->ps_name
, index
, glyph_name
, index
,
340 glyph_name
, (float)lsb
/ t42
->emsize
, (float)awidth
/ t42
->emsize
);
342 sprintf(buf
, glyph_def
, pdl
->ps_name
, index
, glyph_name
, index
);
344 PSDRV_WriteSpool(physDev
, buf
, strlen(buf
));
346 t42
->glyph_sent
[index
] = TRUE
;
347 HeapFree(GetProcessHeap(), 0, buf
);
351 void T42_free(TYPE42
*t42
)
354 for(table
= t42
->tables
; table
->MS_tag
; table
++)
355 if(table
->data
) HeapFree(GetProcessHeap(), 0, table
->data
);
356 if(t42
->glyph_sent
) HeapFree(GetProcessHeap(), 0, t42
->glyph_sent
);
357 HeapFree(GetProcessHeap(), 0, t42
);