|
|
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
fontsub.c
Abstract:
Function for handling TrueType font substitution dialog
[Environment:]
Win32 subsystem, PostScript driver UI
[Notes:]
Revision History:
02/10/97 -davidx- Consistent handling of common printer info.
09/18/96 - amandan- Modified for common binary data and UI
08/29/95 -davidx- Created it.
--*/
#include "precomp.h"
VOID VSetupTrueTypeFontMappings( IN PUIDATA pUiData )
/*++
Routine Description:
Initialize the font substitution items with the settings from current font substitution table.
Arguments:
pUiData - Points to UIDATA structure
Return Value:
NONE
--*/
{ POPTITEM pOptItem; POPTPARAM pOptParam; DWORD dwOptItem; PWSTR pTTSubstTable;
//
// Get the current font substitution table
//
if ((pTTSubstTable = PGetTTSubstTable(pUiData->ci.hPrinter, NULL)) == NULL && (pTTSubstTable = GET_DEFAULT_FONTSUB_TABLE(&pUiData->ci, pUiData->ci.pUIInfo)) == NULL) { WARNING(("Font substitution table is not available\n")); return; }
//
// For each TrueType font, check if there is a device font mapped to it.
// If there is, find the index of the device font in the selection list.
//
pOptItem = pUiData->pTTFontItems; dwOptItem = pUiData->dwTTFontItem;
while (dwOptItem--) { DWORD dwOptParam, dwIndex; LPCTSTR pDevFontName;
ASSERT(ISFONTSUBSTITEM(pOptItem->UserData));
pOptItem->Sel = 0; pDevFontName = PtstrSearchTTSubstTable(pTTSubstTable, pOptItem->pName);
//
// Check if we found a match
//
if (pDevFontName != NULL && *pDevFontName != NUL) {
//
// Get the total substitution font list
//
dwOptParam = pOptItem->pOptType->Count; pOptParam = pOptItem->pOptType->pOptParam;
//
// Skip the first device font name in the list
// which should always be "Download as Soft Font".
//
for (dwIndex=1; dwIndex < dwOptParam; dwIndex++) { if (_wcsicmp(pDevFontName, pOptParam[dwIndex].pData) == EQUAL_STRING) { pOptItem->Sel = dwIndex; break; } } }
pOptItem++; }
//
// Remember to free the memory occupied by the substitution
// table after we're done with it.
//
FREE_DEFAULT_FONTSUB_TABLE(pTTSubstTable); }
int __cdecl ICompareOptParam( const void *p1, const void *p2 )
{ return _wcsicmp(((POPTPARAM) p1)->pData, ((POPTPARAM) p2)->pData); }
POPTTYPE PFillDevFontOptType( IN PUIDATA pUiData )
/*++
Routine Description:
Initialize an OPTTYPE structure to hold information about the list of device fonts supported by a printer
Arguments:
pUiData - Pointer to UIDATA structure
Return Value:
Pointer to an OPTTYPE structure NULL if there is an error
--*/
{ POPTTYPE pOptType; POPTPARAM pOptParam; HDC hdc; DWORD dwCount, dwIndex; INT iSize; PWSTR pwstrFontNames, pwstr;
//
// Get the list of printer device font names
//
dwCount = 0;
if ((hdc = CreateIC(NULL, pUiData->ci.pPrinterName, NULL, NULL)) && (iSize = _IListDevFontNames(hdc, NULL, 0)) > 0 && (pwstrFontNames = HEAPALLOC(pUiData->ci.hHeap, iSize)) && (iSize == _IListDevFontNames(hdc, pwstrFontNames, iSize))) { //
// Count the number of device font names
//
for (pwstr=pwstrFontNames; *pwstr; pwstr += wcslen(pwstr)+1) dwCount++; } else { ERR(("Couldn't enumerate printer device fonts\n")); }
if (hdc) DeleteDC(hdc);
//
// Generate an OPTTYPE structure for device font list
//
pOptType = HEAPALLOC(pUiData->ci.hHeap, sizeof(OPTTYPE)); pOptParam = HEAPALLOC(pUiData->ci.hHeap, sizeof(OPTPARAM) * (dwCount+1));
if (pOptType == NULL || pOptParam == NULL) { ERR(("Memory allocation failed\n")); return NULL; }
pOptType->cbSize = sizeof(OPTTYPE); pOptType->Count = (WORD) (dwCount+1); pOptType->Type = TVOT_LISTBOX; pOptType->pOptParam = pOptParam;
//
// Initialize OPTPARAM structures.
// The first item is always "Download as Soft Font".
//
for (dwIndex=0; dwIndex <= dwCount; dwIndex++) pOptParam[dwIndex].cbSize = sizeof(OPTPARAM);
pOptParam->pData = (PWSTR) IDS_DOWNLOAD_AS_SOFTFONT; pOptParam++;
// hack to get around a compiler bug
dwCount++; dwCount--;
for (dwIndex=0, pwstr=pwstrFontNames; dwIndex < dwCount; dwIndex++) { pOptParam[dwIndex].pData = pwstr; pwstr += wcslen(pwstr) + 1; }
//
// Sort device font names into alphabetical order;
// Hide any duplicate device font names as well.
//
qsort(pOptParam, dwCount, sizeof(OPTPARAM), ICompareOptParam);
for (dwIndex=1; dwIndex < dwCount; dwIndex++) { if (_wcsicmp(pOptParam[dwIndex].pData, pOptParam[dwIndex-1].pData) == EQUAL_STRING) pOptParam[dwIndex].Flags |= OPTPF_HIDE; }
return pOptType; }
//
// Data structures and functions for enumerating printer device fonts
//
typedef struct _ENUMTTFONT {
DWORD dwCount; POPTITEM pOptItem; POPTTYPE pOptType; HANDLE hHeap; WCHAR awchLastFontName[LF_FACESIZE];
} ENUMTTFONT, *PENUMTTFONT;
INT CALLBACK EnumTTFontProc( ENUMLOGFONT *pelf, NEWTEXTMETRIC *pntm, INT FontType, LPARAM lParam )
{ PENUMTTFONT pEnumData; PTSTR pFontName; PTSTR pFamilyName;
//
// We only care about the TrueType fonts.
//
if (! (FontType & TRUETYPE_FONTTYPE)) return 1;
pEnumData = (PENUMTTFONT) lParam; pFamilyName = pelf->elfLogFont.lfFaceName;
if (_tcscmp(pFamilyName, pEnumData->awchLastFontName) == EQUAL_STRING) return 1;
CopyString(pEnumData->awchLastFontName, pFamilyName, LF_FACESIZE); pEnumData->dwCount++;
if (pEnumData->pOptItem) { pFontName = PtstrDuplicateStringFromHeap(pFamilyName, pEnumData->hHeap);
if (pFontName == NULL) return 0; FILLOPTITEM(pEnumData->pOptItem, pEnumData->pOptType, pFontName, 0, TVITEM_LEVEL2, DMPUB_NONE, FONT_SUBST_ITEM, HELP_INDEX_TTTODEV);
pEnumData->pOptItem++; }
return 1; }
int __cdecl ICompareOptItem( const void *p1, const void *p2 )
{ return _wcsicmp(((POPTITEM) p1)->pName, ((POPTITEM) p2)->pName); }
BOOL BPackItemFontSubstTable( IN OUT PUIDATA pUiData )
/*++
Routine Description:
Pack Font Substitution options
Arguments:
pUiData - Points to UIDATA structure
Return Value:
TRUE if successful, FALSE if there is an error.
--*/
{ ENUMTTFONT EnumData; POPTITEM pOptItem; HDC hdc; INT iResult;
//
// If the printer doesn't support font-substitution,
// then simply return success here.
//
if (pUiData->ci.pUIInfo->dwFontSubCount == 0) return TRUE;
//
// Create a screen IC
//
if ((hdc = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL)) == NULL) { ERR(("Cannot create screen IC\n")); return FALSE; }
//
// Font substitution table
// TrueType font <-> Device font
// ....
//
// Group Header for Font Substitution Table
//
pOptItem = pUiData->pOptItem;
VPackOptItemGroupHeader( pUiData, IDS_FONTSUB_TABLE, IDI_CPSUI_FONTSUB, HELP_INDEX_FONTSUB_TABLE);
ZeroMemory(&EnumData, sizeof(EnumData)); EnumData.hHeap = pUiData->ci.hHeap;
if (pOptItem == NULL) { //
// Count the number of TrueType fonts
//
iResult = EnumFontFamilies(hdc, NULL, (FONTENUMPROC) EnumTTFontProc, (LPARAM) &EnumData); } else { //
// Collapse the group header
//
pOptItem->Flags |= OPTIF_COLLAPSE;
pUiData->pTTFontItems = pUiData->pOptItem; EnumData.pOptItem = pUiData->pOptItem;
//
// Get the list of printer device fonts
//
EnumData.pOptType = PFillDevFontOptType(pUiData);
if (EnumData.pOptType == NULL) { ERR(("PFillDevFontOptType failed\n")); iResult = 0; } else { //
// Enumerate the list of TrueType fonts
//
iResult = EnumFontFamilies(hdc, NULL, (FONTENUMPROC) EnumTTFontProc, (LPARAM) &EnumData);
if (iResult == 0 || EnumData.dwCount != pUiData->dwTTFontItem) { ERR(("Inconsistent number of TrueType fonts\n")); iResult = 0; } else { //
// Sort the TrueType font items alphabetically
//
qsort(pUiData->pTTFontItems, pUiData->dwTTFontItem, sizeof(OPTITEM), ICompareOptItem); } } }
DeleteDC(hdc);
if (iResult == 0) { ERR(("Failed to enumerate TrueType fonts\n")); return FALSE; }
pUiData->dwTTFontItem = EnumData.dwCount; pUiData->dwOptItem += pUiData->dwTTFontItem;
if (pUiData->pOptItem) { pUiData->pOptItem += pUiData->dwTTFontItem; VSetupTrueTypeFontMappings(pUiData); }
return TRUE; }
DWORD DwCollectTrueTypeMappings( IN POPTITEM pOptItem, IN DWORD dwOptItem, OUT PWSTR pwstrTable )
/*++
Routine Description:
Assemble TrueType to device font mappings into a table
Arguments:
pOptItem - Pointer to an array of OPTITEMs cOptItem - Number of OPTITEMs pwstrTable - Pointer to memory buffer for storing the table. NULL if we're only interested in table size.
Return Value:
Size of the table bytes, 0 if there is an error.
--*/
{ DWORD dwChars = 0; INT iLength; POPTPARAM pOptParam;
while (dwOptItem--) { ASSERT(ISFONTSUBSTITEM(pOptItem->UserData));
if (pOptItem->Sel > 0) { iLength = wcslen(pOptItem->pName) + 1; dwChars += iLength; if (pwstrTable != NULL) { CopyMemory(pwstrTable, pOptItem->pName, iLength*sizeof(WCHAR)); pwstrTable += iLength; }
pOptParam = pOptItem->pOptType->pOptParam + pOptItem->Sel;
iLength = wcslen(pOptParam->pData) + 1; dwChars += iLength;
if (pwstrTable != NULL) { CopyMemory(pwstrTable, pOptParam->pData, iLength*sizeof(WCHAR)); pwstrTable += iLength; } } pOptItem++; }
//
// Append a NUL character at the end of the table
//
dwChars++;
if (pwstrTable != NULL) *pwstrTable = NUL;
//
// Return the table size in bytes
//
return dwChars * sizeof(WCHAR); }
BOOL BUnpackItemFontSubstTable( IN PUIDATA pUiData )
/*++
Routine Description:
Extract substitution table from treeview items
Arguments:
pUiData - Pointer to UIDATA structure
Return Value:
TRUE if successful, FALSE otherwise
--*/
{ DWORD dwTableSize; PWSTR pwstrTable = NULL; POPTITEM pOptItem = pUiData->pTTFontItems; DWORD dwOptItem = pUiData->dwTTFontItem;
//
// Check if any changes were made to font-substitution items
//
if (! BOptItemSelectionsChanged(pOptItem, dwOptItem)) return TRUE;
//
// Figure out how much memory we need to save the font substitution table
// Assemble the font substitution table
// Save the TrueType font substitution table to registry
//
if ((dwTableSize = DwCollectTrueTypeMappings(pOptItem, dwOptItem, NULL)) == 0 || (pwstrTable = MemAlloc(dwTableSize)) == NULL || (dwTableSize != DwCollectTrueTypeMappings(pOptItem, dwOptItem, pwstrTable)) || !BSaveTTSubstTable(pUiData->ci.hPrinter, pwstrTable, dwTableSize)) { ERR(("Couldn't save font substitution table\n")); MemFree(pwstrTable); return FALSE; }
MemFree(pwstrTable); return TRUE; }
|