| /* |
| * Font metric functions common to Type 1 (AFM) and TrueType font files. |
| * Functions specific to Type 1 and TrueType fonts are in type1afm.c and |
| * truetype.c respectively. |
| * |
| * Copyright 1998 Huw D M Davies |
| * Copyright 2001 Ian Pilcher |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include "config.h" |
| |
| #include <string.h> |
| |
| #include "psdrv.h" |
| #include "wine/debug.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(psdrv); |
| |
| /* ptr to fonts for which we have afm files */ |
| DECLSPEC_HIDDEN FONTFAMILY *PSDRV_AFMFontList = NULL; |
| |
| |
| /*********************************************************** |
| * |
| * PSDRV_FreeAFMList |
| * |
| * Frees the family and afmlistentry structures in list head |
| */ |
| void PSDRV_FreeAFMList( FONTFAMILY *head ) |
| { |
| AFMLISTENTRY *afmle, *nexta; |
| FONTFAMILY *family, *nextf; |
| |
| for(nextf = family = head; nextf; family = nextf) { |
| for(nexta = afmle = family->afmlist; nexta; afmle = nexta) { |
| nexta = afmle->next; |
| HeapFree( PSDRV_Heap, 0, afmle ); |
| } |
| nextf = family->next; |
| HeapFree( PSDRV_Heap, 0, family ); |
| } |
| return; |
| } |
| |
| |
| /*********************************************************** |
| * |
| * PSDRV_FindAFMinList |
| * Returns ptr to an AFM if name (which is a PS font name) exists in list |
| * headed by head. |
| */ |
| const AFM *PSDRV_FindAFMinList(FONTFAMILY *head, LPCSTR name) |
| { |
| FONTFAMILY *family; |
| AFMLISTENTRY *afmle; |
| |
| for(family = head; family; family = family->next) { |
| for(afmle = family->afmlist; afmle; afmle = afmle->next) { |
| if(!strcmp(afmle->afm->FontName, name)) |
| return afmle->afm; |
| } |
| } |
| return NULL; |
| } |
| |
| /*********************************************************** |
| * |
| * PSDRV_AddAFMtoList |
| * |
| * Adds an afm to the list whose head is pointed to by head. Creates new |
| * family node if necessary and always creates a new AFMLISTENTRY. |
| * |
| * Returns FALSE for memory allocation error; returns TRUE, but sets *p_added |
| * to FALSE, for duplicate. |
| */ |
| BOOL PSDRV_AddAFMtoList(FONTFAMILY **head, const AFM *afm, BOOL *p_added) |
| { |
| FONTFAMILY *family = *head; |
| FONTFAMILY **insert = head; |
| AFMLISTENTRY *tmpafmle, *newafmle; |
| |
| newafmle = HeapAlloc(PSDRV_Heap, HEAP_ZERO_MEMORY, |
| sizeof(*newafmle)); |
| if (newafmle == NULL) |
| return FALSE; |
| |
| newafmle->afm = afm; |
| |
| while(family) { |
| if(!strcmp(family->FamilyName, afm->FamilyName)) |
| break; |
| insert = &(family->next); |
| family = family->next; |
| } |
| |
| if(!family) { |
| family = HeapAlloc(PSDRV_Heap, HEAP_ZERO_MEMORY, |
| sizeof(*family)); |
| if (family == NULL) { |
| HeapFree(PSDRV_Heap, 0, newafmle); |
| return FALSE; |
| } |
| *insert = family; |
| if (!(family->FamilyName = HeapAlloc(PSDRV_Heap, 0, strlen(afm->FamilyName)+1 ))) { |
| HeapFree(PSDRV_Heap, 0, family); |
| HeapFree(PSDRV_Heap, 0, newafmle); |
| return FALSE; |
| } |
| strcpy( family->FamilyName, afm->FamilyName ); |
| family->afmlist = newafmle; |
| *p_added = TRUE; |
| return TRUE; |
| } |
| else { |
| tmpafmle = family->afmlist; |
| while (tmpafmle) { |
| if (!strcmp(tmpafmle->afm->FontName, afm->FontName)) { |
| WARN("Ignoring duplicate FontName '%s'\n", afm->FontName); |
| HeapFree(PSDRV_Heap, 0, newafmle); |
| *p_added = FALSE; |
| return TRUE; /* not a fatal error */ |
| } |
| tmpafmle = tmpafmle->next; |
| } |
| } |
| |
| tmpafmle = family->afmlist; |
| while(tmpafmle->next) |
| tmpafmle = tmpafmle->next; |
| |
| tmpafmle->next = newafmle; |
| |
| *p_added = TRUE; |
| return TRUE; |
| } |
| |
| |
| /*********************************************************** |
| * |
| * PSDRV_DumpFontList |
| * |
| */ |
| static void PSDRV_DumpFontList(void) |
| { |
| FONTFAMILY *family; |
| AFMLISTENTRY *afmle; |
| |
| for(family = PSDRV_AFMFontList; family; family = family->next) { |
| TRACE("Family '%s'\n", family->FamilyName); |
| for(afmle = family->afmlist; afmle; afmle = afmle->next) |
| { |
| #if 0 |
| INT i; |
| #endif |
| |
| TRACE("\tFontName '%s' (%i glyphs) - '%s' encoding:\n", |
| afmle->afm->FontName, afmle->afm->NumofMetrics, |
| afmle->afm->EncodingScheme); |
| |
| /* Uncomment to regenerate font data; see afm2c.c */ |
| |
| /* PSDRV_AFM2C(afmle->afm); */ |
| |
| #if 0 |
| for (i = 0; i < afmle->afm->NumofMetrics; ++i) |
| { |
| TRACE("\t\tU+%.4lX; C %i; N '%s'\n", afmle->afm->Metrics[i].UV, |
| afmle->afm->Metrics[i].C, afmle->afm->Metrics[i].N->sz); |
| } |
| #endif |
| } |
| } |
| return; |
| } |
| |
| |
| /******************************************************************************* |
| * PSDRV_CalcAvgCharWidth |
| * |
| * Calculate WinMetrics.sAvgCharWidth for a Type 1 font. Can also be used on |
| * TrueType fonts, if font designer set OS/2:xAvgCharWidth to zero. |
| * |
| * Tries to use formula in TrueType specification; falls back to simple mean |
| * if any lowercase latin letter (or space) is not present. |
| */ |
| static inline SHORT MeanCharWidth(const AFM *afm) |
| { |
| float w = 0.0; |
| int i; |
| |
| for (i = 0; i < afm->NumofMetrics; ++i) |
| w += afm->Metrics[i].WX; |
| |
| w /= afm->NumofMetrics; |
| |
| return (SHORT)(w + 0.5); |
| } |
| |
| static const struct { LONG UV; int weight; } UVweight[27] = |
| { |
| { 0x0061, 64 }, { 0x0062, 14 }, { 0x0063, 27 }, { 0x0064, 35 }, |
| { 0x0065, 100 }, { 0x0066, 20 }, { 0x0067, 14 }, { 0x0068, 42 }, |
| { 0x0069, 63 }, { 0x006a, 3 }, { 0x006b, 6 }, { 0x006c, 35 }, |
| { 0x006d, 20 }, { 0x006e, 56 }, { 0x006f, 56 }, { 0x0070, 17 }, |
| { 0x0071, 4 }, { 0x0072, 49 }, { 0x0073, 56 }, { 0x0074, 71 }, |
| { 0x0075, 31 }, { 0x0076, 10 }, { 0x0077, 18 }, { 0x0078, 3 }, |
| { 0x0079, 18 }, { 0x007a, 2 }, { 0x0020, 166 } |
| }; |
| |
| SHORT PSDRV_CalcAvgCharWidth(const AFM *afm) |
| { |
| float w = 0.0; |
| int i; |
| |
| for (i = 0; i < 27; ++i) |
| { |
| const AFMMETRICS *afmm; |
| |
| afmm = PSDRV_UVMetrics(UVweight[i].UV, afm); |
| if (afmm->UV != UVweight[i].UV) /* UVMetrics returns first glyph */ |
| return MeanCharWidth(afm); /* in font if UV is missing */ |
| |
| w += afmm->WX * (float)(UVweight[i].weight); |
| } |
| |
| w /= 1000.0; |
| |
| return (SHORT)(w + 0.5); |
| } |
| |
| |
| /******************************************************************************* |
| * AddBuiltinAFMs |
| * |
| */ |
| |
| static BOOL AddBuiltinAFMs(void) |
| { |
| const AFM *const *afm = PSDRV_BuiltinAFMs; |
| |
| while (*afm != NULL) |
| { |
| BOOL added; |
| |
| if (PSDRV_AddAFMtoList(&PSDRV_AFMFontList, *afm, &added) == FALSE) |
| return FALSE; |
| |
| if (added == FALSE) |
| TRACE("Ignoring built-in font %s\n", (*afm)->FontName); |
| |
| ++afm; |
| } |
| |
| return TRUE; |
| } |
| |
| |
| /*********************************************************** |
| * |
| * PSDRV_GetFontMetrics |
| * |
| * Parses all afm files listed in the |
| * HKEY_CURRENT_USER\\Software\\Wine\\Fonts registry key. |
| * Adds built-in data last, so it can be overridden by |
| * user-supplied AFM or TTF files. |
| * |
| * If this function fails, PSDRV_Init will destroy PSDRV_Heap, so don't worry |
| * about freeing all the memory that's been allocated. |
| */ |
| |
| BOOL PSDRV_GetFontMetrics(void) |
| { |
| if (PSDRV_GlyphListInit() != 0) |
| return FALSE; |
| |
| if (PSDRV_GetType1Metrics() == FALSE) |
| return FALSE; |
| |
| if (AddBuiltinAFMs() == FALSE) |
| return FALSE; |
| |
| PSDRV_IndexGlyphList(); /* Enable fast searching of glyph names */ |
| |
| PSDRV_DumpFontList(); |
| |
| return TRUE; |
| } |