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"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(psdrv
);
40 DWORD glyph_sent_size
;
45 #define GLYPH_SENT_INC 128
47 /* Type 1 font commands */
58 TYPE1
*T1_download_header(PSDRV_PDEVICE
*physDev
, char *ps_name
, RECT
*bbox
, UINT emsize
)
63 char dict
[] = /* name, emsquare, fontbbox */
65 " /FontName /%s def\n"
66 " /Encoding 256 array 0 1 255{1 index exch /.notdef put} for def\n"
68 " /FontMatrix [1 %d div 0 0 1 %d div 0 0] def\n"
69 " /FontBBox [%d %d %d %d] def\n"
71 " /Private 7 dict begin\n"
72 " /RD {string currentfile exch readhexstring pop} def\n"
75 " /MinFeature {16 16} def\n"
76 " /BlueValues [] def\n"
77 " /password 5839 def\n"
79 " currentdict end def\n"
80 " currentdict dup /Private get begin\n"
81 " /CharStrings 256 dict begin\n"
82 " /.notdef 4 RD 8b8b0d0e ND\n"
83 " currentdict end put\n"
85 "currentdict end dup /FontName get exch definefont pop\n";
87 t1
= HeapAlloc(GetProcessHeap(), 0, sizeof(*t1
));
90 t1
->glyph_sent_size
= GLYPH_SENT_INC
;
91 t1
->glyph_sent
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
93 sizeof(*(t1
->glyph_sent
)));
95 buf
= HeapAlloc(GetProcessHeap(), 0, sizeof(dict
) + strlen(ps_name
) +
98 sprintf(buf
, dict
, ps_name
, t1
->emsize
, t1
->emsize
,
99 bbox
->left
, bbox
->bottom
, bbox
->right
, bbox
->top
);
101 PSDRV_WriteSpool(physDev
, buf
, strlen(buf
));
103 HeapFree(GetProcessHeap(), 0, buf
);
113 static STR
*str_init(int sz
)
115 STR
*str
= HeapAlloc(GetProcessHeap(), 0, sizeof(*str
));
117 str
->str
= HeapAlloc(GetProcessHeap(), 0, str
->max_len
);
122 static void str_free(STR
*str
)
124 HeapFree(GetProcessHeap(), 0, str
->str
);
125 HeapFree(GetProcessHeap(), 0, str
);
128 static void str_add_byte(STR
*str
, BYTE b
)
130 if(str
->len
== str
->max_len
) {
132 str
->str
= HeapReAlloc(GetProcessHeap(), 0, str
->str
, str
->max_len
);
134 str
->str
[str
->len
++] = b
;
137 static void str_add_num(STR
*str
, int num
)
139 if(num
<= 107 && num
>= -107)
140 str_add_byte(str
, num
+ 139);
141 else if(num
>= 108 && num
<= 1131) {
142 str_add_byte(str
, ((num
- 108) >> 8) + 247);
143 str_add_byte(str
, (num
- 108) & 0xff);
144 } else if(num
<= -108 && num
>= -1131) {
146 str_add_byte(str
, ((num
- 108) >> 8) + 251);
147 str_add_byte(str
, (num
- 108) & 0xff);
149 str_add_byte(str
, 0xff);
150 str_add_byte(str
, (num
>> 24) & 0xff);
151 str_add_byte(str
, (num
>> 16) & 0xff);
152 str_add_byte(str
, (num
>> 8) & 0xff);
153 str_add_byte(str
, (num
& 0xff));
157 static void str_add_point(STR
*str
, POINTFX
*pt
, POINT
*curpos
)
160 newpos
.x
= pt
->x
.value
+ ((pt
->x
.fract
>> 15) & 0x1);
161 newpos
.y
= pt
->y
.value
+ ((pt
->y
.fract
>> 15) & 0x1);
163 str_add_num(str
, newpos
.x
- curpos
->x
);
164 str_add_num(str
, newpos
.y
- curpos
->y
);
168 static void str_add_cmd(STR
*str
, enum t1_cmds cmd
)
170 str_add_byte(str
, (BYTE
)cmd
);
173 static int str_get_bytes(STR
*str
, BYTE
**b
)
179 BOOL
T1_download_glyph(PSDRV_PDEVICE
*physDev
, DOWNLOAD
*pdl
, DWORD index
,
187 HFONT old_font
, unscaled_font
;
191 TTPOLYGONHEADER
*pph
;
196 static const char glyph_def_begin
[] =
198 "/Private get begin\n"
199 "/CharStrings get begin\n"
201 static const char glyph_def_end
[] =
205 TRACE("%d %s\n", index
, glyph_name
);
206 assert(pdl
->type
== Type1
);
207 t1
= pdl
->typeinfo
.Type1
;
209 if(index
< t1
->glyph_sent_size
) {
210 if(t1
->glyph_sent
[index
])
213 t1
->glyph_sent_size
= (index
/ GLYPH_SENT_INC
+ 1) * GLYPH_SENT_INC
;
214 t1
->glyph_sent
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
216 t1
->glyph_sent_size
* sizeof(*(t1
->glyph_sent
)));
219 GetObjectW(GetCurrentObject(physDev
->hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
220 rc
.left
= rc
.right
= rc
.bottom
= 0;
222 DPtoLP(physDev
->hdc
, (POINT
*)&rc
, 2);
223 lf
.lfHeight
= -abs(rc
.top
- rc
.bottom
);
225 lf
.lfOrientation
= lf
.lfEscapement
= 0;
226 unscaled_font
= CreateFontIndirectW(&lf
);
227 old_font
= SelectObject(physDev
->hdc
, unscaled_font
);
228 len
= GetGlyphOutlineW(physDev
->hdc
, index
, GGO_GLYPH_INDEX
| GGO_BEZIER
,
230 if(len
== GDI_ERROR
) return FALSE
;
231 glyph_buf
= HeapAlloc(GetProcessHeap(), 0, len
);
232 GetGlyphOutlineW(physDev
->hdc
, index
, GGO_GLYPH_INDEX
| GGO_BEZIER
,
233 &gm
, len
, glyph_buf
, NULL
);
235 SelectObject(physDev
->hdc
, old_font
);
236 DeleteObject(unscaled_font
);
238 charstring
= str_init(100);
240 curpos
.x
= gm
.gmptGlyphOrigin
.x
;
243 str_add_num(charstring
, curpos
.x
);
244 str_add_num(charstring
, gm
.gmCellIncX
);
245 str_add_cmd(charstring
, hsbw
);
247 pph
= (TTPOLYGONHEADER
*)glyph_buf
;
248 while((char*)pph
< glyph_buf
+ len
) {
249 TRACE("contour len %d\n", pph
->cb
);
250 ppc
= (TTPOLYCURVE
*)((char*)pph
+ sizeof(*pph
));
252 str_add_point(charstring
, &pph
->pfxStart
, &curpos
);
253 str_add_cmd(charstring
, rmoveto
);
255 while((char*)ppc
< (char*)pph
+ pph
->cb
) {
256 TRACE("line type %d cpfx = %d\n", ppc
->wType
, ppc
->cpfx
);
259 for(i
= 0; i
< ppc
->cpfx
; i
++) {
260 str_add_point(charstring
, ppc
->apfx
+ i
, &curpos
);
261 str_add_cmd(charstring
, rlineto
);
264 case TT_PRIM_CSPLINE
:
265 for(i
= 0; i
< ppc
->cpfx
/3; i
++) {
266 str_add_point(charstring
, ppc
->apfx
+ 3 * i
, &curpos
);
267 str_add_point(charstring
, ppc
->apfx
+ 3 * i
+ 1, &curpos
);
268 str_add_point(charstring
, ppc
->apfx
+ 3 * i
+ 2, &curpos
);
269 str_add_cmd(charstring
, rrcurveto
);
273 ERR("curve type = %d\n", ppc
->wType
);
276 ppc
= (TTPOLYCURVE
*)((char*)ppc
+ sizeof(*ppc
) +
277 (ppc
->cpfx
- 1) * sizeof(POINTFX
));
279 str_add_cmd(charstring
, closepath
);
280 pph
= (TTPOLYGONHEADER
*)((char*)pph
+ pph
->cb
);
282 str_add_cmd(charstring
, endchar
);
284 buf
= HeapAlloc(GetProcessHeap(), 0, sizeof(glyph_def_begin
) +
285 strlen(pdl
->ps_name
) + strlen(glyph_name
) + 100);
287 sprintf(buf
, "%%%%glyph %04x\n", index
);
288 PSDRV_WriteSpool(physDev
, buf
, strlen(buf
));
290 len
= str_get_bytes(charstring
, &bytes
);
291 sprintf(buf
, glyph_def_begin
, pdl
->ps_name
, glyph_name
, len
);
292 PSDRV_WriteSpool(physDev
, buf
, strlen(buf
));
293 PSDRV_WriteBytes(physDev
, bytes
, len
);
294 sprintf(buf
, glyph_def_end
);
295 PSDRV_WriteSpool(physDev
, buf
, strlen(buf
));
296 str_free(charstring
);
298 t1
->glyph_sent
[index
] = TRUE
;
299 HeapFree(GetProcessHeap(), 0, glyph_buf
);
300 HeapFree(GetProcessHeap(), 0, buf
);
304 void T1_free(TYPE1
*t1
)
306 HeapFree(GetProcessHeap(), 0, t1
->glyph_sent
);
307 HeapFree(GetProcessHeap(), 0, t1
);