2 * PostScript driver font functions
4 * Copyright 1998 Huw D M Davies
10 #include "debugtools.h"
14 DEFAULT_DEBUG_CHANNEL(psdrv
);
17 /***********************************************************************
18 * PSDRV_FONT_SelectObject
20 HFONT16
PSDRV_FONT_SelectObject( DC
* dc
, HFONT16 hfont
,
23 HFONT16 prevfont
= dc
->hFont
;
24 PSDRV_PDEVICE
*physDev
= (PSDRV_PDEVICE
*)dc
->physDev
;
25 LOGFONT16
*lf
= &(font
->logfont
);
26 BOOL bd
= FALSE
, it
= FALSE
;
30 char FaceName
[LF_FACESIZE
];
33 TRACE("FaceName = '%s' Height = %d Italic = %d Weight = %d\n",
34 lf
->lfFaceName
, lf
->lfHeight
, lf
->lfItalic
, lf
->lfWeight
);
40 if(lf
->lfWeight
> 550)
42 strcpy(FaceName
, lf
->lfFaceName
);
44 if(FaceName
[0] == '\0') {
45 switch(lf
->lfPitchAndFamily
& 0xf0) {
50 strcpy(FaceName
, "Times");
53 strcpy(FaceName
, "Helvetica");
56 strcpy(FaceName
, "Courier");
59 strcpy(FaceName
, "Symbol");
64 if(FaceName
[0] == '\0') {
65 switch(lf
->lfPitchAndFamily
& 0x0f) {
67 strcpy(FaceName
, "Times");
70 strcpy(FaceName
, "Courier");
75 TRACE("Trying to find facename '%s'\n", FaceName
);
77 /* Look for a matching font family */
78 for(family
= physDev
->pi
->Fonts
; family
; family
= family
->next
) {
79 if(!strcasecmp(FaceName
, family
->FamilyName
))
83 /* Fallback for Window's font families to common PostScript families */
84 if(!strcmp(FaceName
, "Arial"))
85 strcpy(FaceName
, "Helvetica");
86 else if(!strcmp(FaceName
, "System"))
87 strcpy(FaceName
, "Helvetica");
88 else if(!strcmp(FaceName
, "Times New Roman"))
89 strcpy(FaceName
, "Times");
90 else if(!strcmp(FaceName
, "Courier New"))
91 strcpy(FaceName
, "Courier");
93 for(family
= physDev
->pi
->Fonts
; family
; family
= family
->next
) {
94 if(!strcmp(FaceName
, family
->FamilyName
))
98 /* If all else fails, use the first font defined for the printer */
100 family
= physDev
->pi
->Fonts
;
102 TRACE("Got family '%s'\n", family
->FamilyName
);
104 for(afmle
= family
->afmlist
; afmle
; afmle
= afmle
->next
) {
105 if( (bd
== (afmle
->afm
->Weight
== FW_BOLD
)) &&
106 (it
== (afmle
->afm
->ItalicAngle
!= 0.0)) )
110 afmle
= family
->afmlist
; /* not ideal */
114 physDev
->font
.afm
= afm
;
115 physDev
->font
.tm
.tmHeight
= INTERNAL_YWSTODS(dc
, lf
->lfHeight
);
116 if(physDev
->font
.tm
.tmHeight
< 0) {
117 physDev
->font
.tm
.tmHeight
*= - (afm
->FullAscender
- afm
->Descender
) /
118 (afm
->Ascender
- afm
->Descender
);
119 TRACE("Fixed -ve height to %ld\n", physDev
->font
.tm
.tmHeight
);
121 physDev
->font
.size
= physDev
->font
.tm
.tmHeight
* 1000.0 /
122 (afm
->FullAscender
- afm
->Descender
);
123 physDev
->font
.scale
= physDev
->font
.size
/ 1000.0;
124 physDev
->font
.escapement
= lf
->lfEscapement
;
125 physDev
->font
.tm
.tmAscent
= afm
->FullAscender
* physDev
->font
.scale
;
126 physDev
->font
.tm
.tmDescent
= -afm
->Descender
* physDev
->font
.scale
;
127 physDev
->font
.tm
.tmInternalLeading
= (afm
->FullAscender
- afm
->Ascender
)
128 * physDev
->font
.scale
;
129 physDev
->font
.tm
.tmExternalLeading
= (1000.0 - afm
->FullAscender
)
130 * physDev
->font
.scale
; /* ?? */
131 physDev
->font
.tm
.tmAveCharWidth
= afm
->CharWidths
[120] * /* x */
133 physDev
->font
.tm
.tmMaxCharWidth
= afm
->CharWidths
[77] * /* M */
135 physDev
->font
.tm
.tmWeight
= afm
->Weight
;
136 physDev
->font
.tm
.tmItalic
= afm
->ItalicAngle
!= 0.0;
137 physDev
->font
.tm
.tmUnderlined
= lf
->lfUnderline
;
138 physDev
->font
.tm
.tmStruckOut
= lf
->lfStrikeOut
;
139 physDev
->font
.tm
.tmFirstChar
= 32;
140 physDev
->font
.tm
.tmLastChar
= 251;
141 physDev
->font
.tm
.tmDefaultChar
= 128;
142 physDev
->font
.tm
.tmBreakChar
= 32;
143 physDev
->font
.tm
.tmPitchAndFamily
= afm
->IsFixedPitch
? 0 :
145 physDev
->font
.tm
.tmPitchAndFamily
|= TMPF_DEVICE
;
146 physDev
->font
.tm
.tmCharSet
= ANSI_CHARSET
;
147 physDev
->font
.tm
.tmOverhang
= 0;
148 physDev
->font
.tm
.tmDigitizedAspectX
= dc
->devCaps
->logPixelsY
;
149 physDev
->font
.tm
.tmDigitizedAspectY
= dc
->devCaps
->logPixelsX
;
151 physDev
->font
.set
= FALSE
;
153 TRACE("Selected PS font '%s' size %d weight %ld.\n",
154 physDev
->font
.afm
->FontName
, physDev
->font
.size
,
155 physDev
->font
.tm
.tmWeight
);
156 TRACE("H = %ld As = %ld Des = %ld IL = %ld EL = %ld\n",
157 physDev
->font
.tm
.tmHeight
, physDev
->font
.tm
.tmAscent
,
158 physDev
->font
.tm
.tmDescent
, physDev
->font
.tm
.tmInternalLeading
,
159 physDev
->font
.tm
.tmExternalLeading
);
164 /***********************************************************************
165 * PSDRV_GetTextMetrics
167 BOOL
PSDRV_GetTextMetrics(DC
*dc
, TEXTMETRICA
*metrics
)
169 PSDRV_PDEVICE
*physDev
= (PSDRV_PDEVICE
*)dc
->physDev
;
171 memcpy(metrics
, &(physDev
->font
.tm
), sizeof(physDev
->font
.tm
));
175 /***********************************************************************
176 * PSDRV_UnicodeToANSI
178 char PSDRV_UnicodeToANSI(int u
)
183 case 0x2013: /* endash */
185 case 0x2014: /* emdash */
187 case 0x2018: /* quoteleft */
189 case 0x2019: /* quoteright */
191 case 0x201c: /* quotedblleft */
193 case 0x201d: /* quotedblright */
195 case 0x2022: /* bullet */
198 WARN("Umapped unicode char U%04x\n", u
);
202 /***********************************************************************
203 * PSDRV_GetTextExtentPoint
205 BOOL
PSDRV_GetTextExtentPoint( DC
*dc
, LPCWSTR str
, INT count
,
208 PSDRV_PDEVICE
*physDev
= (PSDRV_PDEVICE
*)dc
->physDev
;
214 for(i
= 0; i
< count
&& str
[i
]; i
++) {
215 char c
= PSDRV_UnicodeToANSI(str
[i
]);
216 width
+= physDev
->font
.afm
->CharWidths
[(int)(unsigned char)c
];
217 /* TRACE(psdrv, "Width after %dth char '%c' = %f\n", i, str[i], width);*/
219 width
*= physDev
->font
.scale
;
220 TRACE("Width after scale (%f) is %f\n", physDev
->font
.scale
, width
);
222 size
->cx
= GDI_ROUND((FLOAT
)width
* dc
->xformVport2World
.eM11
);
223 size
->cy
= GDI_ROUND((FLOAT
)physDev
->font
.tm
.tmHeight
* dc
->xformVport2World
.eM22
);
229 /***********************************************************************
232 BOOL
PSDRV_GetCharWidth( DC
*dc
, UINT firstChar
, UINT lastChar
,
235 PSDRV_PDEVICE
*physDev
= (PSDRV_PDEVICE
*)dc
->physDev
;
238 TRACE("first = %d last = %d\n", firstChar
, lastChar
);
240 if(lastChar
> 0xff) return FALSE
;
241 for( i
= firstChar
; i
<= lastChar
; i
++ )
242 *buffer
++ = physDev
->font
.afm
->CharWidths
[i
] * physDev
->font
.scale
;
248 /***********************************************************************
251 BOOL
PSDRV_SetFont( DC
*dc
)
253 PSDRV_PDEVICE
*physDev
= (PSDRV_PDEVICE
*)dc
->physDev
;
254 BOOL ReEncode
= FALSE
;
256 PSDRV_WriteSetColor(dc
, &physDev
->font
.color
);
257 if(physDev
->font
.set
) return TRUE
;
259 if(physDev
->font
.afm
->EncodingScheme
&&
260 !strcmp(physDev
->font
.afm
->EncodingScheme
, "AdobeStandardEncoding"))
263 PSDRV_WriteReencodeFont(dc
);
264 PSDRV_WriteSetFont(dc
, ReEncode
);
265 physDev
->font
.set
= TRUE
;
270 /***********************************************************************
271 * PSDRV_GetFontMetric
273 static UINT
PSDRV_GetFontMetric(HDC hdc
, AFM
*pafm
, NEWTEXTMETRIC16
*pTM
,
274 ENUMLOGFONTEX16
*pLF
, INT16 size
)
277 DC
*dc
= DC_GetDCPtr( hdc
);
278 float scale
= size
/ (pafm
->FullAscender
- pafm
->Descender
);
280 if (!dc
) return FALSE
;
282 memset( pLF
, 0, sizeof(*pLF
) );
283 memset( pTM
, 0, sizeof(*pTM
) );
285 #define plf ((LPLOGFONT16)pLF)
286 plf
->lfHeight
= pTM
->tmHeight
= size
;
287 plf
->lfWidth
= pTM
->tmAveCharWidth
= pafm
->CharWidths
[120] * scale
;
288 plf
->lfWeight
= pTM
->tmWeight
= pafm
->Weight
;
289 plf
->lfItalic
= pTM
->tmItalic
= pafm
->ItalicAngle
!= 0.0;
290 plf
->lfUnderline
= pTM
->tmUnderlined
= 0;
291 plf
->lfStrikeOut
= pTM
->tmStruckOut
= 0;
292 plf
->lfCharSet
= pTM
->tmCharSet
= ANSI_CHARSET
;
294 /* convert pitch values */
296 pTM
->tmPitchAndFamily
= pafm
->IsFixedPitch
? 0 : TMPF_FIXED_PITCH
;
297 pTM
->tmPitchAndFamily
|= TMPF_DEVICE
;
298 plf
->lfPitchAndFamily
= 0;
300 lstrcpynA( plf
->lfFaceName
, pafm
->FamilyName
, LF_FACESIZE
);
303 pTM
->tmAscent
= pafm
->FullAscender
* scale
;
304 pTM
->tmDescent
= -pafm
->Descender
* scale
;
305 pTM
->tmInternalLeading
= (pafm
->FullAscender
- pafm
->Ascender
) * scale
;
306 pTM
->tmMaxCharWidth
= pafm
->CharWidths
[77] * scale
;
307 pTM
->tmDigitizedAspectX
= dc
->devCaps
->logPixelsY
;
308 pTM
->tmDigitizedAspectY
= dc
->devCaps
->logPixelsX
;
310 *(INT
*)&pTM
->tmFirstChar
= 32;
312 GDI_ReleaseObj( hdc
);
313 /* return font type */
314 return DEVICE_FONTTYPE
;
318 /***********************************************************************
319 * PSDRV_EnumDeviceFonts
321 BOOL
PSDRV_EnumDeviceFonts( HDC hdc
, LPLOGFONT16 plf
,
322 DEVICEFONTENUMPROC proc
, LPARAM lp
)
329 PSDRV_PDEVICE
*physDev
;
331 DC
*dc
= DC_GetDCPtr( hdc
);
332 if (!dc
) return FALSE
;
334 physDev
= (PSDRV_PDEVICE
*)dc
->physDev
;
335 /* FIXME!! should reevaluate dc->physDev after every callback */
336 GDI_ReleaseObj( hdc
);
338 if( plf
->lfFaceName
[0] ) {
339 TRACE("lfFaceName = '%s'\n", plf
->lfFaceName
);
340 for(family
= physDev
->pi
->Fonts
; family
; family
= family
->next
) {
341 if(!strncmp(plf
->lfFaceName
, family
->FamilyName
,
342 strlen(family
->FamilyName
)))
346 for(afmle
= family
->afmlist
; afmle
; afmle
= afmle
->next
) {
347 TRACE("Got '%s'\n", afmle
->afm
->FontName
);
348 if( (b
= (*proc
)( &lf
, &tm
,
349 PSDRV_GetFontMetric( hdc
, afmle
->afm
, &tm
, &lf
, 200 ),
357 TRACE("lfFaceName = NULL\n");
358 for(family
= physDev
->pi
->Fonts
; family
; family
= family
->next
) {
359 afmle
= family
->afmlist
;
360 TRACE("Got '%s'\n", afmle
->afm
->FontName
);
361 if( (b
= (*proc
)( &lf
, &tm
,
362 PSDRV_GetFontMetric( hdc
, afmle
->afm
, &tm
, &lf
, 200 ),