Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1993, 1994, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: gdevmsxf.c,v 1.8 2004/08/04 23:33:29 stefan Exp $ */
18
/* External font (xfont) implementation for Microsoft Windows. */
19
#include "ctype_.h"
20
#include "math_.h"
21
#include "memory_.h"
22
#include "string_.h"
23
#include "gdevmswn.h"
24
#include "gsutil.h"
25
#include "gxxfont.h"
26
#include "gsstruct.h"
27
 
28
/* Imported from gdevemap.c */
29
extern const byte gs_map_std_to_iso[256];
30
 
31
/* Declare the xfont procedures */
32
private xfont_proc_lookup_font(win_lookup_font);
33
private xfont_proc_char_xglyph(win_char_xglyph);
34
private xfont_proc_char_metrics(win_char_metrics);
35
private xfont_proc_render_char(win_render_char);
36
private xfont_proc_release(win_release);
37
private const gx_xfont_procs win_xfont_procs =
38
{
39
    win_lookup_font,
40
    win_char_xglyph,
41
    win_char_metrics,
42
    win_render_char,
43
    win_release
44
};
45
 
46
/* Return the xfont procedure record. */
47
const gx_xfont_procs *
48
win_get_xfont_procs(gx_device * dev)
49
{
50
    return &win_xfont_procs;
51
}
52
 
53
/* Define a Windows xfont. */
54
typedef struct win_xfont_s win_xfont;
55
struct win_xfont_s {
56
    gx_xfont_common common;
57
    LOGFONT lf;
58
    TEXTMETRIC tm;
59
    HFONT hFont;
60
    gx_device_win *dev;		/* for GetDC */
61
    int invert_y;
62
    int y_offset;
63
};
64
 
65
gs_private_st_dev_ptrs1(st_win_xfont, win_xfont, "win_xfont",
66
			win_xfont_enum_ptrs, win_xfont_reloc_ptrs, dev);
67
#define wxf ((win_xfont *)xf)
68
 
69
/* Forward references */
70
private HDC near win_get_dc(gx_device_win *);
71
private void near win_release_dc(gx_device_win *, HDC);
72
private int win_select_font(HDC, win_xfont *);
73
 
74
/* Map from PostScript to Windows character codes. */
75
/* (These tables were generated by winmaps.ps.) */
76
 
77
private const byte far_data gs_map_symbol_to_oem[256] =
78
{
79
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
80
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
81
    32, 33, 0, 35, 0, 37, 38, 0, 40, 41, 0, 43, 44, 0, 46, 47,
82
    48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
83
    0, 0, 0, 0, 0, 0, 231, 225, 0, 0, 0, 0, 0, 0, 0, 0,
84
    226, 232, 0, 227, 0, 0, 0, 233, 0, 0, 0, 91, 0, 93, 0, 95,
85
    0, 223, 224, 0, 234, 0, 236, 0, 0, 0, 0, 0, 0, 229, 0, 0,
86
    0, 0, 0, 228, 230, 0, 0, 0, 0, 0, 0, 123, 124, 125, 0, 0,
87
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
88
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
89
    0, 0, 0, 242, 0, 235, 0, 5, 4, 3, 6, 29, 27, 24, 26, 25,
90
    247, 240, 0, 241, 0, 0, 0, 7, 245, 0, 239, 0, 0, 0, 0, 0,
91
    0, 0, 0, 0, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 237, 0,
92
    0, 0, 0, 0, 0, 0, 250, 248, 169, 0, 0, 0, 0, 0, 0, 0,
93
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
94
    0, 0, 0, 243, 0, 244, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
95
};
96
 
97
private const byte far_data gs_map_iso_to_oem[256] =
98
{
99
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
100
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
101
    32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 0, 46, 47,
102
    48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
103
    64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
104
    80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
105
 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
106
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 0,
107
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
109
    32, 172, 154, 155, 0, 156, 0, 21, 0, 0, 165, 173, 169, 45, 0, 0,
110
    247, 240, 252, 0, 0, 229, 20, 249, 0, 0, 166, 174, 171, 170, 0, 167,
111
    0, 0, 0, 0, 141, 142, 145, 128, 0, 143, 0, 0, 0, 0, 0, 0,
112
    0, 164, 0, 0, 0, 0, 152, 0, 0, 0, 0, 0, 153, 0, 0, 0,
113
 133, 159, 131, 0, 132, 134, 144, 135, 138, 130, 136, 137, 140, 160, 0, 139,
114
    0, 163, 148, 161, 146, 0, 147, 245, 0, 150, 162, 149, 129, 0, 0, 151
115
};
116
 
117
/* Correlate PostScript font names with Windows font names. */
118
/* This table should be an external resource, like Fontmap, */
119
/* but that will have to wait till later. */
120
 
121
typedef struct font_entry_s {
122
    const char *key;
123
    const char *value;
124
    uint pitchAndFamily;
125
} font_entry;
126
 
127
private const font_entry font_names[] =
128
{
129
    {"Courier", "Courier New", FIXED_PITCH | FF_MODERN},
130
    {"Helvetica", "Arial", VARIABLE_PITCH | FF_SWISS},
131
    {"Helvetica", "Helv", VARIABLE_PITCH | FF_SWISS},
132
    {"Times", "Times New Roman", VARIABLE_PITCH | FF_ROMAN},
133
    {"Times", "Tms Rmn", VARIABLE_PITCH | FF_ROMAN}
134
};
135
 
136
/* Look up a font. */
137
private int /*bool */ map_logical_font(HDC, win_xfont *);
138
gx_xfont *
139
win_lookup_font(gx_device * dev, const byte * fname, uint len,
140
	    int encoding_index, const gs_uid * puid, const gs_matrix * pmat,
141
		gs_memory_t * mem)
142
{
143
    win_xfont f;
144
    win_xfont *wf;
145
    uint name_len = min(len, LF_FACESIZE - 1);
146
    const font_entry *pfe;
147
    HDC hdc;
148
 
149
    /* Only handle simple cases for now. */
150
    if (pmat->xy != 0 || pmat->yx != 0 || pmat->xx <= 0 ||
151
	fabs(fabs(pmat->yy) - pmat->xx) > 0.00002
152
	)
153
	return NULL;
154
    f.lf.lfHeight = (long)(pmat->xx * 1000);
155
    /* Don't trust Windows with very small sizes. */
156
    if (f.lf.lfHeight < 6 || f.lf.lfHeight >= 36)
157
	return NULL;
158
    f.lf.lfWidth = 0;
159
    f.lf.lfEscapement = 0;
160
    f.lf.lfOrientation = 0;
161
    f.lf.lfWeight =
162
	(string_match(fname, len, "*Bold*", 6, NULL) ?
163
	 FW_BOLD : FW_REGULAR);
164
    f.lf.lfItalic =
165
	string_match(fname, len, "*Italic*", 8, NULL) ||
166
	string_match(fname, len, "*Oblique*", 9, NULL);
167
    f.lf.lfUnderline = 0;
168
    f.lf.lfStrikeOut = 0;
169
    f.lf.lfCharSet =
170
	(encoding_index == 2 ? SYMBOL_CHARSET : ANSI_CHARSET);
171
    f.lf.lfOutPrecision = OUT_CHARACTER_PRECIS;
172
    f.lf.lfClipPrecision = CLIP_STROKE_PRECIS;
173
    f.lf.lfQuality = PROOF_QUALITY;
174
    f.hFont = 0;
175
    f.invert_y = pmat->yy >= 0;
176
    hdc = win_get_dc(wdev);
177
    if (hdc == NULL)
178
	return NULL;
179
    for (pfe = font_names; pfe != &font_names[countof(font_names)]; pfe++)
180
	if (!strncmp(pfe->key, fname, strlen(pfe->key))) {	/* Found a match. */
181
	    strcpy(f.lf.lfFaceName, pfe->value);
182
	    f.lf.lfPitchAndFamily = pfe->pitchAndFamily;
183
	    if (map_logical_font(hdc, &f))
184
		break;
185
	}
186
    if (f.hFont == 0) {		/* No matches in the table, try with the given name. */
187
	uint len;
188
 
189
	memcpy(f.lf.lfFaceName, fname, name_len);	/* default */
190
	for (len = 0; len < name_len; len++)
191
	    if (!isalnum(fname[len]))
192
		break;
193
	f.lf.lfFaceName[len] = 0;
194
	f.lf.lfPitchAndFamily = 0;	/* default */
195
	if (!map_logical_font(hdc, &f)) {
196
	    win_release_dc(wdev, hdc);
197
	    return NULL;
198
	}
199
    }
200
    GetTextMetrics(hdc, &f.tm);
201
    win_release_dc(wdev, hdc);
202
    f.y_offset = (!f.invert_y ? f.tm.tmAscent : f.tm.tmDescent);
203
    wf = gs_alloc_struct(mem, win_xfont, &st_win_xfont, "win_lookup_font");
204
    if (wf == 0) {
205
	DeleteObject(f.hFont);
206
	return NULL;
207
    }
208
    f.common.procs = &win_xfont_procs;
209
    f.dev = wdev;
210
    *wf = f;
211
    return (gx_xfont *) wf;
212
}
213
/* Map the logical font, and see if the result is satisfactory. */
214
private int			/*bool */
215
map_logical_font(HDC hdc, win_xfont * xf)
216
{
217
    char szFaceName[LF_FACESIZE];
218
 
219
    xf->hFont = CreateFontIndirect(&xf->lf);
220
    if (xf->hFont == 0)
221
	return 0;
222
    /* Check the face name */
223
    SelectObject(hdc, xf->hFont);
224
    GetTextFace(hdc, sizeof(szFaceName), szFaceName);
225
    if (!strncmp(xf->lf.lfFaceName, szFaceName, strlen(xf->lf.lfFaceName)))
226
	return 1;
227
    DeleteObject(xf->hFont);
228
    xf->hFont = 0;
229
    return 0;
230
}
231
 
232
/* Convert a character name or index to an xglyph code. */
233
gx_xglyph
234
win_char_xglyph(gx_xfont * xf, gs_char chr, int encoding_index,
235
		gs_glyph glyph, const gs_const_string *glyph_name)
236
{
237
    if (chr == gs_no_char)
238
	return gx_no_xglyph;	/* can't look up names yet */
239
    if (encoding_index == 0) {	/* Map StandardEncoding to ISOLatin1Encoding. */
240
	/* We lose a couple of characters that exist in both */
241
	/* StandardEncoding and the Windows OEM encoding but not in */
242
	/* the ISOLatin1Encoding; we won't worry about this */
243
	/* for now. */
244
	chr = gs_map_std_to_iso[chr];
245
	encoding_index = 1;
246
    }
247
    if (wxf->hFont == NULL) {	/* TEXTMETRICS not filled in yet */
248
	HDC hdc = win_get_dc(wxf->dev);
249
	int code;
250
 
251
	if (hdc == NULL)
252
	    return gx_no_xglyph;
253
	code = win_select_font(hdc, wxf);
254
	win_release_dc(wxf->dev, hdc);
255
	if (code < 0)
256
	    return gx_no_xglyph;
257
    }
258
    switch (wxf->tm.tmCharSet) {
259
	case ANSI_CHARSET:
260
	    if (encoding_index == 1 && (chr < 0x7f || chr > 0x9f ||
261
					chr == 0x91 || chr == 0x92)
262
		)
263
		break;
264
	    return gx_no_xglyph;
265
	case OEM_CHARSET:
266
	    switch (encoding_index) {
267
		case 1:	/* ISOLatin1 */
268
		    chr = gs_map_iso_to_oem[chr];
269
		    break;
270
		case 2:	/* Symbol */
271
		    chr = gs_map_symbol_to_oem[chr];
272
		    break;
273
		default:
274
		    return gx_no_xglyph;
275
	    }
276
	    break;
277
	default:
278
	    return gx_no_xglyph;
279
    }
280
    return (chr != 0 && chr >= wxf->tm.tmFirstChar &&
281
	    chr <= wxf->tm.tmLastChar ?
282
	    (gx_xglyph) chr : gx_no_xglyph);
283
}
284
 
285
/* Get the metrics for a character. */
286
int
287
win_char_metrics(gx_xfont * xf, gx_xglyph xg, int wmode,
288
		 gs_point * pwidth, gs_int_rect * pbbox)
289
{
290
    int code;
291
    HDC hdc;
292
    char chr = (char)xg;
293
 
294
    if (wmode != 0)
295
	return gs_error_undefined;
296
    hdc = win_get_dc(wxf->dev);
297
    if (hdc == NULL)
298
	return gs_error_limitcheck;
299
    if ((code = win_select_font(hdc, wxf)) < 0) {
300
	win_release_dc(wxf->dev, hdc);
301
	return code;
302
    }
303
#ifdef __WIN32__
304
    {
305
	SIZE sz;
306
 
307
	GetTextExtentPoint(hdc, &chr, 1, &sz);
308
	pwidth->x = sz.cx;
309
    }
310
#else
311
    {
312
	DWORD extent;
313
 
314
	extent = GetTextExtent(hdc, &chr, 1);
315
	pwidth->x = LOWORD(extent);
316
    }
317
#endif
318
    win_release_dc(wxf->dev, hdc);
319
    pwidth->y = 0;
320
    pbbox->p.x = 0;
321
    pbbox->q.x = (int)pwidth->x;
322
    if (wxf->invert_y) {
323
	pbbox->p.y = -wxf->tm.tmDescent;
324
	pbbox->q.y = wxf->tm.tmAscent;
325
    } else {
326
	pbbox->p.y = -wxf->tm.tmAscent;
327
	pbbox->q.y = wxf->tm.tmDescent;
328
    }
329
    return 0;
330
}
331
 
332
/* Render a character. */
333
int
334
win_render_char(gx_xfont * xf, gx_xglyph xg, gx_device * dev,
335
		int xo, int yo, gx_color_index color, int required)
336
{
337
    char chr = (char)xg;
338
    int code;
339
 
340
#ifdef NOTUSED			/* we don't own any windows so we can no longer do this */
341
    if (dev->dname == gs_mswin_device.dname &&
342
	wdev->hdctext != NULL && !wxf->invert_y
343
	) {			/* Display the character directly */
344
	HDC hdc = wdev->hdctext;
345
	PALETTEENTRY *pal = &wdev->limgpalette->palPalEntry[color];
346
 
347
	if ((code = win_select_font(hdc, wxf)) < 0)
348
	    return code;
349
	SetTextColor(hdc, RGB(pal->peRed, pal->peGreen, pal->peBlue));
350
	SetBkMode(hdc, TRANSPARENT);
351
	TextOut(hdc, xo, yo - wxf->y_offset, &chr, 1);
352
    } else
353
#endif
354
    if (!required)
355
	code = -1;		/* too hard */
356
    else {			/* Display on an intermediate bitmap, then copy the bits. */
357
	gs_point wxy;
358
	gs_int_rect bbox;
359
	int w, h, wbm, raster;
360
	gx_device_win *fdev = wxf->dev;
361
	HBITMAP hbm;
362
	byte *bits;
363
 
364
	code = (*xf->common.procs->char_metrics) (xf, xg, 0,
365
						  &wxy, &bbox);
366
	if (code < 0)
367
	    return code;
368
	w = bbox.q.x - bbox.p.x;
369
	h = bbox.q.y - bbox.p.y;
370
	wbm = ROUND_UP(w, align_bitmap_mod * 8);
371
	raster = wbm >> 3;
372
	bits = gs_malloc(dev->memory, h, raster, "win_render_char");
373
	if (bits == 0)
374
	    return gs_error_limitcheck;
375
	hbm = CreateBitmap(wbm, h, 1, 1, NULL);
376
	if (hbm == NULL) {
377
	    code = gs_error_limitcheck;
378
	} else {
379
	    HDC hdcwin = win_get_dc(fdev);
380
	    HDC hdcbit = CreateCompatibleDC(hdcwin);
381
 
382
	    dev_proc_copy_mono((*copy_mono)) =
383
		dev_proc(dev, copy_mono);
384
	    int y = yo - wxf->y_offset;
385
 
386
	    SetMapMode(hdcbit, GetMapMode(hdcwin));
387
	    win_select_font(hdcbit, wxf);
388
	    SelectObject(hdcbit, hbm);
389
	    PatBlt(hdcbit, 0, 0, wbm, h, rop_write_0s);
390
	    SetTextColor(hdcbit, 0xffffffL);	/* 1 */
391
	    SetBkMode(hdcbit, TRANSPARENT);
392
	    TextOut(hdcbit, 0, 0, &chr, 1);
393
	    GetBitmapBits(hbm, (DWORD) raster * h, bits);
394
	    DeleteDC(hdcbit);
395
	    win_release_dc(fdev, hdcwin);
396
	    DeleteObject(hbm);
397
	    if (!wxf->invert_y)
398
		code = (*copy_mono) (dev, bits, 0,
399
				     raster, gx_no_bitmap_id,
400
				     xo, y, w, h,
401
				     gx_no_color_index, color);
402
	    else {		/* Copy scan lines in reverse order. */
403
		int i;
404
 
405
		y += h - 1;
406
		for (i = 0; i < h; i++)
407
		    (*copy_mono) (dev, bits + i * raster,
408
				  0, raster, gx_no_bitmap_id,
409
				  xo, y - i, w, 1,
410
				  gx_no_color_index, color);
411
	    }
412
	}
413
	gs_free(dev->memory, bits, h, raster, "win_render_char");
414
    }
415
    return (code < 0 ? code : 0);
416
}
417
 
418
/* Release an xfont. */
419
private int
420
win_release(gx_xfont * xf, gs_memory_t * mem)
421
{
422
    if (wxf->hFont) {
423
	DeleteObject(wxf->hFont);
424
	wxf->hFont = 0;
425
    }
426
    if (mem != NULL)
427
	gs_free_object(mem, xf, "win_release");
428
    return 0;
429
}
430
 
431
/* ------ Font utilities ------ */
432
 
433
#undef wdev
434
#undef wxf
435
 
436
/* Get a DC for the font's device. */
437
private HDC near
438
win_get_dc(gx_device_win * wdev)
439
{
440
    /* Since we don't have a window, use the desktop */
441
    /* Don't draw into it! */
442
    return GetDC(HWND_DESKTOP);
443
}
444
 
445
/* Release a DC for the font's device. */
446
private void near
447
win_release_dc(gx_device_win * wdev, HDC hdc)
448
{
449
    ReleaseDC(HWND_DESKTOP, hdc);
450
}
451
 
452
/* Make an xfont current, possibly remapping it from a logical font. */
453
private int
454
win_select_font(HDC hdc, win_xfont * wxf)
455
{
456
    HFONT hFont = wxf->hFont;
457
 
458
    if (hFont == NULL) {	/* The font was released to free up resources. */
459
	/* Re-acquire it now. */
460
	wxf->hFont = CreateFontIndirect(&wxf->lf);
461
	if (wxf->hFont == NULL)
462
	    return gs_error_limitcheck;
463
    }
464
    SelectObject(hdc, wxf->hFont);
465
    return 0;
466
}