Changed wsock32 to use the new iphlpapi for interface and route
[wine/wine64.git] / dlls / wineps / type42.c
blobf195a17b37e290eb1684ca464fe3a52b79428de7
1 /*
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
20 #include <string.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <assert.h>
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "wingdi.h"
28 #include "winspool.h"
30 #include "psdrv.h"
31 #include "wine/debug.h"
32 #include "config.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 ) | \
46 (DWORD)_x1 )
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
53 typedef struct {
54 DWORD MS_tag;
55 DWORD len, check;
56 BYTE *data;
57 BOOL write;
58 } OTTable;
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 },
69 #else
70 { MS_MAKE_TAG('h','m','t','x'), 0, 0, NULL, TRUE },
71 #endif
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 },
75 { 0, 0, 0, NULL, 0 }
78 struct tagTYPE42 {
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 */
81 int hmtx_tab;
82 DWORD glyph_sent_size;
83 BOOL *glyph_sent;
84 DWORD emsize;
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)
106 int i;
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);
113 table->check = 0;
114 for(i = 0; i < (table->len + 3) / 4; i++)
115 table->check += FLIP_ORDER(*((DWORD*)(table->data) + i));
116 return TRUE;
120 TYPE42 *T42_download_header(PSDRV_PDEVICE *physDev, LPOUTLINETEXTMETRICA potm,
121 char *ps_name)
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;
126 char *buf;
127 TYPE42 *t42;
128 char start[] = /* name, fontbbox */
129 "25 dict begin\n"
130 " /FontName /%s def\n"
131 " /Encoding 256 array 0 1 255{1 index exch /.notdef put} for\n"
132 " def\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"
138 " /.notdef 0 def\n"
139 " currentdict end def\n"
140 " /GlyphDirectory 256 dict def\n"
141 #ifdef USE_SEPARATE_METRICS
142 " /Metrics 256 dict def\n"
143 #endif
144 " /sfnts [\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'))
161 t42->loca_tab = i;
162 else if(t42->tables[i].MS_tag == MS_MAKE_TAG('g','l','y','f'))
163 t42->glyf_tab = i;
164 else if(t42->tables[i].MS_tag == MS_MAKE_TAG('h','e','a','d'))
165 t42->head_tab = i;
166 else if(t42->tables[i].MS_tag == MS_MAKE_TAG('h','m','t','x'))
167 t42->hmtx_tab = i;
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);
171 T42_free(t42);
172 return NULL;
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) +
181 100);
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,
201 t42->tables[i].len);
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);
220 return t42;
226 BOOL T42_download_glyph(PSDRV_PDEVICE *physDev, DOWNLOAD *pdl, DWORD index,
227 char *glyph_name)
229 DWORD start, end, i;
230 char *buf;
231 TYPE42 *t42;
232 WORD loca_format;
233 WORD awidth;
234 short lsb;
236 #ifdef USE_SEPARATE_METRICS
237 char glyph_with_Metrics_def[] =
238 "/%s findfont exch 1 index /GlyphDirectory get\n"
239 "begin\n"
240 " %d exch def\n"
241 "end\n"
242 "dup /CharStrings get\n"
243 "begin\n"
244 " /%s %d def\n"
245 "end\n"
246 "/Metrics get\n"
247 "begin\n"
248 " /%s [%f %f] def\n"
249 "end\n";
250 #else
251 char glyph_def[] =
252 "/%s findfont exch 1 index /GlyphDirectory get\n"
253 "begin\n"
254 " %d exch def\n"
255 "end\n"
256 "/CharStrings get\n"
257 "begin\n"
258 " /%s %d def\n"
259 "end\n";
260 #endif
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])
268 return TRUE;
269 } else {
270 t42->glyph_sent_size = (index / GLYPH_SENT_INC + 1) * GLYPH_SENT_INC;
271 t42->glyph_sent = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
272 t42->glyph_sent,
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) {
282 case 0:
283 start = GET_BE_WORD(((WORD*)t42->tables[t42->loca_tab].data) + index);
284 start <<= 1;
285 end = GET_BE_WORD(((WORD*)t42->tables[t42->loca_tab].data) + index + 1);
286 end <<= 1;
287 break;
288 case 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);
291 break;
292 default:
293 ERR("Unknown loca_format %d\n", loca_format);
294 return FALSE;
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];
307 do {
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);
314 sg_start += 4;
315 if(sg_flags & ARG_1_AND_2_ARE_WORDS)
316 sg_start += 4;
317 else
318 sg_start += 2;
319 if(sg_flags & WE_HAVE_A_SCALE)
320 sg_start += 2;
321 else if(sg_flags & WE_HAVE_AN_X_AND_Y_SCALE)
322 sg_start += 4;
323 else if(sg_flags & WE_HAVE_A_TWO_BY_TWO)
324 sg_start += 8;
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);
341 #else
342 sprintf(buf, glyph_def, pdl->ps_name, index, glyph_name, index);
343 #endif
344 PSDRV_WriteSpool(physDev, buf, strlen(buf));
346 t42->glyph_sent[index] = TRUE;
347 HeapFree(GetProcessHeap(), 0, buf);
348 return TRUE;
351 void T42_free(TYPE42 *t42)
353 OTTable *table;
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);
358 return;