1 /* Copyright (C) 1994-2001 artofcode LLC. 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: gdevmacxf.c,v 1.6 2002/06/09 23:08:22 lpd Exp $ */
18 /* External font (xfont) implementation for Classic/Carbon MacOS. */
19
20 #include "gdevmac.h"
21 #include "gdevmacttf.h"
22
23
24 /* if set to 1, new carbon supported FontManager calls are used */
25 /* if set to 0, old FM calls that are "not recommended" for carbon are used */
26 /* for now, we'll set it to 0, as classic and carbon targets don't generate link errors, */
27 /* but the carbon target would be better built with this macro set to 1 */
28 /* In the case that it is set, the classic target should link in FontManager(Lib) */
29 #define USE_RECOMMENDED_CARBON_FONTMANAGER_CALLS 1
30
31
32
33 extern const byte gs_map_std_to_iso[256];
34 extern const byte gs_map_iso_to_std[256];
35
36
37 const byte gs_map_std_to_mac[256] =
38 {
39 /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
40 /* 0x */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41 /* 1x */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42 /* 2x */ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
43 /* 3x */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
44 /* 4x */ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
45 /* 5x */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
46 /* 6x */ 0xD4, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
47 /* 7x */ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
48 /* 8x */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 /* 9x */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 /* Ax */ 0x00, 0xC1, 0xA2, 0xA3, 0xDA, 0xB4, 0xC4, 0xA4, 0xDB, 0x27, 0xD2, 0xC7, 0xDC, 0xDD, 0xDE, 0xDF,
51 /* Bx */ 0x00, 0xD0, 0xA0, 0xE0, 0xE1, 0x00, 0xA6, 0xA5, 0xE2, 0xE3, 0xD3, 0xC8, 0xC9, 0xE4, 0x00, 0xC0,
52 /* Cx */ 0x00, 0x60, 0xAB, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xAC, 0x00, 0xFB, 0xFC, 0x00, 0xFD, 0xFE, 0xFF,
53 /* Dx */ 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54 /* Ex */ 0x00, 0xAE, 0x00, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAF, 0xCE, 0xBC, 0x00, 0x00, 0x00, 0x00,
55 /* Fx */ 0x00, 0xBE, 0x00, 0x00, 0x00, 0xF5, 0x00, 0x00, 0x00, 0xBF, 0xCF, 0xA7, 0x00, 0x00, 0x00, 0x00
56 };
57
58 const byte gs_map_mac_to_std[256] =
59 {
60 };
61
62 const byte gs_map_iso_to_mac[256] =
63 {
64 /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
65 /* 0x */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 /* 1x */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 /* 2x */ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
68 /* 3x */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
69 /* 4x */ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
70 /* 5x */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
71 /* 6x */ 0xD4, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
72 /* 7x */ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
73 /* 8x */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 /* 9x */ 0xF5, 0x60, 0xAB, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xAC, 0x00, 0xFB, 0xFC, 0x00, 0xFD, 0xFE, 0xFF,
75 /* Ax */ 0x00, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4, 0x00, 0xA4, 0xAC, 0xA9, 0xBB, 0xC7, 0xC2, 0x2D, 0xA8, 0xF8,
76 /* Bx */ 0xA1, 0xB1, 0x00, 0x00, 0xAB, 0xB5, 0xA6, 0xE1, 0xFC, 0x00, 0xBC, 0xC8, 0x00, 0x00, 0x00, 0xC0,
77 /* Cx */ 0xCB, 0xE7, 0xE5, 0xCC, 0x80, 0x81, 0xAE, 0x82, 0xE9, 0x83, 0xE6, 0xE8, 0xEA, 0xED, 0xEB, 0xEC,
78 /* Dx */ 0x00, 0x84, 0xF1, 0xEE, 0xEF, 0xCD, 0x85, 0x00, 0xAF, 0xF4, 0xF2, 0xF3, 0x86, 0x00, 0x00, 0xA7,
79 /* Ex */ 0x88, 0x87, 0x89, 0x8B, 0x8A, 0x8C, 0xBE, 0x8D, 0x8F, 0x8E, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,
80 /* Fx */ 0x00, 0x96, 0x98, 0x97, 0x99, 0x9B, 0x9A, 0xD6, 0xBF, 0x9D, 0x9C, 0x9E, 0x9F, 0x00, 0x00, 0xD8
81 };
82
83 const byte gs_map_mac_to_iso[256] =
84 {
85 };
86
87
88
89
90
91 /* The xfont procedure record. */
92
93 private const gx_xfont_procs mac_xfont_procs =
94 {
95 mac_lookup_font,
96 mac_char_xglyph,
97 mac_char_metrics,
98 mac_render_char,
99 mac_release
100 };
101
102
103 gs_private_st_dev_ptrs1(st_mac_xfont, mac_xfont, "mac_xfont", mac_xfont_enum_ptrs,
104 mac_xfont_reloc_ptrs, dev);
105
106
107
108
109
110 /* Return the xfont procedure record. */
111
112 const gx_xfont_procs *
mac_get_xfont_procs(gx_device * dev)113 mac_get_xfont_procs(gx_device *dev)
114 {
115 #pragma unused(dev)
116 return &mac_xfont_procs;
117 }
118
119
120
121 /* lookup_font */
122
123 private gx_xfont *
mac_lookup_font(gx_device * dev,const byte * fname,uint len,int encoding_index,const gs_uid * puid,const gs_matrix * pmat,gs_memory_t * mem)124 mac_lookup_font(gx_device *dev, const byte *fname, uint len,
125 int encoding_index, const gs_uid *puid,
126 const gs_matrix *pmat, gs_memory_t *mem)
127 {
128 #pragma unused(encoding_index,puid)
129 mac_xfont *macxf;
130
131 CGrafPort *currentPort;
132 int txFont, txSize, txMode;
133 StyleField txFace;
134 Fixed spExtra;
135
136 /* are XFonts enabled? */
137 if (((gx_device_macos*) dev)->useXFonts == false)
138 return NULL;
139
140 /* we can handle only requests from these encodings */
141 if (encoding_index != ENCODING_INDEX_MACROMAN && encoding_index != ENCODING_INDEX_ISOLATIN1 &&
142 encoding_index != ENCODING_INDEX_STANDARD)
143 return NULL;
144
145 /* Don't render very small fonts */
146 if (fabs(pmat->xx * 1000.0) < 3.0)
147 return NULL;
148
149 /* Only handle simple cases for now (no transformations). */
150 if (fabs(pmat->xy) > 0.0001 || fabs(pmat->yx) > 0.0001 || pmat->xx <= 0)
151 return NULL;
152
153 /* allocate memory for gx_xfont */
154 macxf = gs_alloc_struct(mem, mac_xfont, &st_mac_xfont, "mac_lookup_font");
155 if (macxf == NULL) {
156 return NULL;
157 }
158
159 /* set default values */
160 macxf->common.procs = &mac_xfont_procs;
161 macxf->dev = dev;
162
163 /* find the specified font */
164 mac_find_font_family(fname, len, &(macxf->fontID), &(macxf->fontFace));
165
166 /* no font found */
167 if (macxf->fontID == 0)
168 return NULL;
169
170 FMGetFontFamilyName(macxf->fontID, macxf->fontName);
171 macxf->fontSize = (short)(pmat->xx * 1000.0);
172 macxf->fontEncoding = mac_get_font_encoding(macxf);
173
174 /* we can handle only fonts with these encodings for now (all original Mac fonts have MacRoman encoding!) */
175 if (macxf->fontEncoding != ENCODING_INDEX_MACROMAN && macxf->fontEncoding != ENCODING_INDEX_ISOLATIN1)
176 return NULL;
177
178 /* get font metrics */
179
180 /* save current GrafPort's font information */
181 GetPort(&((GrafPort*) currentPort));
182 txFont = currentPort->txFont;
183 txSize = currentPort->txSize;
184 txFace = currentPort->txFace;
185 txMode = currentPort->txMode;
186 spExtra = currentPort->spExtra;
187
188 /* set values for measuring */
189 TextFont(macxf->fontID);
190 TextSize(macxf->fontSize);
191 TextFace(macxf->fontFace);
192 TextMode(srcOr);
193 SpaceExtra(0);
194
195 /* measure font */
196 FontMetrics(&(macxf->fontMetrics));
197
198 /* restore current GrafPort's font information */
199 currentPort->txFont = txFont;
200 currentPort->txSize = txSize;
201 currentPort->txFace = txFace;
202 currentPort->txMode = txMode;
203 currentPort->spExtra = spExtra;
204
205 return (gx_xfont*) macxf;
206 }
207
208
209
210 /* char_xglyph */
211
212 private gx_xglyph
mac_char_xglyph(gx_xfont * xf,gs_char chr,int encoding_index,gs_glyph glyph,const gs_const_string * glyph_name)213 mac_char_xglyph(gx_xfont *xf, gs_char chr, int encoding_index,
214 gs_glyph glyph, const gs_const_string *glyph_name)
215 {
216 #pragma unused(glyph_name,glyph)
217 mac_xfont * macxf = (mac_xfont*) xf;
218
219 /* can't look up names yet */
220 if (chr == gs_no_char)
221 return gx_no_xglyph;
222
223 if (macxf->fontEncoding == ENCODING_INDEX_MACROMAN) {
224 switch (encoding_index) {
225 case ENCODING_INDEX_MACROMAN: return chr;
226 case ENCODING_INDEX_STANDARD: return gs_map_std_to_mac[chr];
227 case ENCODING_INDEX_ISOLATIN1: return gs_map_iso_to_mac[chr];
228 }
229 } else if (macxf->fontEncoding == ENCODING_INDEX_ISOLATIN1) {
230 switch (encoding_index) {
231 case ENCODING_INDEX_MACROMAN: return gs_map_mac_to_iso[chr];
232 case ENCODING_INDEX_STANDARD: return gs_map_std_to_iso[chr];
233 case ENCODING_INDEX_ISOLATIN1: return chr;
234 }
235 }
236
237 return gx_no_xglyph;
238 }
239
240
241
242 /* char_metrics */
243
244 private int
mac_char_metrics(gx_xfont * xf,gx_xglyph xg,int wmode,gs_point * pwidth,gs_int_rect * pbbox)245 mac_char_metrics(gx_xfont *xf, gx_xglyph xg, int wmode,
246 gs_point *pwidth, gs_int_rect *pbbox)
247 {
248 #pragma unused(xg)
249 mac_xfont * macxf = (mac_xfont*) xf;
250
251 if (wmode != 0)
252 return gs_error_undefined;
253
254 pbbox->p.x = 0;
255 pbbox->q.x = Fix2Long(macxf->fontMetrics.widMax);
256 pbbox->p.y = -Fix2Long(macxf->fontMetrics.ascent);
257 pbbox->q.y = Fix2Long(macxf->fontMetrics.descent);
258 pwidth->x = pbbox->q.x;
259 pwidth->y = 0.0;
260
261 return 0;
262 }
263
264
265
266 /* render_char */
267
268 private int
mac_render_char(gx_xfont * xf,gx_xglyph xg,gx_device * dev,int xo,int yo,gx_color_index color,int required)269 mac_render_char(gx_xfont *xf, gx_xglyph xg, gx_device *dev,
270 int xo, int yo, gx_color_index color, int required)
271 {
272 #pragma unused(dev,required)
273 mac_xfont * macxf = (mac_xfont*) xf;
274 gx_device_macos * mdev = (gx_device_macos*) macxf->dev;
275
276 Str255 character;
277 int i, found;
278
279 CheckMem(10*1024, 100*1024);
280 ResetPage();
281
282 character[0] = 1;
283 character[1] = xg;
284
285 GSSetFgCol(macxf->dev, mdev->currPicPos, color);
286
287 found = 0;
288 for (i=0; i<mdev->numUsedFonts; i++)
289 if (mdev->usedFontIDs[i] == macxf->fontID) found = 1;
290
291 if (!found) {
292 mdev->usedFontIDs[mdev->numUsedFonts++] = macxf->fontID;
293 PICT_fontName(mdev->currPicPos, macxf->fontID, macxf->fontName);
294 }
295 if (mdev->lastFontID != macxf->fontID) {
296 PICT_TxFont(mdev->currPicPos, macxf->fontID);
297 mdev->lastFontID = macxf->fontID;
298 }
299 if (mdev->lastFontSize != macxf->fontSize) {
300 PICT_TxSize(mdev->currPicPos, macxf->fontSize);
301 mdev->lastFontSize = macxf->fontSize;
302 }
303 if (mdev->lastFontFace != macxf->fontFace) {
304 PICT_TxFace(mdev->currPicPos, macxf->fontFace);
305 mdev->lastFontFace = macxf->fontFace;
306 }
307 PICT_LongText(mdev->currPicPos, xo, yo, character);
308 PICT_OpEndPicGoOn(mdev->currPicPos);
309
310 return 0;
311 }
312
313
314
315 /* release */
316
317 private int
mac_release(gx_xfont * xf,gs_memory_t * mem)318 mac_release(gx_xfont *xf, gs_memory_t *mem)
319 {
320 if (mem != NULL)
321 gs_free_object(mem, xf, "mac_release");
322
323 return 0;
324 }
325
326
327
328 /* try to extract font family and style from name and find a suitable font */
329
330 private void
mac_find_font_family(ConstStringPtr fname,int len,FMFontFamily * fontID,FMFontStyle * fontFace)331 mac_find_font_family(ConstStringPtr fname, int len, FMFontFamily *fontID, FMFontStyle *fontFace)
332 {
333 char fontNameStr[512];
334 char *fontFamilyName;
335 char *fontStyleName;
336 int i;
337
338 *fontID = 0;
339 *fontFace = 0;
340
341 /* first try the full fontname */
342 fontNameStr[0] = len;
343 memcpy(fontNameStr+1, fname, len);
344 *fontID = FMGetFontFamilyFromName((StringPtr) fontNameStr);
345 if (*fontID > 0) return;
346
347 /* try to find the font without the dashes */
348 fontNameStr[0] = len;
349 memcpy(fontNameStr+1, fname, len);
350 for (i=1; i<=len; i++)
351 if (fontNameStr[i] == '-') fontNameStr[i] = ' ';
352 *fontID = FMGetFontFamilyFromName((StringPtr) fontNameStr);
353 if (*fontID > 0) return;
354
355 /* we should read some default fontname mappings from a file here */
356 if (*fontID > 0) return;
357
358 /* try to extract font basename and style names */
359 memcpy(fontNameStr, fname, len);
360 fontNameStr[len] = 0;
361
362 fontFamilyName = strtok(fontNameStr, "- ");
363 while ((fontStyleName = strtok(NULL, "- ")) != NULL) {
364 if (!strcmp(fontStyleName, "Italic") || !strcmp(fontStyleName, "Oblique") || !strcmp(fontStyleName, "It"))
365 *fontFace |= italic;
366 if (!strcmp(fontStyleName, "Bold") || !strcmp(fontStyleName, "Bd"))
367 *fontFace |= bold;
368 if (!strcmp(fontStyleName, "Narrow") || !strcmp(fontStyleName, "Condensed"))
369 *fontFace |= condense;
370 }
371
372 if (fontFamilyName == NULL) {
373 return;
374 } else {
375 Str255 fontName;
376
377 fontName[0] = strlen(fontFamilyName);
378 strcpy((char*)(fontName+1), fontFamilyName);
379 *fontID = FMGetFontFamilyFromName((StringPtr) fontNameStr);
380 if (*fontID > 0) return;
381 }
382 }
383
384
385
386 /* extract a font's platform id (encoding) */
387
388 private int
mac_get_font_encoding(mac_xfont * macxf)389 mac_get_font_encoding(mac_xfont *macxf)
390 {
391 int encoding = ENCODING_INDEX_UNKNOWN;
392 ResType resType;
393 short resID;
394
395 mac_get_font_resource(macxf, &resType, &resID);
396
397 if (resType == 'sfnt') {
398 Handle fontHandle;
399 TTFontDir *fontDir;
400 TTFontNamingTable *fontNamingTable;
401 int i;
402
403 /* load resource */
404 if ((fontHandle = GetResource(resType, resID)) == NULL)
405 return encoding;
406 HLock(fontHandle);
407
408 /* walk through the font directory and find the font naming table */
409 fontDir = (TTFontDir*) *fontHandle;
410 if (fontDir != NULL && fontDir->version == 'true') {
411 for (i=0; i<fontDir->numTables; i++) {
412 if (fontDir->components[i].tagName == TTF_FONT_NAMING_TABLE) {
413 fontNamingTable = (TTFontNamingTable*) ((long)(fontDir->components[i].offset) + (long)fontDir);
414 switch (fontNamingTable->platformID) {
415 //case 0: encoding = ENCODING_INDEX_STANDARD; break; /* Unicode */
416 case 1: encoding = ENCODING_INDEX_MACROMAN; break;
417 case 2: encoding = ENCODING_INDEX_ISOLATIN1; break;
418 //case 3: encoding = ENCODING_INDEX_WINANSI; break;
419 }
420 break;
421 }
422 }
423 }
424
425 HUnlock(fontHandle);
426 ReleaseResource(fontHandle);
427 }
428
429 return encoding;
430 }
431
432
433
434 /* get a handle to a font resource */
435
436 private void
mac_get_font_resource(mac_xfont * macxf,ResType * resType,short * resID)437 mac_get_font_resource(mac_xfont *macxf, ResType *resType, short *resID)
438 {
439 FMInput fontInput = {0, 0, 0, true, 0, {1,1}, {1,1}};
440 FMOutputPtr fontOutput;
441
442 Str255 resName;
443
444 fontInput.family = macxf->fontID;
445 fontInput.size = macxf->fontSize;
446 fontInput.face = macxf->fontFace;
447
448 fontOutput = FMSwapFont(&fontInput);
449
450 if (fontOutput == NULL || fontOutput->fontHandle == NULL)
451 return;
452
453 GetResInfo(fontOutput->fontHandle, resID, resType, resName);
454 }
455
456
457
458 #if !USE_RECOMMENDED_CARBON_FONTMANAGER_CALLS
459 /* wrap the old Classic MacOS font manager calls to fake support for the
460 new FontManager API on older systems */
461
462 OSStatus
FMGetFontFamilyName(FMFontFamily fontFamilyID,Str255 fontNameStr)463 FMGetFontFamilyName(FMFontFamily fontFamilyID, Str255 fontNameStr)
464 {
465 GetFontName(fontFamilyID, fontNameStr);
466 return noErr;
467 }
468
469 FMFontFamily
FMGetFontFamilyFromName(ConstStr255Param fontNameStr)470 FMGetFontFamilyFromName(ConstStr255Param fontNameStr)
471 {
472 int fontID;
473 GetFNum(fontNameStr, &fontID);
474
475 return (FMFontFamily)fontID;
476 }
477 #endif
478