~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/wineps.drv/builtin.c

Version: ~ [ wine-1.5.30 ] ~ [ wine-1.5.29 ] ~ [ wine-1.5.28 ] ~ [ wine-1.5.27 ] ~ [ wine-1.5.26 ] ~ [ wine-1.5.25 ] ~ [ wine-1.5.24 ] ~ [ wine-1.5.23 ] ~ [ wine-1.5.22 ] ~ [ wine-1.5.21 ] ~ [ wine-1.5.20 ] ~ [ wine-1.5.19 ] ~ [ wine-1.5.18 ] ~ [ wine-1.5.17 ] ~ [ wine-1.5.16 ] ~ [ wine-1.5.15 ] ~ [ wine-1.5.14 ] ~ [ wine-1.5.13 ] ~ [ wine-1.5.12 ] ~ [ wine-1.5.11 ] ~ [ wine-1.5.10 ] ~ [ wine-1.5.9 ] ~ [ wine-1.5.8 ] ~ [ wine-1.5.7 ] ~ [ wine-1.4.1 ] ~ [ wine-1.5.6 ] ~ [ wine-1.5.5 ] ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  *      PostScript driver builtin font functions
  3  *
  4  *      Copyright 2002  Huw D M Davies for CodeWeavers
  5  *
  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.
 10  *
 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.
 15  *
 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
 19  */
 20 #include <stdarg.h>
 21 #include <string.h>
 22 #include <stdlib.h>
 23 #include <math.h>
 24 #include <assert.h>
 25 
 26 #include "windef.h"
 27 #include "winbase.h"
 28 #include "winerror.h"
 29 #include "wingdi.h"
 30 #include "winnls.h"
 31 
 32 #include "psdrv.h"
 33 #include "wine/debug.h"
 34 
 35 WINE_DEFAULT_DEBUG_CHANNEL(psdrv);
 36 
 37 
 38 /***********************************************************************
 39  *           is_stock_font
 40  */
 41 static inline BOOL is_stock_font( HFONT font )
 42 {
 43     int i;
 44     for (i = OEM_FIXED_FONT; i <= DEFAULT_GUI_FONT; i++)
 45     {
 46         if (i != DEFAULT_PALETTE && font == GetStockObject(i)) return TRUE;
 47     }
 48     return FALSE;
 49 }
 50 
 51 
 52 /*******************************************************************************
 53  *  ScaleFont
 54  *
 55  *  Scale builtin font to requested lfHeight
 56  *
 57  */
 58 static inline float Round(float f)
 59 {
 60     return (f > 0) ? (f + 0.5) : (f - 0.5);
 61 }
 62 
 63 static VOID ScaleFont(const AFM *afm, LONG lfHeight, PSFONT *font,
 64                       TEXTMETRICW *tm)
 65 {
 66     const WINMETRICS    *wm = &(afm->WinMetrics);
 67     USHORT              usUnitsPerEm, usWinAscent, usWinDescent;
 68     SHORT               sAscender, sDescender, sLineGap, sAvgCharWidth;
 69 
 70     TRACE("'%s' %i\n", afm->FontName, lfHeight);
 71 
 72     if (lfHeight < 0)                                   /* match em height */
 73     {
 74         font->fontinfo.Builtin.scale = - ((float)lfHeight / (float)(wm->usUnitsPerEm));
 75     }
 76     else                                                /* match cell height */
 77     {
 78         font->fontinfo.Builtin.scale = (float)lfHeight /
 79                 (float)(wm->usWinAscent + wm->usWinDescent);
 80     }
 81 
 82     font->size.xx = (INT)Round(font->fontinfo.Builtin.scale * (float)wm->usUnitsPerEm);
 83     font->size.xy = font->size.yx = 0;
 84     font->size.yy = -(INT)Round(font->fontinfo.Builtin.scale * (float)wm->usUnitsPerEm);
 85 
 86     usUnitsPerEm = (USHORT)Round((float)(wm->usUnitsPerEm) * font->fontinfo.Builtin.scale);
 87     sAscender = (SHORT)Round((float)(wm->sAscender) * font->fontinfo.Builtin.scale);
 88     sDescender = (SHORT)Round((float)(wm->sDescender) * font->fontinfo.Builtin.scale);
 89     sLineGap = (SHORT)Round((float)(wm->sLineGap) * font->fontinfo.Builtin.scale);
 90     usWinAscent = (USHORT)Round((float)(wm->usWinAscent) * font->fontinfo.Builtin.scale);
 91     usWinDescent = (USHORT)Round((float)(wm->usWinDescent) * font->fontinfo.Builtin.scale);
 92     sAvgCharWidth = (SHORT)Round((float)(wm->sAvgCharWidth) * font->fontinfo.Builtin.scale);
 93 
 94     tm->tmAscent = (LONG)usWinAscent;
 95     tm->tmDescent = (LONG)usWinDescent;
 96     tm->tmHeight = tm->tmAscent + tm->tmDescent;
 97 
 98     tm->tmInternalLeading = tm->tmHeight - (LONG)usUnitsPerEm;
 99     if (tm->tmInternalLeading < 0)
100         tm->tmInternalLeading = 0;
101 
102     tm->tmExternalLeading =
103             (LONG)(sAscender - sDescender + sLineGap) - tm->tmHeight;
104     if (tm->tmExternalLeading < 0)
105         tm->tmExternalLeading = 0;
106 
107     tm->tmAveCharWidth = (LONG)sAvgCharWidth;
108 
109     tm->tmWeight = afm->Weight;
110     tm->tmItalic = (afm->ItalicAngle != 0.0);
111     tm->tmUnderlined = 0;
112     tm->tmStruckOut = 0;
113     tm->tmFirstChar = (WCHAR)(afm->Metrics[0].UV);
114     tm->tmLastChar = (WCHAR)(afm->Metrics[afm->NumofMetrics - 1].UV);
115     tm->tmDefaultChar = 0x001f;         /* Win2K does this - FIXME? */
116     tm->tmBreakChar = tm->tmFirstChar;          /* should be 'space' */
117 
118     tm->tmPitchAndFamily = TMPF_DEVICE | TMPF_VECTOR;
119     if (!afm->IsFixedPitch)
120         tm->tmPitchAndFamily |= TMPF_FIXED_PITCH;   /* yes, it's backwards */
121     if (wm->usUnitsPerEm != 1000)
122         tm->tmPitchAndFamily |= TMPF_TRUETYPE;
123 
124     tm->tmCharSet = ANSI_CHARSET;       /* FIXME */
125     tm->tmOverhang = 0;
126 
127     /*
128      *  This is kludgy.  font->scale is used in several places in the driver
129      *  to adjust PostScript-style metrics.  Since these metrics have been
130      *  "normalized" to an em-square size of 1000, font->scale needs to be
131      *  similarly adjusted..
132      */
133 
134     font->fontinfo.Builtin.scale *= (float)wm->usUnitsPerEm / 1000.0;
135 
136     tm->tmMaxCharWidth = (LONG)Round(
137             (afm->FontBBox.urx - afm->FontBBox.llx) * font->fontinfo.Builtin.scale);
138 
139     font->underlinePosition = afm->UnderlinePosition * font->fontinfo.Builtin.scale;
140     font->underlineThickness = afm->UnderlineThickness * font->fontinfo.Builtin.scale;
141     font->strikeoutPosition = tm->tmAscent / 2;
142     font->strikeoutThickness = font->underlineThickness;
143 
144     TRACE("Selected PS font '%s' size %d weight %d.\n", afm->FontName,
145           font->size.xx, tm->tmWeight );
146     TRACE("H = %d As = %d Des = %d IL = %d EL = %d\n", tm->tmHeight,
147             tm->tmAscent, tm->tmDescent, tm->tmInternalLeading,
148             tm->tmExternalLeading);
149 }
150 
151 
152 /****************************************************************************
153  *  PSDRV_SelectBuiltinFont
154  *
155  *  Set up physDev->font for a builtin font
156  *
157  */
158 BOOL PSDRV_SelectBuiltinFont(PSDRV_PDEVICE *physDev, HFONT hfont,
159                              LOGFONTW *plf, LPSTR FaceName)
160 {
161     AFMLISTENTRY *afmle;
162     FONTFAMILY *family;
163     BOOL bd = FALSE, it = FALSE;
164     LONG height;
165 
166     TRACE("Trying to find facename '%s'\n", FaceName);
167 
168     /* Look for a matching font family */
169     for(family = physDev->pi->Fonts; family; family = family->next) {
170         if(!strcasecmp(FaceName, family->FamilyName))
171             break;
172     }
173 
174     if(!family) {
175         /* Fallback for Window's font families to common PostScript families */
176         if(!strcmp(FaceName, "Arial"))
177             strcpy(FaceName, "Helvetica");
178         else if(!strcmp(FaceName, "System"))
179             strcpy(FaceName, "Helvetica");
180         else if(!strcmp(FaceName, "Times New Roman"))
181             strcpy(FaceName, "Times");
182         else if(!strcmp(FaceName, "Courier New"))
183             strcpy(FaceName, "Courier");
184 
185         for(family = physDev->pi->Fonts; family; family = family->next) {
186             if(!strcmp(FaceName, family->FamilyName))
187                 break;
188         }
189     }
190     /* If all else fails, use the first font defined for the printer */
191     if(!family)
192         family = physDev->pi->Fonts;
193 
194     TRACE("Got family '%s'\n", family->FamilyName);
195 
196     if(plf->lfItalic)
197         it = TRUE;
198     if(plf->lfWeight > 550)
199         bd = TRUE;
200 
201     for(afmle = family->afmlist; afmle; afmle = afmle->next) {
202         if( (bd == (afmle->afm->Weight == FW_BOLD)) &&
203             (it == (afmle->afm->ItalicAngle != 0.0)) )
204                 break;
205     }
206     if(!afmle)
207         afmle = family->afmlist; /* not ideal */
208 
209     TRACE("Got font '%s'\n", afmle->afm->FontName);
210 
211     physDev->font.fontloc = Builtin;
212     physDev->font.fontinfo.Builtin.afm = afmle->afm;
213 
214     height = plf->lfHeight;
215     /* stock fonts ignore the mapping mode */
216     if (!is_stock_font( hfont )) {
217         POINT pts[2];
218         pts[0].x = pts[0].y = pts[1].x = 0;
219         pts[1].y = height;
220         LPtoDP(physDev->hdc, pts, 2);
221         height = pts[1].y - pts[0].y;
222     }
223     ScaleFont(physDev->font.fontinfo.Builtin.afm, height,
224               &(physDev->font), &(physDev->font.fontinfo.Builtin.tm));
225 
226 
227     /* Does anyone know if these are supposed to be reversed like this? */
228 
229     physDev->font.fontinfo.Builtin.tm.tmDigitizedAspectX = physDev->logPixelsY;
230     physDev->font.fontinfo.Builtin.tm.tmDigitizedAspectY = physDev->logPixelsX;
231 
232     return TRUE;
233 }
234 
235 BOOL PSDRV_WriteSetBuiltinFont(PSDRV_PDEVICE *physDev)
236 {
237     return PSDRV_WriteSetFont(physDev,
238                               physDev->font.fontinfo.Builtin.afm->FontName,
239                               physDev->font.size, physDev->font.escapement);
240 }
241 
242 BOOL PSDRV_WriteBuiltinGlyphShow(PSDRV_PDEVICE *physDev, LPCWSTR str, INT count)
243 {
244     int i;
245     LPCSTR name;
246 
247     for (i = 0; i < count; ++i)
248     {
249         name = PSDRV_UVMetrics(str[i], physDev->font.fontinfo.Builtin.afm)->N->sz;
250 
251         PSDRV_WriteGlyphShow(physDev, name);
252     }
253 
254     return TRUE;
255 }
256 
257 /***********************************************************************
258  *           PSDRV_GetTextMetrics
259  */
260 BOOL CDECL PSDRV_GetTextMetrics(PSDRV_PDEVICE *physDev, TEXTMETRICW *metrics)
261 {
262     assert(physDev->font.fontloc == Builtin);
263 
264     memcpy(metrics, &(physDev->font.fontinfo.Builtin.tm),
265            sizeof(physDev->font.fontinfo.Builtin.tm));
266     return TRUE;
267 }
268 
269 /******************************************************************************
270  *      PSDRV_UVMetrics
271  *
272  *  Find the AFMMETRICS for a given UV.  Returns first glyph in the font
273  *  (space?) if the font does not have a glyph for the given UV.
274  */
275 static int MetricsByUV(const void *a, const void *b)
276 {
277     return (int)(((const AFMMETRICS *)a)->UV - ((const AFMMETRICS *)b)->UV);
278 }
279 
280 const AFMMETRICS *PSDRV_UVMetrics(LONG UV, const AFM *afm)
281 {
282     AFMMETRICS          key;
283     const AFMMETRICS    *needle;
284 
285     /*
286      *  Ugly work-around for symbol fonts.  Wine is sending characters which
287      *  belong in the Unicode private use range (U+F020 - U+F0FF) as ASCII
288      *  characters (U+0020 - U+00FF).
289      */
290 
291     if ((afm->Metrics->UV & 0xff00) == 0xf000 && UV < 0x100)
292         UV |= 0xf000;
293 
294     key.UV = UV;
295 
296     needle = bsearch(&key, afm->Metrics, afm->NumofMetrics, sizeof(AFMMETRICS),
297             MetricsByUV);
298 
299     if (needle == NULL)
300     {
301         WARN("No glyph for U+%.4X in %s\n", UV, afm->FontName);
302         needle = afm->Metrics;
303     }
304 
305     return needle;
306 }
307 
308 /***********************************************************************
309  *           PSDRV_GetTextExtentExPoint
310  */
311 BOOL CDECL PSDRV_GetTextExtentExPoint(PSDRV_PDEVICE *physDev, LPCWSTR str, INT count,
312                                       INT maxExt, LPINT lpnFit, LPINT alpDx, LPSIZE size)
313 {
314     int             nfit = 0;
315     int             i;
316     float           width = 0.0;
317     float           scale;
318 
319     assert(physDev->font.fontloc == Builtin);
320 
321     TRACE("%s %i\n", debugstr_wn(str, count), count);
322 
323     scale = physDev->font.fontinfo.Builtin.scale;
324     for (i = 0; i < count && str[i] != '\0'; ++i)
325     {
326         float scaled_width;
327         width += PSDRV_UVMetrics(str[i], physDev->font.fontinfo.Builtin.afm)->WX;
328         scaled_width = width * scale;
329         if (alpDx)
330             alpDx[i] = scaled_width;
331         if (scaled_width <= maxExt)
332             ++nfit;
333     }
334 
335     size->cx = width * physDev->font.fontinfo.Builtin.scale;
336     size->cy = physDev->font.fontinfo.Builtin.tm.tmHeight;
337 
338     if (lpnFit)
339         *lpnFit = nfit;
340 
341     TRACE("cx=%i cy=%i\n", size->cx, size->cy);
342 
343     return TRUE;
344 }
345 
346 /***********************************************************************
347  *           PSDRV_GetCharWidth
348  */
349 BOOL CDECL PSDRV_GetCharWidth(PSDRV_PDEVICE *physDev, UINT firstChar, UINT lastChar, LPINT buffer)
350 {
351     UINT            i;
352 
353     assert(physDev->font.fontloc == Builtin);
354 
355     TRACE("U+%.4X U+%.4X\n", firstChar, lastChar);
356 
357     if (lastChar > 0xffff || firstChar > lastChar)
358     {
359         SetLastError(ERROR_INVALID_PARAMETER);
360         return FALSE;
361     }
362 
363     for (i = firstChar; i <= lastChar; ++i)
364     {
365         *buffer = floor( PSDRV_UVMetrics(i, physDev->font.fontinfo.Builtin.afm)->WX
366                          * physDev->font.fontinfo.Builtin.scale + 0.5 );
367         TRACE("U+%.4X: %i\n", i, *buffer);
368         ++buffer;
369     }
370 
371     return TRUE;
372 }
373 
374 
375 /***********************************************************************
376  *           PSDRV_GetFontMetric
377  */
378 static UINT PSDRV_GetFontMetric(HDC hdc, const AFM *afm,
379         NEWTEXTMETRICEXW *ntmx, ENUMLOGFONTEXW *elfx)
380 {
381     /* ntmx->ntmTm is NEWTEXTMETRICW; compatible w/ TEXTMETRICW per Win32 doc */
382 
383     TEXTMETRICW     *tm = (TEXTMETRICW *)&(ntmx->ntmTm);
384     LOGFONTW        *lf = &(elfx->elfLogFont);
385     PSFONT          font;
386 
387     memset(ntmx, 0, sizeof(*ntmx));
388     memset(elfx, 0, sizeof(*elfx));
389 
390     ScaleFont(afm, -(LONG)(afm->WinMetrics.usUnitsPerEm), &font, tm);
391 
392     lf->lfHeight = tm->tmHeight;
393     lf->lfWidth = tm->tmAveCharWidth;
394     lf->lfWeight = tm->tmWeight;
395     lf->lfItalic = tm->tmItalic;
396     lf->lfCharSet = tm->tmCharSet;
397 
398     lf->lfPitchAndFamily = (afm->IsFixedPitch) ? FIXED_PITCH : VARIABLE_PITCH;
399 
400     MultiByteToWideChar(CP_ACP, 0, afm->FamilyName, -1, lf->lfFaceName,
401             LF_FACESIZE);
402 
403     return DEVICE_FONTTYPE;
404 }
405 
406 /***********************************************************************
407  *           PSDRV_EnumDeviceFonts
408  */
409 BOOL CDECL PSDRV_EnumDeviceFonts( PSDRV_PDEVICE *physDev, LPLOGFONTW plf,
410                                   FONTENUMPROCW proc, LPARAM lp )
411 {
412     ENUMLOGFONTEXW      lf;
413     NEWTEXTMETRICEXW    tm;
414     BOOL                b, bRet = 0;
415     AFMLISTENTRY        *afmle;
416     FONTFAMILY          *family;
417     char                FaceName[LF_FACESIZE];
418 
419     if( plf && plf->lfFaceName[0] ) {
420         WideCharToMultiByte(CP_ACP, 0, plf->lfFaceName, -1,
421                           FaceName, sizeof(FaceName), NULL, NULL);
422         TRACE("lfFaceName = '%s'\n", FaceName);
423         for(family = physDev->pi->Fonts; family; family = family->next) {
424             if(!strncmp(FaceName, family->FamilyName,
425                         strlen(family->FamilyName)))
426                 break;
427         }
428         if(family) {
429             for(afmle = family->afmlist; afmle; afmle = afmle->next) {
430                 UINT fm;
431 
432                 TRACE("Got '%s'\n", afmle->afm->FontName);
433                 fm = PSDRV_GetFontMetric( physDev->hdc, afmle->afm, &tm, &lf );
434                 if( (b = (*proc)( &lf.elfLogFont, (TEXTMETRICW *)&tm, fm, lp )) )
435                      bRet = b;
436                 else break;
437             }
438         }
439     } else {
440 
441         TRACE("lfFaceName = NULL\n");
442         for(family = physDev->pi->Fonts; family; family = family->next) {
443             UINT fm;
444 
445             afmle = family->afmlist;
446             TRACE("Got '%s'\n", afmle->afm->FontName);
447             fm = PSDRV_GetFontMetric( physDev->hdc, afmle->afm, &tm, &lf );
448             if( (b = (*proc)( &lf.elfLogFont, (TEXTMETRICW *)&tm, fm, lp )) )
449                 bRet = b;
450             else break;
451         }
452     }
453     return bRet;
454 }
455 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.