windows-nt/Source/XPSP1/NT/printscan/print/drivers/usermode/driverui/fontsub.c

619 lines
13 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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;
}