|
|
/**************************************************************************\
* * Copyright (c) 2000 Microsoft Corporation * * Abstract: * * Font linking handling * * Revision History: * * 3/03/2000 Tarek Mahmoud Sayed * Created it. * \**************************************************************************/
#include "precomp.hpp"
static const WCHAR FontLinkKeyW[] = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink";
static const WCHAR FontSubstitutesKeyW[] = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes"; static const WCHAR EudcKeyW[]=L"EUDC\\"; static const char EudcKeyA[]= "EUDC\\";
static const char WinIniFontSubstitutionSectionName[] = "FontSubstitutes";
/**************************************************************************\
* * Function Description: * Font Linking constructor. * caches the font linking and EUDC from the registry. * * * Arguments: * * Returns: * * * History: * * 3/3/2000 Tarek Mahmoud Sayed * Created it. * \**************************************************************************/
GpFontLink::GpFontLink(): DefaultFamily (NULL), linkedFonts (NULL), eudcCache (NULL), privateFonts (NULL), FontSubstitutionTable (NULL), substitutionCount (0) { // Before we cache the font linking and substitution data we need to
// make sure we loaded the font table data.
GpFontTable *fontTable = Globals::FontCollection->GetFontTable();
if (!fontTable->IsValid()) return;
if (!fontTable->IsFontLoaded()) fontTable->LoadAllFonts();
if (Globals::IsNt) { GetFontLinkingDataFromRegistryW(); GetEudcDataFromTheRegistryW(); CacheFontSubstitutionDataW(); } else { // There is no font linking in Win9x. and we don't support the font association
// because it is for Ansi support and not Unicode.
// we support the font substitution under win9x.
GetEudcDataFromTheRegistryA(); CacheFontSubstitutionDataA(); } }
/**************************************************************************\
* * Function Description: * * If not already cached, create the default family to be used for font * that is not linked by default. * * o Search for the subtitution font of "MS Shell Dlg" * o Use the font the "MS Shell Dlg" substitution is linked to if exist * o If no "MS Shell Dlg" found, use the final font of the first fontlink * entry found if fontlinking is supported in the system. * o If not, lookup hardcoded UI font via system default ansi codepage. * * History: * * 4/19/2001 Worachai Chaoweeraprasit * Created it. * \**************************************************************************/
const AssociatedFamilies *GpFontLink::GetDefaultFamily() { if (!DefaultFamily) { AssociatedFamilies *associated = NULL; GpFontFamily *family = GetFamilySubstitution(L"MS Shell Dlg");
if (family) { associated = GetLinkedFonts(family); } else { // "MS Shell Dlg" not found,
// try the first linking font found if one existed
if (linkedFonts) { family = linkedFonts->family; associated = linkedFonts->associatedFamilies; } else { // No fontlinking supported in this machine. This is likely a Win9x system,
// lookup default UI font via ACP.
typedef struct { UINT AnsiCodepage; const WCHAR* FamilyName; } AssociatedUIFonts;
static const UINT MaxEastAsianCodepages = 4; static const AssociatedUIFonts uiFonts[MaxEastAsianCodepages] = { { 932, L"MS UI Gothic" }, // Japanese
{ 949, L"Gulim" }, // Korean
{ 950, L"PMingLiu" }, // Traditional Chinese
{ 936, L"Simsun" } // Simplified Chinese
};
const WCHAR *familyName = NULL;
for (UINT i = 0; i < MaxEastAsianCodepages; i++) { if (uiFonts[i].AnsiCodepage == Globals::ACP) { familyName = uiFonts[i].FamilyName; break; } }
if (familyName) { GpFontTable *fontTable = Globals::FontCollection->GetFontTable(); if (fontTable) { family = fontTable->GetFontFamily(familyName); } } } }
if (family) { DefaultFamily = &DefaultFamilyBuffer; DefaultFamily->family = family; DefaultFamily->next = associated; } else { // Nothing we could use,
// let's make sure we wouldnt try to cache it again.
DefaultFamily = (AssociatedFamilies *)(-1); } }
ASSERT(DefaultFamily != NULL); return (DefaultFamily && DefaultFamily != (AssociatedFamilies *)(-1)) ? DefaultFamily : NULL; }
/**************************************************************************\
* * Function Description: * Font linking destructor. it should be called when free theGDIPLUS library * it free all allocated data. * * * Arguments: * * Returns: * * * History: * * 3/3/2000 Tarek Mahmoud Sayed * Created it. * \**************************************************************************/
GpFontLink::~GpFontLink() { FontLinkingFamily *tempFontLinkingFamily = linkedFonts; AssociatedFamilies *tempAssocFonts; PrivateLoadedFonts *loadedFontsList;
while (linkedFonts != NULL) { while (linkedFonts->associatedFamilies != NULL) { tempAssocFonts = linkedFonts->associatedFamilies->next; GpFree(linkedFonts->associatedFamilies); linkedFonts->associatedFamilies = tempAssocFonts; } linkedFonts = linkedFonts->next; GpFree(tempFontLinkingFamily); tempFontLinkingFamily = linkedFonts; }
if (eudcCache != NULL) { EUDCMAP *tempEUDCMapList; while (eudcCache->eudcMapList != NULL) { tempEUDCMapList = eudcCache->eudcMapList->next; GpFree(eudcCache->eudcMapList); eudcCache->eudcMapList = tempEUDCMapList; } GpFree(eudcCache); }
while (privateFonts != NULL) { delete privateFonts->fontCollection; loadedFontsList = privateFonts; privateFonts = privateFonts->next; GpFree(loadedFontsList); }
if (FontSubstitutionTable) { GpFree(FontSubstitutionTable); } }
/**************************************************************************\
* * Function Description: * * Read the font linking registry data for the NT * * Arguments: * * Returns: * nothing * * History: * * 3/3/2000 Tarek Mahmoud Sayed * Created it. * \**************************************************************************/
void GpFontLink::GetFontLinkingDataFromRegistryW() { // Open the key
HKEY hkey; ULONG index = 0;
WCHAR subKey[MAX_PATH]; DWORD allocatedDataSize= 2 * MAX_PATH; unsigned char *allocatedBuffer = NULL; DWORD subKeyLength ; DWORD RegDataLength ;
LONG error = RegOpenKeyExW( HKEY_LOCAL_MACHINE, FontLinkKeyW, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hkey);
if (error == ERROR_SUCCESS) { allocatedBuffer = (unsigned char *) GpMalloc(allocatedDataSize); if (allocatedBuffer == NULL) { return; }
while (error != ERROR_NO_MORE_ITEMS) { subKeyLength = MAX_PATH; RegDataLength = allocatedDataSize;
error = RegEnumValueW( hkey, index, subKey, &subKeyLength, NULL, NULL, allocatedBuffer, &RegDataLength); if (error == ERROR_MORE_DATA) { allocatedDataSize *= 2; GpFree(allocatedBuffer); allocatedBuffer = (unsigned char *) GpMalloc(allocatedDataSize); if (allocatedBuffer == NULL) { RegCloseKey(hkey); return; } RegDataLength = allocatedDataSize; error = RegEnumValueW( hkey, index, subKey, &subKeyLength, NULL, NULL, allocatedBuffer, &RegDataLength); } if (error != ERROR_SUCCESS) { break; } index ++;
// record current node.
FontLinkingFamily *tempLinkedFonts; tempLinkedFonts = (FontLinkingFamily *) GpMalloc( sizeof (FontLinkingFamily) ); if (tempLinkedFonts) { AssociatedFamilies * tailAssociatedFamilies = NULL; tempLinkedFonts->family = Globals::FontCollection->GetFontTable()->GetFontFamily(subKey); if (tempLinkedFonts->family == NULL) { GpFree(tempLinkedFonts); continue; } tempLinkedFonts->associatedFamilies = NULL; tempLinkedFonts->next = NULL;
DWORD i = 0; WCHAR nextFontFile[MAX_PATH]; WCHAR awcPath[MAX_PATH]; DWORD charIndex = 0; UINT hash ; GpFontFile* fontFile; AssociatedFamilies *tempAssocFamilies; GpFontFamily *family; BOOL hasFontFileName = FALSE; RegDataLength /= 2; while (charIndex < RegDataLength) { if (((WCHAR *)allocatedBuffer)[charIndex] == 0x002C) { i = 0; hasFontFileName = TRUE; } else if (((WCHAR *)allocatedBuffer)[charIndex] == 0x0000) { if (i > 0) { nextFontFile[i] = 0x0; i = 0; if (hasFontFileName) { family = Globals::FontCollection->GetFontTable()->GetFontFamily(nextFontFile); hasFontFileName = FALSE; } else { family = NULL; INT j =0; WCHAR charNumber;
if (MakePathName(awcPath, nextFontFile)) { UnicodeStringToUpper(awcPath, awcPath); fontFile = Globals::FontCollection->GetFontTable()->GetFontFile(awcPath); if (fontFile != NULL) { family = Globals::FontCollection->GetFontTable()->GetFontFamily(fontFile->GetFamilyName(0)); } else { fontFile = Globals::FontCollection->GetFontTable()->AddFontFile(awcPath); if (fontFile != NULL) { family = Globals::FontCollection->GetFontTable()->GetFontFamily(fontFile->GetFamilyName(0)); } } } }
if (family != NULL) { tempAssocFamilies = (AssociatedFamilies *) GpMalloc( sizeof (AssociatedFamilies) ); if (tempAssocFamilies != NULL) { if (!tailAssociatedFamilies) { tempAssocFamilies->family = family; tempAssocFamilies->next = tempLinkedFonts->associatedFamilies; tempLinkedFonts->associatedFamilies = tempAssocFamilies; } else { tempAssocFamilies->family = family; tempAssocFamilies->next = NULL; tailAssociatedFamilies->next = tempAssocFamilies; }
tailAssociatedFamilies = tempAssocFamilies; } } } } else // ! 0
{ nextFontFile[i] = ((WCHAR *)allocatedBuffer)[charIndex]; i++; } charIndex++; } tempLinkedFonts->next = linkedFonts; linkedFonts = tempLinkedFonts; } }
if (allocatedBuffer != NULL) { GpFree(allocatedBuffer); } RegCloseKey(hkey); } return; }
/**************************************************************************\
* * Function Description: * return the linked list of all fonts linked to family * * * Arguments: * family[in] the original family * * Returns: * AssociatedFamilies* the linked list of the linked fonts * * History: * * 3/3/2000 Tarek Mahmoud Sayed * Created it. * \**************************************************************************/
AssociatedFamilies* GpFontLink::GetLinkedFonts(const GpFontFamily *family) { GpFontFamily *linkedFamily; if (family->IsPrivate()) { WCHAR name[LF_FACESIZE]; if (family->GetFamilyName(name) != Ok) { return NULL; }
GpInstalledFontCollection *gpFontCollection = GpInstalledFontCollection::GetGpInstalledFontCollection();
if (gpFontCollection == NULL) { return NULL; } GpFontTable *fontTable = gpFontCollection->GetFontTable();
if (fontTable == NULL) { return NULL; }
linkedFamily = fontTable->GetFontFamily(name); if (linkedFamily == NULL) { return NULL; } } else { linkedFamily = (GpFontFamily *) family; }
FontLinkingFamily *currentFontLink = linkedFonts; while (currentFontLink != NULL) { if (currentFontLink->family == linkedFamily) { return currentFontLink->associatedFamilies; } currentFontLink = currentFontLink->next; } return NULL; }
/**************************************************************************\
* * Function Description: * caches EUDC data from the registry * * * Arguments: * * Returns: * * * History: * * 3/3/2000 Tarek Mahmoud Sayed * Created it. * \**************************************************************************/
void GpFontLink::GetEudcDataFromTheRegistryW() { eudcCache = (EUDC *) GpMalloc(sizeof(EUDC)); if (eudcCache == NULL) { return; }
eudcCache->defaultFamily = NULL; eudcCache->eudcMapList = NULL;
WCHAR tempString[MAX_PATH]; INT i = 0; while ( EudcKeyW[i] != 0x0000) { tempString[i] = EudcKeyW[i]; i++; }
INT j = 0; WCHAR acpString[5]; UINT acp = GetACP();
while (j < 5 && acp > 0) { acpString[j] = (acp % 10) + 0x0030; acp /= 10; j++; }
j--; while (j>=0) { tempString[i] = acpString[j]; i++; j--; }
tempString[i] = 0x0;
HKEY hkey = NULL; ULONG index = 0; LONG error = RegOpenKeyExW( HKEY_CURRENT_USER, tempString, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hkey);
WCHAR subKey[MAX_PATH]; DWORD subKeyLength ; DWORD RegDataLength ; GpFontFamily *family; GpFontFamily *linkedfamily; EUDCMAP *eudcMap; BOOL isDefaultNotCached = TRUE;
while (error == ERROR_SUCCESS) { subKeyLength = MAX_PATH; RegDataLength = MAX_PATH; error = RegEnumValueW(hkey, index, subKey, &subKeyLength, NULL, NULL, (unsigned char *) tempString, &RegDataLength);
if (error == ERROR_SUCCESS) { if (isDefaultNotCached && UnicodeStringCompareCI(subKey, L"SystemDefaultEUDCFont") == 0) { isDefaultNotCached = FALSE; family = CheckAndLoadTheFile(tempString); if (family != NULL) { eudcCache->defaultFamily = family; } } else { family = Globals::FontCollection->GetFontTable()->GetFontFamily(subKey); if (family != NULL) { linkedfamily = CheckAndLoadTheFile(tempString); if (linkedfamily != NULL) { eudcMap = (EUDCMAP *) GpMalloc(sizeof(EUDCMAP)); if (eudcMap != NULL) { eudcMap->inputFamily = family; eudcMap->eudcFamily = linkedfamily; if (eudcCache->eudcMapList == NULL) { eudcCache->eudcMapList = eudcMap; eudcMap->next = NULL; } else { eudcMap->next = eudcCache->eudcMapList; eudcCache->eudcMapList = eudcMap; } } } } } }
index++; }
if (hkey != NULL) { RegCloseKey(hkey); }
return; }
/**************************************************************************\
* * Function Description: * caches EUDC data from the registry * * * Arguments: * * Returns: * * * History: * * 3/3/2000 Tarek Mahmoud Sayed * Created it. * \**************************************************************************/
void GpFontLink::GetEudcDataFromTheRegistryA() { eudcCache = (EUDC *) GpMalloc(sizeof(EUDC)); if (eudcCache == NULL) { return; }
eudcCache->defaultFamily = NULL; eudcCache->eudcMapList = NULL;
char tempStringA[MAX_PATH]; WCHAR tempString[MAX_PATH]; INT i = 0; while ( EudcKeyA[i] != 0x00) { tempStringA[i] = EudcKeyA[i]; i++; }
INT j = 0; char acpString[5]; UINT acp = GetACP();
while (j < 5 && acp > 0) { acpString[j] = (acp % 10) + 0x30; acp /= 10; j++; }
j--; while (j>=0) { tempStringA[i] = acpString[j]; i++; j--; }
tempStringA[i] = 0x0;
HKEY hkey = NULL; ULONG index = 0; LONG error = RegOpenKeyExA( HKEY_CURRENT_USER, tempStringA, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hkey);
WCHAR subKey[MAX_PATH]; char subKeyA[MAX_PATH]; DWORD subKeyLength ; DWORD RegDataLength ; GpFontFamily *family; GpFontFamily *linkedfamily; EUDCMAP *eudcMap; BOOL isDefaultNotCached = TRUE;
while (error == ERROR_SUCCESS) { subKeyLength = MAX_PATH; RegDataLength = MAX_PATH; error = RegEnumValueA( hkey, index, subKeyA, &subKeyLength, NULL, NULL, (unsigned char *) tempStringA, &RegDataLength);
if (error == ERROR_SUCCESS) { if (!AnsiToUnicodeStr( subKeyA, subKey, MAX_PATH) ||
!AnsiToUnicodeStr( tempStringA, tempString, MAX_PATH)) continue; if (isDefaultNotCached && UnicodeStringCompareCI(subKey, L"SystemDefaultEUDCFont") == 0) { isDefaultNotCached = FALSE; family = CheckAndLoadTheFile(tempString); if (family != NULL) { eudcCache->defaultFamily = family; } } else { family = Globals::FontCollection->GetFontTable()->GetFontFamily(subKey); if (family != NULL) { linkedfamily = CheckAndLoadTheFile(tempString); if (linkedfamily != NULL) { eudcMap = (EUDCMAP *) GpMalloc(sizeof(EUDCMAP)); if (eudcMap != NULL) { eudcMap->inputFamily = family; eudcMap->eudcFamily = linkedfamily; if (eudcCache->eudcMapList == NULL) { eudcCache->eudcMapList = eudcMap; eudcMap->next = NULL; } else { eudcMap->next = eudcCache->eudcMapList; eudcCache->eudcMapList = eudcMap; } } } } } }
index++; } if (hkey != NULL) { RegCloseKey(hkey); } return; }
/**************************************************************************\
* * Function Description: * check if the font file name is loaded, * and load it if it is not loaded before. * * * Arguments: * fileName[In] font file name * * Returns: * GpFontFamily* the family object for that font * * History: * * 3/3/2000 Tarek Mahmoud Sayed * Created it. * \**************************************************************************/
GpFontFamily* GpFontLink::CheckAndLoadTheFile(WCHAR *fileName) { WCHAR awcPath[MAX_PATH]; UINT hash ; GpFontFamily *family = NULL; GpFontFile *fontFile; GpFontTable *fontTable; if (MakePathName(awcPath, fileName)) { PrivateLoadedFonts *currentCell = privateFonts; while (currentCell != NULL) { if ( UnicodeStringCompareCI(fileName, currentCell->FileName) == 0 ) { fontTable = currentCell->fontCollection->GetFontTable(); fontFile = fontTable->GetFontFile(awcPath); if (fontFile) { family = fontTable->GetFontFamily(fontFile->GetFamilyName(0)); }; break; } else { currentCell = currentCell->next; } } if (family == NULL) { GpPrivateFontCollection *privateFontCollection = new GpPrivateFontCollection(); if (privateFontCollection != NULL) { if (privateFontCollection->AddFontFile(awcPath) == Ok) { fontTable = privateFontCollection->GetFontTable(); fontFile = fontTable->GetFontFile(awcPath); if (fontFile != NULL) { family = fontTable->GetFontFamily(fontFile->GetFamilyName(0)); PrivateLoadedFonts *tempLoadedFonts = (PrivateLoadedFonts *) GpMalloc(sizeof(PrivateLoadedFonts)); if (tempLoadedFonts != NULL) { tempLoadedFonts->fontCollection = privateFontCollection; UnicodeStringCopy(tempLoadedFonts->FileName, fileName); tempLoadedFonts->next = privateFonts; privateFonts = tempLoadedFonts; } else { delete privateFontCollection; } } else { delete privateFontCollection; } } else { delete privateFontCollection; } } } } return family; }
/**************************************************************************\
* * Function Description: * return the default family used as fallback for the EUDC * * * Arguments: * * Returns: * GpFontFamily* the family of the EUDC font * * History: * * 3/3/2000 Tarek Mahmoud Sayed * Created it. * \**************************************************************************/ GpFontFamily *GpFontLink::GetDefaultEUDCFamily() {
if (eudcCache != NULL) { return eudcCache->defaultFamily; } return NULL; }
/**************************************************************************\
* * Function Description: * return the family of the EUDC font mapped from the font family * * Arguments: * family[In] original font family * * Returns: * GpFontFamily* the family of the EUDC font * * History: * * 3/3/2000 Tarek Mahmoud Sayed * Created it. * \**************************************************************************/ GpFontFamily *GpFontLink::GetMappedEUDCFamily(const GpFontFamily *family) { EUDCMAP *eudcMaping; if (eudcCache != NULL) { eudcMaping = eudcCache->eudcMapList; while (eudcMaping != NULL) { if (eudcMaping->inputFamily == family) { return eudcMaping->eudcFamily; } eudcMaping = eudcMaping->next; } } return NULL; }
/**************************************************************************\
* * Function Description: * Read and cache the font substitution data from the registry under * Windows NT * * Arguments: * * Returns: * * History: * * 4/12/2000 Tarek Mahmoud Sayed * Created it. * \**************************************************************************/
void GpFontLink::CacheFontSubstitutionDataW() { HKEY hkey;
// open this key for query and enumeration.
LONG error = RegOpenKeyExW( HKEY_LOCAL_MACHINE, FontSubstitutesKeyW, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hkey);
if (error != ERROR_SUCCESS) { // failed to find these data in the registry.
return; }
DWORD numberOfValues = 0; error = RegQueryInfoKeyW( hkey, NULL, NULL, NULL, NULL, NULL, NULL, &numberOfValues, NULL, NULL, NULL, NULL);
if (error != ERROR_SUCCESS || numberOfValues==0) { RegCloseKey(hkey); return; }
// Now let's allocate for data.
// we allocate memory enough to hold all font substitution data but might
// not use all the allocated memory. I did that to just call the GpMalloc
// one time.
FontSubstitutionTable = (FontSubstitutionEntry*) GpMalloc(numberOfValues*sizeof(FontSubstitutionEntry));
if (FontSubstitutionTable == NULL) { // we can't support font substitution while we out of memory.
RegCloseKey(hkey); return; }
// Time to read the data from the registry.
ULONG index = 0; WCHAR subKey[MAX_PATH]; WCHAR subKeyValue[MAX_PATH]; DWORD subKeyLength ; DWORD regDataLength ; while (error == ERROR_SUCCESS) { subKeyLength = MAX_PATH; regDataLength = MAX_PATH;
error = RegEnumValueW( hkey, index, subKey, &subKeyLength, NULL, NULL, (unsigned char *) subKeyValue, ®DataLength); if (error != ERROR_SUCCESS) { break; } index ++;
// If the font substitution mentioned the charset, then neglect the charset
// and keep the family name only.
for (INT i=regDataLength-1; i>=0; i--) { if (subKeyValue[i] == 0x002C) // ','
{ subKeyValue[i] = 0x0000; break; } } // we found one. then try to get substitution GpFontFamily
GpFontFamily *family;
ASSERT(Globals::FontCollection != NULL); family = Globals::FontCollection->GetFontTable()->GetFontFamily(subKeyValue); if (family != NULL) { FontSubstitutionTable[substitutionCount].family = family; DWORD j; for (j=0 ; j<subKeyLength; j++) { if (subKey[j] == 0x002C) // ','
{ break; } else { FontSubstitutionTable[substitutionCount].familyName[j] = subKey[j]; } } FontSubstitutionTable[substitutionCount].familyName[j] = 0x0000; FontSubstitutionTable[substitutionCount].familyNameLength = j; substitutionCount++; } }
RegCloseKey(hkey); return; }
/**************************************************************************\
* * Function Description: * Read and cache the font substitution data from win.ini under Windows 9x * * Arguments: * * Returns: * * History: * * 6/1/2000 Tarek Mahmoud Sayed * Created it. * \**************************************************************************/
void GpFontLink::CacheFontSubstitutionDataA() { DWORD bufferSize = 2048; // 2K to allocate for data reading
DWORD count = 2048; char *buffer = (char*) GpMalloc(bufferSize); if (!buffer) { // OutOfMemory
return; }
// This loop insure we did read all the requested data in the win.ini
while (bufferSize == count) { count = GetProfileSectionA( WinIniFontSubstitutionSectionName, buffer, bufferSize); if (count == 0) { // something wrong
GpFree(buffer); return; }
if (bufferSize-2 <= count) { // we didn't read all data, make the buffer bigger
GpFree(buffer); bufferSize += 1024; if (bufferSize > 32*1024) { // the upper limit for Windows 95 is 32 KB
return; } count = bufferSize; // to continue the loop
buffer = (char *) GpMalloc(bufferSize); if (buffer == NULL) { // Out of memory
return; } } }
// Now we have the filled data buffer and the count. start parsing
// first we need to know how much memory need to allocate for caching
// then we fill this cache with useful data.
DWORD i = 0; INT entriesCount = 0; while (i<count) { while (i<count && buffer[i] != 0) { i++; } entriesCount++; i++; }
// Now allocate for the font substitution cache according to entriesCount
FontSubstitutionTable = (FontSubstitutionEntry*) GpMalloc(entriesCount*sizeof(FontSubstitutionEntry));
if (FontSubstitutionTable == NULL) { // we can't support font substitution while we out of memory.
GpFree(buffer); return; }
ASSERT(Globals::FontCollection != NULL);
char *fontName; char *fontSubstitutionName; WCHAR familyName[MAX_PATH]; GpFontFamily *family; substitutionCount = 0; i = 0;
while (i<count) { fontName = &buffer[i]; while ( i<count && buffer[i] != '=' && buffer[i] != ',') { i++; }
if (i>=count-1) { // something wrong in the data.
break; }
if (buffer[i] == ',') { buffer[i] = 0x0; i++; while (i<count && buffer[i] != '=') { i++; } if (i>=count-1) { // something wrong in the data.
break; } }
buffer[i] = 0x0; i++;
fontSubstitutionName = &buffer[i]; while ( i<count && buffer[i] != 0x0 && buffer[i] != ',') { i++; }
if (i>=count) { i++; // last line may not have a null terminator
// we sure we have a buffer has space more than the count
buffer[i] = 0x0; } if (buffer[i] == ',') { buffer[i] = 0x0; i++; while (i<count && buffer[i] != 0x0) { i++; } }
i++; if (!AnsiToUnicodeStr( fontSubstitutionName, familyName, MAX_PATH)) { continue; }
family = Globals::FontCollection->GetFontTable()->GetFontFamily(familyName); if (family != NULL) { if (!AnsiToUnicodeStr( fontName, FontSubstitutionTable[substitutionCount].familyName, MAX_PATH)) { continue; }
FontSubstitutionTable[substitutionCount].family = family; INT j=0; while (FontSubstitutionTable[substitutionCount].familyName[j] != 0x0000) { j++; } FontSubstitutionTable[substitutionCount].familyNameLength = j; substitutionCount++; } }
// clean up the allocated buffer
GpFree(buffer); return; }
/**************************************************************************\
* * Function Description: * Search for matched substitution font family * * Arguments: * familyName [in] name of the font to be substituted * * Returns: * font family in success, NULL otherwise * * History: * * 4/12/2000 Tarek Mahmoud Sayed * Created it. * \**************************************************************************/
GpFontFamily *GpFontLink::GetFamilySubstitution(const WCHAR* familyName) const { INT nameLength = UnicodeStringLength(familyName);
for (INT i=0 ; i<substitutionCount ; i++) { // to speed up the search, we use the string length comparison before
// comparing the string itself.
if (nameLength == FontSubstitutionTable[i].familyNameLength && UnicodeStringCompareCI(FontSubstitutionTable[i].familyName, familyName) == 0) { ASSERT(FontSubstitutionTable[i].family != NULL); return FontSubstitutionTable[i].family; } }
// Not found;
return NULL; }
|