2 * PostScript driver Type1 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
22 #include "wine/port.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(psdrv
);
42 DWORD glyph_sent_size
;
47 #define GLYPH_SENT_INC 128
49 /* Type 1 font commands */
60 TYPE1
*T1_download_header(PSDRV_PDEVICE
*physDev
, char *ps_name
, RECT
*bbox
, UINT emsize
)
65 char dict
[] = /* name, emsquare, fontbbox */
67 " /FontName /%s def\n"
68 " /Encoding 256 array 0 1 255{1 index exch /.notdef put} for def\n"
70 " /FontMatrix [1 %d div 0 0 1 %d div 0 0] def\n"
71 " /FontBBox [%d %d %d %d] def\n"
73 " /Private 7 dict begin\n"
74 " /RD {string currentfile exch readhexstring pop} def\n"
77 " /MinFeature {16 16} def\n"
78 " /BlueValues [] def\n"
79 " /password 5839 def\n"
81 " currentdict end def\n"
82 " currentdict dup /Private get begin\n"
83 " /CharStrings 256 dict begin\n"
84 " /.notdef 4 RD 8b8b0d0e ND\n"
85 " currentdict end put\n"
87 "currentdict end dup /FontName get exch definefont pop\n";
89 t1
= HeapAlloc(GetProcessHeap(), 0, sizeof(*t1
));
92 t1
->glyph_sent_size
= GLYPH_SENT_INC
;
93 t1
->glyph_sent
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
95 sizeof(*(t1
->glyph_sent
)));
97 buf
= HeapAlloc(GetProcessHeap(), 0, sizeof(dict
) + strlen(ps_name
) +
100 sprintf(buf
, dict
, ps_name
, t1
->emsize
, t1
->emsize
,
101 bbox
->left
, bbox
->bottom
, bbox
->right
, bbox
->top
);
103 PSDRV_WriteSpool(physDev
, buf
, strlen(buf
));
105 HeapFree(GetProcessHeap(), 0, buf
);
115 static STR
*str_init(int sz
)
117 STR
*str
= HeapAlloc(GetProcessHeap(), 0, sizeof(*str
));
119 str
->str
= HeapAlloc(GetProcessHeap(), 0, str
->max_len
);
124 static void str_free(STR
*str
)
126 HeapFree(GetProcessHeap(), 0, str
->str
);
127 HeapFree(GetProcessHeap(), 0, str
);
130 static void str_add_byte(STR
*str
, BYTE b
)
132 if(str
->len
== str
->max_len
) {
134 str
->str
= HeapReAlloc(GetProcessHeap(), 0, str
->str
, str
->max_len
);
136 str
->str
[str
->len
++] = b
;
139 static void str_add_num(STR
*str
, int num
)
141 if(num
<= 107 && num
>= -107)
142 str_add_byte(str
, num
+ 139);
143 else if(num
>= 108 && num
<= 1131) {
144 str_add_byte(str
, ((num
- 108) >> 8) + 247);
145 str_add_byte(str
, (num
- 108) & 0xff);
146 } else if(num
<= -108 && num
>= -1131) {
148 str_add_byte(str
, ((num
- 108) >> 8) + 251);
149 str_add_byte(str
, (num
- 108) & 0xff);
151 str_add_byte(str
, 0xff);
152 str_add_byte(str
, (num
>> 24) & 0xff);
153 str_add_byte(str
, (num
>> 16) & 0xff);
154 str_add_byte(str
, (num
>> 8) & 0xff);
155 str_add_byte(str
, (num
& 0xff));
159 static void str_add_point(STR
*str
, POINTFX
*pt
, POINT
*curpos
)
162 newpos
.x
= pt
->x
.value
+ ((pt
->x
.fract
>> 15) & 0x1);
163 newpos
.y
= pt
->y
.value
+ ((pt
->y
.fract
>> 15) & 0x1);
165 str_add_num(str
, newpos
.x
- curpos
->x
);
166 str_add_num(str
, newpos
.y
- curpos
->y
);
170 static void str_add_cmd(STR
*str
, enum t1_cmds cmd
)
172 str_add_byte(str
, (BYTE
)cmd
);
175 static int str_get_bytes(STR
*str
, BYTE
**b
)
181 BOOL
T1_download_glyph(PSDRV_PDEVICE
*physDev
, DOWNLOAD
*pdl
, DWORD index
,
189 HFONT old_font
, unscaled_font
;
193 TTPOLYGONHEADER
*pph
;
198 char glyph_def_begin
[] =
200 "/Private get begin\n"
201 "/CharStrings get begin\n"
203 char glyph_def_end
[] =
207 TRACE("%ld %s\n", index
, glyph_name
);
208 assert(pdl
->type
== Type1
);
209 t1
= pdl
->typeinfo
.Type1
;
211 if(index
< t1
->glyph_sent_size
) {
212 if(t1
->glyph_sent
[index
])
215 t1
->glyph_sent_size
= (index
/ GLYPH_SENT_INC
+ 1) * GLYPH_SENT_INC
;
216 t1
->glyph_sent
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
218 t1
->glyph_sent_size
* sizeof(*(t1
->glyph_sent
)));
221 GetObjectW(GetCurrentObject(physDev
->hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
222 rc
.left
= rc
.right
= rc
.bottom
= 0;
224 DPtoLP(physDev
->hdc
, (POINT
*)&rc
, 2);
225 lf
.lfHeight
= -abs(rc
.top
- rc
.bottom
);
226 lf
.lfOrientation
= lf
.lfEscapement
= 0;
227 unscaled_font
= CreateFontIndirectW(&lf
);
228 old_font
= SelectObject(physDev
->hdc
, unscaled_font
);
229 len
= GetGlyphOutlineW(physDev
->hdc
, index
, GGO_GLYPH_INDEX
| GGO_BEZIER
,
231 if(len
== GDI_ERROR
) return FALSE
;
232 glyph_buf
= HeapAlloc(GetProcessHeap(), 0, len
);
233 GetGlyphOutlineW(physDev
->hdc
, index
, GGO_GLYPH_INDEX
| GGO_BEZIER
,
234 &gm
, len
, glyph_buf
, NULL
);
236 SelectObject(physDev
->hdc
, old_font
);
237 DeleteObject(unscaled_font
);
239 charstring
= str_init(100);
241 curpos
.x
= gm
.gmptGlyphOrigin
.x
;
244 str_add_num(charstring
, curpos
.x
);
245 str_add_num(charstring
, gm
.gmCellIncX
);
246 str_add_cmd(charstring
, hsbw
);
248 pph
= (TTPOLYGONHEADER
*)glyph_buf
;
249 while((char*)pph
< glyph_buf
+ len
) {
250 TRACE("contour len %ld\n", pph
->cb
);
251 ppc
= (TTPOLYCURVE
*)((char*)pph
+ sizeof(*pph
));
253 str_add_point(charstring
, &pph
->pfxStart
, &curpos
);
254 str_add_cmd(charstring
, rmoveto
);
256 while((char*)ppc
< (char*)pph
+ pph
->cb
) {
257 TRACE("line type %d cpfx = %d\n", ppc
->wType
, ppc
->cpfx
);
260 for(i
= 0; i
< ppc
->cpfx
; i
++) {
261 str_add_point(charstring
, ppc
->apfx
+ i
, &curpos
);
262 str_add_cmd(charstring
, rlineto
);
265 case TT_PRIM_CSPLINE
:
266 for(i
= 0; i
< ppc
->cpfx
/3; i
++) {
267 str_add_point(charstring
, ppc
->apfx
+ 3 * i
, &curpos
);
268 str_add_point(charstring
, ppc
->apfx
+ 3 * i
+ 1, &curpos
);
269 str_add_point(charstring
, ppc
->apfx
+ 3 * i
+ 2, &curpos
);
270 str_add_cmd(charstring
, rrcurveto
);
274 ERR("curve type = %d\n", ppc
->wType
);
277 ppc
= (TTPOLYCURVE
*)((char*)ppc
+ sizeof(*ppc
) +
278 (ppc
->cpfx
- 1) * sizeof(POINTFX
));
280 str_add_cmd(charstring
, closepath
);
281 pph
= (TTPOLYGONHEADER
*)((char*)pph
+ pph
->cb
);
283 str_add_cmd(charstring
, endchar
);
285 buf
= HeapAlloc(GetProcessHeap(), 0, sizeof(glyph_def_begin
) +
286 strlen(pdl
->ps_name
) + strlen(glyph_name
) + 100);
288 sprintf(buf
, "%%%%glyph %04lx\n", index
);
289 PSDRV_WriteSpool(physDev
, buf
, strlen(buf
));
291 len
= str_get_bytes(charstring
, &bytes
);
292 sprintf(buf
, glyph_def_begin
, pdl
->ps_name
, glyph_name
, len
);
293 PSDRV_WriteSpool(physDev
, buf
, strlen(buf
));
294 PSDRV_WriteBytes(physDev
, bytes
, len
);
295 sprintf(buf
, glyph_def_end
);
296 PSDRV_WriteSpool(physDev
, buf
, strlen(buf
));
297 str_free(charstring
);
299 t1
->glyph_sent
[index
] = TRUE
;
300 HeapFree(GetProcessHeap(), 0, glyph_buf
);
301 HeapFree(GetProcessHeap(), 0, buf
);
305 void T1_free(TYPE1
*t1
)
307 HeapFree(GetProcessHeap(), 0, t1
->glyph_sent
);
308 HeapFree(GetProcessHeap(), 0, t1
);