// $Id: fontman.cpp 1642 2006-08-02 10:15:44Z alex $ /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE ================================XARAHEADERSTART=========================== Xara LX, a vector drawing and manipulation program. Copyright (C) 1993-2006 Xara Group Ltd. Copyright on certain contributions may be held in joint with their respective authors. See AUTHORS file for details. LICENSE TO USE AND MODIFY SOFTWARE ---------------------------------- This file is part of Xara LX. Xara LX is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. Xara LX and its component source files are 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Xara LX (see the file GPL in the root directory of the distribution); if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ADDITIONAL RIGHTS ----------------- Conditional upon your continuing compliance with the GNU General Public License described above, Xara Group Ltd grants to you certain additional rights. The additional rights are to use, modify, and distribute the software together with the wxWidgets library, the wxXtra library, and the "CDraw" library and any other such library that any version of Xara LX relased by Xara Group Ltd requires in order to compile and execute, including the static linking of that library to XaraLX. In the case of the "CDraw" library, you may satisfy obligation under the GNU General Public License to provide source code by providing a binary copy of the library concerned and a copy of the license accompanying it. Nothing in this section restricts any of the rights you have under the GNU General Public License. SCOPE OF LICENSE ---------------- This license applies to this program (XaraLX) and its constituent source files only, and does not necessarily apply to other Xara products which may in part share the same code base, and are subject to their own licensing terms. This license does not apply to files in the wxXtra directory, which are built into a separate library, and are subject to the wxWindows license contained within that directory in the file "WXXTRA-LICENSE". This license does not apply to the binary libraries (if any) within the "libs" directory, which are subject to a separate license contained within that directory in the file "LIBS-LICENSE". ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS ---------------------------------------------- Subject to the terms of the GNU Public License (see above), you are free to do whatever you like with your modifications. However, you may (at your option) wish contribute them to Xara's source tree. You can find details of how to do this at: http://www.xaraxtreme.org/developers/ Prior to contributing your modifications, you will need to complete our contributor agreement. This can be found at: http://www.xaraxtreme.org/developers/contribute/ Please note that Xara will not accept modifications which modify any of the text between the start and end of this header (marked XARAHEADERSTART and XARAHEADEREND). MARKS ----- Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara designs are registered or unregistered trademarks, design-marks, and/or service marks of Xara Group Ltd. All rights in these marks are reserved. Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. http://www.xara.com/ =================================XARAHEADEREND============================ */ // implementation file for Camelots Font Managler, supposidly /* */ #include "camtypes.h" // #include "fontbase.h" - included in fontman.h #include "nodetxts.h" #include "nodetxtl.h" #include "nodetext.h" #include "fontman.h" //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "txtattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "richard2.h" DECLARE_SOURCE( "$Revision: 1642 $" ); CC_IMPLEMENT_DYNCREATE( CachedFontItem, ListItem ) CC_IMPLEMENT_DYNCREATE( FontManager, CCObject ) CC_IMPLEMENT_DYNCREATE( EnumAllFonts, OILEnumFonts ) // Declare smart memory handling in Debug builds #define new CAM_DEBUG_NEW /* THEORY N ALL (1) The font manager controls its fonts in a simple list. Each entry contains a font description which knows what kind of font it is. (2) All access to fonts should be via the font manager, which in turn asks each font list item. (3) For speed and general lack of gobbling memory, the font list is initialised with font names only. If someone actually wants information about a fonts metrics or its log font structure (heaven forbid) they call the fontmanagers functions to return these items. If the items are null at the time then the info has not been cached yet and will immediately get cached (cor cache on demand!). A little slower for the first use but nice there after. (4) A font name is now no longer enough to uniquely specify a font. The name and class need to be used as you can be using an ATM font called Courier as well as a True Type font of the same name. Eeek. (5) Any new stuff added should NOT be naughty and follow its own guide lines. The idea is simple. Provide a function in the font manager that the external user can call, then implement the same function inside CachedFontItem (ie the font manager usually asks the font item if it wants information from it (it does not simply dig the data straight out itself!). The font item then asks a virtual function derived from FontBase cause the actually font class only knows whats going on at the device level. That way we might even be able to get risc os fonts working one day. Ha Ha Ha Ha! (6) THOU SHALL'T NOT CHANGE SCOPE! Anyone found leaping into structures having promoted things from private to public will be shot. (7) To add a new font controller, simply derive from FontBase and implement the necessary functionality, simple as that although currently we do not have our own internal font descriptors, we currently rely on the one API structure: ENUMLOGFONT The structure OUTLINETEXTMETRIC is cached on demand, since its 'expensive' to retrieve. The only time we need to do it for all the fonts should be when the new file format needs to do some smart font subsitution. */ /******************************************************************************************** > CachedFontItem::CachedFontItem() Author: Mike_Kenny (Xara Group Ltd) Created: 12/09/95 Purpose: Default constructor ********************************************************************************************/ CachedFontItem::CachedFontItem() { pFontClass = NULL; Handle = ILLEGALFHANDLE; pEnumLogFont = NULL; pOutlineTextMetric = NULL; FlagIsCorrupt = FALSE; FlagIsReplaced = FALSE; } CachedFontItem::~CachedFontItem() { Delete(); } /******************************************************************************************** For all the rest of these functions see their FontManager equivalents ********************************************************************************************/ /******************************************************************************************** > ENUMLOGFONT* CachedFontItem::GetEnumLogFont() Author: Mike_Kenny (Xara Group Ltd) Created: 12/09/95 Inputs: - Returns: A pointer to the ENUMLOGFONT structure for this font Purpose: Returns the ENUMLOGFONT structure for this cached font. ********************************************************************************************/ ENUMLOGFONT* CachedFontItem::GetEnumLogFont() { ERROR2IF(pFontClass==NULL, NULL, "structure exists without a FontClass!!!"); if (pEnumLogFont!=NULL) return pEnumLogFont; return NULL; } /******************************************************************************************** > OUTLINETEXTMETRIC* CachedFontItem::GetOutlineTextMetric() Author: Andy_Hayward (Xara Group Ltd) Created: 15/08/96 Inputs: - Returns: A pointer to the OUTLINETEXTMETRIC structure for this font, or NULL if one doesn't exist (non-truetype fonts). Purpose: Returns the OUTLINETEXTMETRIC structure for this cached font. ********************************************************************************************/ OUTLINETEXTMETRIC* CachedFontItem::GetOutlineTextMetric() { ERROR2IF(pFontClass==NULL, NULL, "this.pFontClass==NULL."); ERROR2IF(pEnumLogFont==NULL, NULL, "this.pEnumLogFont==NULL."); if (pOutlineTextMetric==NULL) { // ask the font class for this structure, and cache it FontClass Class = GetFontClass(); pOutlineTextMetric=OILFontMan::GetOutlineTextMetric(Class, &(pEnumLogFont->elfLogFont)); } // return the result. return pOutlineTextMetric; } /******************************************************************************************** > String_64* CachedFontItem::GetFontName() Author: Mike_Kenny (Xara Group Ltd) Created: 12/09/95 Inputs: - Returns: A font name Purpose: Get this items name ********************************************************************************************/ String_64* CachedFontItem::GetFontName() { ERROR2IF(pFontClass==NULL, NULL, "structure exists without a FontClass!!!"); return pFontClass->GetFontName(); } /******************************************************************************************** > FontClass CachedFontItem::GetFontClass() Author: Mike_Kenny (Xara Group Ltd) Created: 12/09/95 Inputs: - Returns: A font class Purpose: Get this items class ********************************************************************************************/ FontClass CachedFontItem::GetFontClass() { ERROR3IF(pFontClass==NULL, "structure exists without a FontClass!!!"); return pFontClass->GetFontClass(); } /******************************************************************************************** > void CachedFontItem::DeleteMetrics() Author: Mike_Kenny (Xara Group Ltd) Created: 12/09/95 Inputs: - Returns: - Purpose: Delete this items LOGFONT cached structure ********************************************************************************************/ void CachedFontItem::DeleteMetrics() { if( NULL == pFontClass ) { TRACE( _T("structure exists without a FontClass!!!") ); } if (pEnumLogFont!=NULL) { delete pEnumLogFont; pEnumLogFont = NULL; } if (pOutlineTextMetric!=NULL) { delete pOutlineTextMetric; pOutlineTextMetric = NULL; } } void CachedFontItem::DeleteFontClass() { if (pFontClass!=NULL) { delete pFontClass; pFontClass=NULL; } } void CachedFontItem::Delete() { DeleteMetrics(); DeleteFontClass(); } /******************************************************************************************** > BOOL CachedFontItem::IsFullyCached() Author: Mike_Kenny (Xara Group Ltd) Created: 12/09/95 Inputs: - Returns: TRUE if this item is fully cached, FALSE if not Purpose: See if this item has all its cached structures resident ********************************************************************************************/ BOOL CachedFontItem::IsFullyCached() { PORTNOTE("text","CachedFontItem::IsFullyCached - do nothing"); #ifndef DISABLE_TEXT_RENDERING // TRACEUSER("wuerthne", _T("CachedFontItem::IsFullyCached called") ); ERROR2IF(pFontClass==NULL, FALSE, "A CachedFontItem structure exists without a FontClass!!!"); return (pEnumLogFont!=NULL); #else return TRUE; #endif } /******************************************************************************************** > BOOL CachedFontItem::Compare(String_64* pFontName) Author: Mike_Kenny (Xara Group Ltd) Created: 12/09/95 Inputs: pFontName = A pointer to a font name Returns: TRUE if the font name on entry matchs that of this cached font FALSE if not Purpose: See if this font has the same name as that passed as a param. ********************************************************************************************/ BOOL CachedFontItem::Compare(String_64 *pFontName) { if( pFontClass == NULL ) { TRACE( _T("A CachedFontItem structure exists without a FontClass!!!") ); return FALSE; } return pFontClass->Compare( pFontName ); } /******************************************************************************************** > void CachedFontItem::Dump() Author: Mike_Kenny (Xara Group Ltd) Created: 12/09/95 Purpose: Dump the contents of this cache entry out ********************************************************************************************/ void CachedFontItem::Dump() { #ifdef _DEBUG ERROR3IF(pFontClass==NULL, "A CachedFontItem structure exists without a FontClass!!!"); TRACE( _T("Font item:\n Handle = %d\n"),Handle); if (IsFullyCached()) { TRACE( _T(" Fully cached\n")); OILFontMan::DumpEnumLogFont(pEnumLogFont); } else { TRACE( _T(" Not fully cached\n")); } pFontClass->Dump(); #endif } /******************************************************************************************** > BOOL CachedFontItem::SetCacheData(ENUMLOGFONT FAR* lpelf) Author: Mike_Kenny (Xara Group Ltd) Created: 12/09/95 Inputs: lpelf = a pointer to the logical font description Returns: TRUE if we manage to cache this data FALSE if not (out of memory) Purpose: This function is called to set the cached data (or metrics) for a particular font item. The metrics will have been returned to us from an oil layer font manager after a request from us to it to cache them. ********************************************************************************************/ BOOL CachedFontItem::SetCacheData(ENUMLOGFONT FAR* lpelf) { ERROR2IF(lpelf==NULL,FALSE,"CachedFontItem::SetCacheData() given a null ENUMLOGFONT structure"); ERROR3IF(pFontClass==NULL, "A CachedFontItem structure exists without a FontClass!!!"); if (pEnumLogFont!=NULL) { ERROR3("Replacing ENUMLOGFONT structure inside CachedFontItem::SetCacheData()"); delete pEnumLogFont; pEnumLogFont=NULL; } // try a claim memory for the new structure ENUMLOGFONT * MyEnumLogFont = new ENUMLOGFONT; if (MyEnumLogFont==NULL) { return FALSE; } // copy the the contents of the structures given as arguments into the new structures *MyEnumLogFont = *lpelf; // and point the pointers to these new structures pEnumLogFont = MyEnumLogFont; return TRUE; } // ---------------------- End of CachedFontItem functions ----------------------------------- /******************************************************************************************** > FontManager::FontManager() Author: Mike_Kenny (Xara Group Ltd) Created: 12/09/95 Purpose: Constructor for the font manager class ********************************************************************************************/ FontManager::FontManager() { UniqueHandle = FIRSTFONTHANDLE; DefaultHandle = DEFAULTHANDLE; TempFontClass = FC_UNDEFINED; } FontManager::~FontManager() { TheFontList.DeleteAll(); } /******************************************************************************************** > BOOL FontManager::LegalFontClass(INT32 Class, FontClass& RealClass) Author: Mike_Kenny (Xara Group Ltd) Created: 12/09/95 Inputs: A INT32 describing the font class Outputs: The real font class to use for this numeric value Returns: TRUE if the font class is supported, FALSE if not Purpose: Check whether a numeric value actually indicates a valid class of font ie lies in the range of supported font types. This is used generally for loading purpose where the font class is loaded as a numeric value. ********************************************************************************************/ BOOL FontManager::LegalFontClass(INT32 Class, FontClass& RealClass) { return OILFontMan::LegalFontClass(Class, RealClass); } /******************************************************************************************** > WORD FontManager::GetNextHandle() Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: - Outputs: The next font handle. Returns: - Purpose: Return a unique handle for the font cache handler Handles range from 1..n, 0 is explicitly reserved for the default handle, 0x7FFF is defined as an illegal handle. ********************************************************************************************/ WORD FontManager::GetNextHandle() { WORD CurrHandle=UniqueHandle; UniqueHandle++; return (CurrHandle); } /******************************************************************************************** > BOOL FontManager::Init() Author: Mike_Kenny (Xara Group Ltd) Created: 12/09/95 Inputs: - Outputs: - Returns: TRUE if the fontmanager was able to initialise correctly FALSE if not Purpose: Get Camelots Font manager going. We simply cache the default font so unknown fonts can be sensibly replaced. ********************************************************************************************/ BOOL FontManager::Init() { // initialise the OIL cache of enumerated fonts by simply enumerating them // and ignoring the result - since we do not want to see the names, we do // not even have to create a subclass OILEnumFonts enumerator; enumerator.Execute(); if (!CacheDefaultFont()) { ERROR3("FontManager::Init() - Unable to cache the default font"); } return TRUE; } /******************************************************************************************** > CachedFontItem* FontManager::GetFirstFont() Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Returns: A pointer to the first cached font item (NULL if none) ********************************************************************************************/ CachedFontItem* FontManager::GetFirstFont() { return (CachedFontItem*)TheFontList.GetHead(); } /******************************************************************************************** > CachedFontItem* FontManager::GetNextFont(CachedFontItem *pItem) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: A pointer to a font item to find the next from. Returns: A pointer to the next cached font item from pItem (NULL if none) ********************************************************************************************/ CachedFontItem* FontManager::GetNextFont(CachedFontItem* pItem) { return (CachedFontItem*)TheFontList.GetNext(pItem); } /******************************************************************************************** > CachedFontItem* FontManager::AddFont(String_64* Name, FontClass fclass, WORD& Handle) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: Name = a pointer to the font name fclass = a reference to the class of font to add Outputs: Handle = ILLEGALFHANDLE if the font could not be added Handle = The font handle if ok Returns: NULL if the font could not be added A pointer to the font record Purpose: Creates a new font item for this named font. The font will not be fully cached. To cache all the data for the font, call CacheFontData(Handle) ********************************************************************************************/ CachedFontItem* FontManager::AddFont(String_64* Name, FontClass fclass, WORD& retHandle) { TRACEUSER("wuerthne", _T("FontManager::AddFont %s"), (TCHAR*)*Name); CachedFontItem* pItem = new CachedFontItem; if (pItem==NULL) return NULL; FontBase* pClass = OILFontMan::CreateNewFont(fclass,Name); if (pClass==NULL) { delete pItem; pItem=NULL; return NULL; } pItem->pFontClass = pClass; pItem->Handle = GetNextHandle(); TheFontList.AddTail(pItem); retHandle = pItem->Handle; TRACEUSER("wuerthne", _T("AddFont, returning %d"), retHandle); return pItem; } /******************************************************************************************** > CachedFontItem* FontManager::FindFont(WORD Handle) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: Handle = The font manager font handle Outputs: - Returns: A pointer to the font managers cached font record for this handle Purpose: Find the entry in the font managers font cache which corresponds to this handle. ********************************************************************************************/ CachedFontItem* FontManager::FindFont(WORD Handle) { // Check the cache first CachedFontItem* pItem = GetFirstFont(); while (pItem!=NULL) { if (pItem->Handle == Handle) return pItem; pItem = GetNextFont(pItem); } return NULL; } /******************************************************************************************** > CachedFontItem* FontManager::FindFont(String_64* pFontName, FontClass Class=FC_UNDEFINED) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: pFontName = a pointer to a font name Class = describes the type of class (see typedef for details) FC_UNDEFINED then ignore the class match and match the first item with the same name whatever font class it is Outputs: - Returns: A pointer to the font managers cached font record for this font NULL if unable to find the font Purpose: Find the entry in the font managers font list which corresponds to this fontname and font class Note: One might be tempted to include the default font item in the comparison and return the default font handle when the default font name is passed, but this does not happen and this is by design. See OnDocumentLoaded for further information. ********************************************************************************************/ CachedFontItem* FontManager::FindFont(String_64* pFontName, FontClass Class) { CachedFontItem* pItem = GetFirstFont(); if (Class==FC_UNDEFINED) { while (pItem!=NULL) { if (pItem->Compare(pFontName)) return pItem; pItem = GetNextFont(pItem); } } else { while (pItem!=NULL) { if (pItem->Compare(pFontName)) { if (pItem->GetFontClass() == Class) return pItem; } pItem = GetNextFont(pItem); } } return NULL; } /******************************************************************************************** > CachedFontItem* FontManager::GetCachedFont(WORD Handle) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: Handle = The font manager font handle Outputs: - Returns: A pointer to a cached font record or NULL Purpose: This function returns the font associated with the handle passed. If the font is not in the cache it will return NULL. It differs from GetFont in that it will not attempt to return the DefaultFontItem if it cannot find the item specified. ********************************************************************************************/ CachedFontItem* FontManager::GetCachedFont(WORD Handle) { if (Handle==DefaultHandle) return (&DefaultFontItem); return FindFont(Handle); } /******************************************************************************************** > WORD FontManager::GetFontHandle(String_64* pFontName, FontClass Class=FC_UNDEFINED) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: pFontName = a pointer to a font name Class = describes the class of font to get the handle of Outputs: - Returns: The handle of the font if the font exists The default handle if the font does not exist and Replace is true ILLEGALFHANDLE if not Purpose: Get the handle on a cached font (if cached) otherwise return the default font handle. ********************************************************************************************/ WORD FontManager::GetFontHandle(String_64* pFontName, FontClass Class) { ERROR2IF(pFontName==NULL, 0, "FontManager::GetFontHandle() called with an illegal font name pointer"); CachedFontItem* pItem=FindFont(pFontName,Class); if (pItem!=NULL) return pItem->GetFontHandle(); return DefaultHandle; } /******************************************************************************************** > CachedFontItem* FontManager::GetFont() Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: - Outputs: - Returns: A pointer to a cached font record or NULL Purpose: Return the precached default font data to use for rendering. ********************************************************************************************/ CachedFontItem* FontManager::GetFont() { return &DefaultFontItem; } /******************************************************************************************** > CachedFontItem* FontManager::GetFont(WORD Handle) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: Handle = The font manager font handle Outputs: - Returns: A pointer to a cached font record or NULL Purpose: Return the font data to use for rendering. This function performs a specific job in avoiding caching the font data. If the font is already cached then fine, it is returned for use. If not, the default font is returned. ********************************************************************************************/ CachedFontItem* FontManager::GetFont(WORD Handle) { CachedFontItem* pItem = FindFont(Handle); if ((pItem!=NULL) && (pItem->IsFullyCached())) return pItem; return &DefaultFontItem; } /******************************************************************************************** > CachedFontItem* FontManager::GetFont(String_64* pFontName, FontClass Class=FC_UNDEFINED) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: pFontName = a pointer to a font name Class = describes the type of class (see typedef for details) FC_UNDEFINED then ignore the class match and match the first item with the same name whatever font class it is Outputs: - Returns: A pointer to a cached font record or NULL Purpose: Return the font data to use for rendering. This function performs a specific job in avoiding caching the font data. If the font is already cached then fine, it is returned for use. If not, the default font is returned. ********************************************************************************************/ CachedFontItem* FontManager::GetFont(String_64 *pFontName, FontClass Class) { CachedFontItem* pItem = FindFont(pFontName, Class); if ((pItem!=NULL) && (pItem->IsFullyCached())) return pItem; return &DefaultFontItem; } /******************************************************************************************** > INT32 FontManager::DoesFontExist(String_64* pFontName, BOOL SearchCache, BOOL SearchInstalled) Author: Mike_Kenny (Xara Group Ltd) Created: 19/05/95 Inputs: FontName : Name of font to find SearchCache : TRUE then search our internal cached fonts SearchInstalled: TRUE then search through the installed set of fonts too Outputs: - Returns: 0 if the font cannot be found in the specified search areas 1 if the font has been installed 2 if the font has been cached Purpose: First check in the cache if necessary, then through the installed set of fonts to find whether the named font actually exists ********************************************************************************************/ INT32 FontManager::DoesFontExist(String_64 *pFontName, BOOL SearchCache, BOOL SearchInstalled) { if (SearchCache) if (FindFont(pFontName) != NULL) return 2; if (SearchInstalled) if (IsFontInstalled(pFontName)) return 1; return 0; } /******************************************************************************************** > BOOL FontManager::IsFontValid(WORD Handle) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: Handle = The font manager font handle Outputs: - Returns: TRUE if the font is valid and ready to use FALSE if not. Purpose: Check to see if the font described is actually valid, ie all the metrics for the font have been cached correctly. ********************************************************************************************/ BOOL FontManager::IsFontValid(WORD Handle) { CachedFontItem* pItem = GetCachedFont(Handle); return ( (pItem!=NULL) && (pItem->IsFullyCached()) ); } /******************************************************************************************** > BOOL FontManager::IsFontReplaced(WORD FontHandle) BOOL FontManager::IsFontReplaced(String_64* pFontName, FontClass Class=FC_UNDEFINED) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: pFontName = a pointer to a font name Class = describes the type of class (see typedef for details) FC_UNDEFINED then ignore the class match and match the first item with the same name whatever font class it is Outputs: - Returns: TRUE if the font has been replaced by the default FALSE if not. Purpose: Check to see if the font described has been replaced. ********************************************************************************************/ BOOL FontManager::IsFontReplaced(WORD FontHandle) { BOOL Result = FALSE; // check whether its the default font, if it is then obviously it's not been replaced. if (IsFontDefault(FontHandle)) { Result = FALSE; } else { CachedFontItem *pItem = FindFont(FontHandle); if (pItem==NULL) { Result = TRUE; // font doesn't exist } else if (pItem->IsReplaced()) { Result = TRUE; // IsReplaced flag is set } else if (!pItem->IsValid()) { Result = TRUE; // The font isn't valid } } return Result; } BOOL FontManager::IsFontReplaced(String_64* pFontName, FontClass Class) { BOOL Result = FALSE; // Check whether its the default font, if it is then obviously it's not been replaced. if (DefaultFontItem.Compare(pFontName)) { Result = FALSE; } else { CachedFontItem *pItem = FindFont(pFontName, Class); if (pItem==NULL) { Result = TRUE; // font doesn't exist } else if (pItem->IsReplaced()) { Result = TRUE; // IsReplaced flag is set } else if (!pItem->IsValid()) { Result = TRUE; // The font isn't valid } } return Result; } /******************************************************************************************** > BOOL FontManager::IsFontDefault(WORD Handle) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: Handle = The font manager font handle Outputs: - Returns: TRUE if the font handle is the handle describing the default font FALSE if not. Purpose: Check to see if the font handle described is the handle of the default font ie the font which is used to replace unknown fonts (fonts not resident on the host machine) ********************************************************************************************/ BOOL FontManager::IsFontDefault(WORD Handle) { return (Handle==DefaultHandle); } BOOL FontManager::IsFontDefault(CachedFontItem* pItem) { return (pItem == (&DefaultFontItem)); } /******************************************************************************************** > BOOL FontManager::IsFontUsedInSiblings(Node* pNode, WORD Handle, WORD CurrentHandle, UINT32 Level) Author: Martin Wuerthner Created: 01/08/06 Inputs: pNode - the root node of the subtree to check Handle - a font handle CurrentHandle - the font handle applying to the current subtree Level - level in the tree (level 0 is NodeDocument, level 1 are default attributes) Returns: Returns TRUE if a font attribute with the given handle applies to a text object. Purpose: Find out whether a given font is used in a document. ********************************************************************************************/ BOOL FontManager::IsFontUsedInSiblings(Node* pNode, WORD Handle, WORD CurrentHandle, UINT32 Level) { // perform a standard child-first recursion keeping track of the current font while(pNode) { Node* pFirstChild = pNode->FindFirstChild(); if (pFirstChild && IsFontUsedInSiblings(pFirstChild, Handle, CurrentHandle, Level + 1)) return TRUE; if (IS_A(pNode, AttrTxtFontTypeface)) { AttrTxtFontTypeface* pAttr = (AttrTxtFontTypeface*)pNode; CurrentHandle = pAttr->Value.HTypeface; ENSURE(!(CurrentHandle == DEFAULTHANDLE && Level > 1), "FontManager::IsFontUsedInSiblings is based on the assumption that we do not have non-default attribute nodes referencing the default font"); } if (CurrentHandle == Handle && (IS_A(pNode, TextStory) || IS_A(pNode, TextLine) || IS_A(pNode, TextChar))) return TRUE; pNode = pNode->FindNext(); } return FALSE; } /******************************************************************************************** > BOOL FontManager::IsFontUsedInDoc(WORD Handle, Document* pDocument) Author: Martin Wuerthner Created: 01/08/06 Inputs: Handle - a font handle pDocument - pointer to a document Returns: When called with Handle == DEFAULTHANDLE it returns TRUE if the default attribute applies to a text object. Otherwise, it returns TRUE if the supplied font handle is used in the document Purpose: Find out whether a given font is used in a document. ********************************************************************************************/ BOOL FontManager::IsFontUsedInDoc(WORD Handle, Document* pDocument) { Node* pNode = pDocument->GetFirstNode(); return IsFontUsedInSiblings(pNode, Handle, ILLEGALFHANDLE, 0); } /******************************************************************************************** > void FontManager::OnDocumentLoaded(Document* pDocument) Author: Martin Wuerthner Created: 01/08/06 Inputs: pDocument - pointer to the newly created/loaded document Purpose: Called after a document has been loaded - allows us to fix the current and default fonts if they are not installed. They are only changed if they are not used in the document. Fixing the current font is useful because it stops "Arial (missing)" from being displayed after start-up if Arial is not installed. The same happens when loading a document with the current font set to Arial (or any other font that is not installed). We do not touch the current font if it is actually used in the document because then, it is possible that it was set deliberately (maybe even in a template). One might consider a similar approach for the default font, but by definition, the default font is always installed (though it may or may not be Times New Roman), so there is no need to change anything. The default attributes are not saved with the document, so, in contrast to the current font, there cannot be any surprises with fonts that are not installed. The font name referenced by the default font does not matter because the default font attribute is never inherited by any text object in the document. This is down to the behaviour of FindFont(String_64*,FontClass), which never returns the default font handle, so any font attribute created by the text tool based on a font name (which involves calling FindFont at some stage) is always different from the default attribute (even if it happens to be the same font as the default font) and hence this attribute is not optimised away. Therefore, each and every text object has a non-default font attribute applied to it. ********************************************************************************************/ void FontManager::OnDocumentLoaded(Document* pDocument) { // check if the current font is installed and change it in case it is not (only if the font is not used) NodeAttribute* pAttr = pDocument->GetAttributeMgr().GetCurrentAttribute(CC_RUNTIME_CLASS(BaseTextClass), CC_RUNTIME_CLASS(AttrTxtFontTypeface)); if (pAttr) { AttrTxtFontTypeface* pTypeface = (AttrTxtFontTypeface*)pAttr; WORD Handle = pTypeface->Value.HTypeface; TRACEUSER("wuerthne", _T("found current font attribute, handle = %d"), Handle); CachedFontItem *pItem = FindFont(Handle); if (pItem) { String_64* SurfaceFontName = pItem->GetFontName(); TRACEUSER("wuerthne", _T("current font name is %s"), (TCHAR*)*SurfaceFontName); ENUMLOGFONT *pEnumLogFont = pItem->GetEnumLogFont(); if (pEnumLogFont) { if (!IsFontInstalled(SurfaceFontName) && !IsFontUsedInDoc(Handle, pDocument)) { // the current font is not installed and not used in the document, // so find out what the replacement font is and use that instead TRACEUSER("wuerthne", _T("font replaced and not used")); String_64* NativeFontName = OILFontMan::GetNativeFontName(pItem->GetFontClass(), &pEnumLogFont->elfLogFont); WORD NewHandle = CacheNamedFont(NativeFontName, pItem->GetFontClass()); if (NewHandle != ILLEGALFHANDLE) { TRACEUSER("wuerthne", _T("change current font to handle %d"), NewHandle); // modify the current attribute directly pTypeface->Value.HTypeface = NewHandle; } } } } } } /******************************************************************************************** > CachedFontItem* FontManager::GetFirstFontType(FontClass Class) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: Class = the class of font to retrieve Outputs: - Returns: A pointer to a cached font record or NULL Purpose: Find the entry in the font managers font list which corresponds to the first 'FontClass' font cached. ********************************************************************************************/ CachedFontItem* FontManager::GetFirstFontType(FontClass Class) { CachedFontItem* pItem = GetFirstFont(); while (pItem!=NULL) { if (pItem->GetFontClass() == Class) return pItem; pItem = GetNextFont(pItem); } return NULL; } /******************************************************************************************** > ENUMLOGFONT* FontManager::GetEnumLogFont(WORD Handle) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: Handle = The font manager font handle Outputs: - Returns: A pointer to the ENUMLOGFONT structure for this font NULL if none Purpose: Return the ENUMLOGFONT structure for this font handle. Note the function will automatically substitute the default font if the handle provided is invalid or the font it describes is not fully cached. ********************************************************************************************/ ENUMLOGFONT* FontManager::GetEnumLogFont(WORD Handle) { // ok, we need to get the font data for this particular font item CachedFontItem *pItem = GetFont(Handle); if (pItem!=NULL) { return (pItem->GetEnumLogFont()); } else { return NULL; } } /******************************************************************************************** > OUTLINETEXTMETRIC* FontManager::GetOutlineTextMetric(WORD Handle) Author: Andy_Hayward (Xara Group Ltd) Created: 15/08/96 Inputs: Handle = the font manager handle Returns: Pointer to the OUTLINETEXTMETRIC structure for this font, NULL if none Purpose: Return the ENUMLOGFONT structure for this font handle Note the function will automatically substitute the default font if the handle provided is invalid or the font it describes is not fully cached. ********************************************************************************************/ OUTLINETEXTMETRIC* FontManager::GetOutlineTextMetric(WORD Handle) { // ok, we need to get the font data for this particular font item CachedFontItem *pItem = GetFont(Handle); if (pItem!=NULL) { return pItem->GetOutlineTextMetric(); } else { return NULL; } } /******************************************************************************************** > String_64* FontManager::GetFontName(WORD Handle) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: Handle = The font manager font handle Outputs: - Returns: A pointer to the font name associated with this handle NULL if the handle is illegal Purpose: Return a pointer to the font name given its font handle ********************************************************************************************/ String_64* FontManager::GetFontName(WORD Handle) { CachedFontItem* pItem = GetCachedFont(Handle); if (pItem==NULL) { ERROR3("FontManager::GetFontName() - given an illegal handle"); return NULL; } return pItem->GetFontName(); } BOOL FontManager::GetFontName(WORD Handle, String_64& OutputString) { CachedFontItem* pItem = GetCachedFont(Handle); if (pItem==NULL) { ERROR3("FontManager::GetFontName() - given an illegal handle"); return FALSE; } OutputString = *(pItem->GetFontName()); return TRUE; } /******************************************************************************************** > FontClass FontManager::GetFontClass(WORD Handle) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: Handle = The font manager font handle Outputs: - Returns: A font class FC_UNDEFINED if the handle is unknown Purpose: Return what class of font this handle is. ********************************************************************************************/ FontClass FontManager::GetFontClass(WORD Handle) { CachedFontItem* pItem = GetCachedFont(Handle); if (pItem==NULL) { ERROR3("FontManager::GetFontClass() - given an illegal handle"); return FC_UNDEFINED; } return pItem->GetFontClass(); } /******************************************************************************************** > WORD FontManager::FindTypeface(String_64 &TypeFacename, FontClass Class) Author: Andy_Hayward (Xara Group Ltd) Created: 19/08/96 Inputs: TypeFaceName - Typeface name of font to search for Class - font class to search for Returns: Font handle of typeface, or ILLEGALFHANDLE if not found Purpose: Used by the new file format, to check if a particular typeface (and font class) is installed and available. See Also: class FontComponent ********************************************************************************************/ WORD FontManager::FindTypeface(String_64 &TypeFaceName, FontClass Class) { WORD FontHandle = ILLEGALFHANDLE; CachedFontItem *pItem=FindFont(&TypeFaceName, Class); if (pItem!=NULL) { // font is in the cached font list. FontHandle=pItem->Handle; } // now scan the installed lists for this font, and set the local temp font data else if (TempCacheNamedFont(&TypeFaceName, Class, 1)) { AddTempFont(&TypeFaceName, Class, FontHandle); } // Okay, so we couldn't find the exact font. It may be possible to create the // font we are after. ATM for instance allows named font instances to be created // from the base multiple master outlines. else if (TempCacheNamedFont(&TypeFaceName, Class, 2)) { AddTempFont(&TypeFaceName, Class, FontHandle); } else // completly unsuccessful. :( { FontHandle=ILLEGALFHANDLE; } return FontHandle; } /******************************************************************************************** > WORD FontManager::FindClosestFont(const CCPanose &PanoseNumber) Author: Andy_Hayward (Xara Group Ltd) Created: 20/08/96 Inputs: PanoseNumber - panose number to search against Returns: Font handle of the closest font Purpose: Performs panose matching on the installed fonts ********************************************************************************************/ WORD FontManager::FindClosestFont(const CCPanose &PanoseNumber) { // check, is this a 'simple' panose number with just Weight and Letterform components? if (PanoseNumber.GetFamilyType()==PAN_ANY && PanoseNumber.GetSerifStyle()==PAN_ANY && PanoseNumber.GetProportion()==PAN_ANY && PanoseNumber.GetContrast()==PAN_ANY && PanoseNumber.GetStrokeVariation()==PAN_ANY && PanoseNumber.GetArmStyle()==PAN_ANY && PanoseNumber.GetMidline()==PAN_ANY && PanoseNumber.GetXHeight()==PAN_ANY) { // These 'simple' panose numbers get saved out for old files and ATM fonts. Obviously // we can't do any sensible font matching, so just return the default font handle. return DEFAULTHANDLE; } else { // shove the data we need into class members. FindClosestFontHandle = ILLEGALFHANDLE; FindClosestPanoseNumber = PanoseNumber; FindClosestDistance = 0xffffffff; FindClosestTypeFaceName = _T(""); FindClosestFontClass = FC_UNDEFINED; // normalise the panose number. FindClosestPanoseNumber.BodgeToNormal(); // choose whichever panose font matching algorithm you require: PORTNOTE("text","TrueType/Win specific code removed") #ifndef EXCLUDE_FROM_XARALX // quick - just checks the seven fonts from the Microsoft(tm) Web Font Pack(tm) return FindClosestFontQuick(PanoseNumber); #endif // full - checks all the fonts installed on the machine. return FindClosestFontFull(PanoseNumber); } } PORTNOTE("text","TrueType/Win specific code removed") #ifndef EXCLUDE_FROM_XARALX WORD FontManager::FindClosestFontQuick(const CCPanose &PanoseNumber) { WORD MyFontHandle; String_64 MyFontName; // try "Arial" MyFontName = _T("Arial"); MyFontHandle = CacheNamedFont(&MyFontName, FC_TRUETYPE); FindClosestFontQuickTry(MyFontHandle); // try "Arial Black" MyFontName = _T("Arial Black"); MyFontHandle = CacheNamedFont(&MyFontName, FC_TRUETYPE); FindClosestFontQuickTry(MyFontHandle); // try "Comic Sans" MyFontName = _T("Comic Sans"); MyFontHandle = CacheNamedFont(&MyFontName, FC_TRUETYPE); FindClosestFontQuickTry(MyFontHandle); // try "Courier New" MyFontName = _T("Courier New"); MyFontHandle = CacheNamedFont(&MyFontName, FC_TRUETYPE); FindClosestFontQuickTry(MyFontHandle); // try "Impact" MyFontName = _T("Impact"); MyFontHandle = CacheNamedFont(&MyFontName, FC_TRUETYPE); FindClosestFontQuickTry(MyFontHandle); // try "Times New Roman" MyFontName = _T("Times New Roman"); MyFontHandle = CacheNamedFont(&MyFontName, FC_TRUETYPE); FindClosestFontQuickTry(MyFontHandle); // try "Verdana" MyFontName = _T("Verdana"); MyFontHandle = CacheNamedFont(&MyFontName, FC_TRUETYPE); FindClosestFontQuickTry(MyFontHandle); return FindClosestFontHandle; } BOOL FontManager::FindClosestFontQuickTry(WORD MyFontHandle) { OUTLINETEXTMETRIC *pOutlineTextMetric = GetOutlineTextMetric(MyFontHandle); if (pOutlineTextMetric!=NULL) { CCPanose MyPanoseNumber = pOutlineTextMetric->otmPanoseNumber; MyPanoseNumber.BodgeToNormal(); UINT32 MyDistance = CCPanose::Distance(FindClosestPanoseNumber, MyPanoseNumber); if (MyDistanceHandle; } else { // the font hasn't been cached yet, so cache it now. pCachedFontItem = AddFont(&FindClosestTypeFaceName, FindClosestFontClass, MyFontHandle); pCachedFontItem->SetCacheData(&FindClosestEnumLogFont); } // return with this font handle return MyFontHandle; } BOOL FontManager::FindClosestFontFullTry(FontClass Class, String_64 *pTypeFaceName, ENUMLOGFONT *pEnumLogFont) { ERROR2IF(pEnumLogFont==NULL, FALSE, "FindClosestTry called with pEnumLogFont==NULL."); OUTLINETEXTMETRIC *pOutlineTextMetric; CCPanose MyPanoseNumber; UINT32 MyDistance; pOutlineTextMetric = OILFontMan::GetOutlineTextMetric(Class, &(pEnumLogFont->elfLogFont)); if (pOutlineTextMetric!=NULL) { MyPanoseNumber = (pOutlineTextMetric->otmPanoseNumber); MyPanoseNumber.BodgeToNormal(); MyDistance = CCPanose::Distance(FindClosestPanoseNumber, MyPanoseNumber); if (MyDistance void FontManager::InvalidateCharMetrics() Author: Ed_Cornes (Xara Group Ltd) Created: 15/1/96 Purpose: Invalidate char metrics cache ********************************************************************************************/ void FontManager::InvalidateCharMetrics() { OILFontMan::InvalidateCharMetrics(); } /******************************************************************************************** > BOOL FontManager::GetCharMetrics(CDC* pDC, WCHAR ch, CharDescription& FontDesc, CharMetrics* pCharMetrics); Author: Ed_Cornes (Xara Group Ltd) Created: 15/1/96 Inputs: pDC - pointer to DC (rather than creating one each time) ch - the char whose metrics are required FontDesc - the font Outputs: pCharMetrics - the metrics Returns: FALSE if fails Purpose: Get the char metrics for the given char and font Just dispenses the call to the FontMetricsCache ********************************************************************************************/ BOOL FontManager::GetCharMetrics(CNativeDC* pDC, WCHAR ch, CharDescription& FontDesc, CharMetrics* pCharMetrics) { return OILFontMan::GetCharMetrics(pDC, ch, FontDesc, pCharMetrics); } /******************************************************************************************** > MILLIPOINT FontManager::GetCharsKerning(CDC* pDC, WCHAR chLeft, WCHAR chRight, CharDescription& FontDesc); Author: Jonathan_Payne (Xara Group Ltd) Created: 15/10/2000 Inputs: pDC - pointer to DC (rather than creating one each time) chLeft - the left char of a kerning pair chRight - the right char of a kerning pair FontDesc - the font Returns: Kern distance between chars or 0 on error or no kern Purpose: Finds the kerning distance between two chars ********************************************************************************************/ MILLIPOINT FontManager::GetCharsKerning(CNativeDC* pDC, WCHAR chLeft, WCHAR chRight, CharDescription& FontDesc) { // TRACEUSER("wuerthne", _T("FontManager::GetCharsKerning called\n") ); return OILFontMan::GetCharsKerning(pDC, chLeft, chRight, FontDesc); } /******************************************************************************************** > static BOOL FontManager::GetCharPath(CharDescription& ChDesc, DocCoord** ppCoords, PathVerb** ppVerbs, UINT32* pNumCoords, CDC* pDC=NULL) Author: Mike_Kenny (Xara Group Ltd) Created: 28/9/95 Inputs: ChDesc = description of char pDC = (possible) pointer to a DC (for optimisation) defaults to NULL Outputs: ppCoords = pointer to path coords buffer ppVerbs = pointer to path verbs buffer pNumCoords = number of elements in path Returns: FALSE if unable to return the outline Purpose: Get the path associated with a given char ********************************************************************************************/ BOOL FontManager::GetCharPath(CharDescription& ChDesc, DocCoord** ppCoords, PathVerb** ppVerbs, UINT32* pNumCoords, CNativeDC* pDC) { ERROR2IF(ppCoords==NULL,FALSE,"FontManager::GetCharPath pCoords==NULL"); ERROR2IF(ppVerbs==NULL,FALSE,"FontManager::GetCharPath ppVerbs==NULL"); ERROR2IF(pNumCoords==NULL,FALSE,"FontManager::GetCharPath pNumCoords==NULL"); CachedFontItem* pItem = GetFont(ChDesc.GetTypefaceHandle()); if (pItem==NULL) return FALSE; if (pItem->IsCorrupt()) return FALSE; BOOL Success = OILFontMan::GetCharPath(pItem->GetFontClass(), ChDesc, ppCoords, ppVerbs, pNumCoords, pDC); if (!Success) pItem->SetIsCorrupt(TRUE); return Success; } /******************************************************************************************** > BOOL FontManager::CacheDefaultFont() Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: - Outputs: - Returns: TRUE if the default font has been cached FALSE if not Purpose: Cache the default font so we can use this as a replacement when unable to find strange fonts. ********************************************************************************************/ BOOL FontManager::CacheDefaultFont() { PORTNOTE("text","FontManager::CacheDefaultFont - do nothing"); #ifndef DISABLE_TEXT_RENDERING if (DefaultFontItem.pFontClass!=NULL) { ERROR3("CacheDefaultFont called but a default font is already resident"); return TRUE; } // now scan all installed lists an set out local temp font data String_64 DefFont(DEFAULTFONTNAME); if (!TempCacheNamedFont(&DefFont)) if (!TempCacheNamedFont(NULL)) return FALSE; FontBase* pClass = OILFontMan::CreateNewFont(TempFontClass,&TempFontName); if (pClass==NULL) return FALSE; DefaultFontItem.pFontClass = pClass; DefaultFontItem.Handle = DEFAULTHANDLE; if (!DefaultFontItem.SetCacheData(&TempEnumLogFont)) { DefaultFontItem.Delete(); return FALSE; } return TRUE; #else return TRUE; #endif } /******************************************************************************************** > void FontManager::ResetDefaultFont() Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: - Outputs: - Returns: - Purpose: Cache the default font so we can use this as a replacement when unable to find strange fonts. The cache is checked first to see if the default font is already there. ********************************************************************************************/ void FontManager::ResetDefaultFont() { DefaultFontItem.Delete(); CacheDefaultFont(); } /******************************************************************************************** > WORD FontManager::CacheNamedFont(String_64* pFontName, FontClass Class = FC_UNDEFINED) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: pFontName = a pointer to a font name Class : the class of font to cache FC_UNDEFINED - then try to cache any font by asking each font manager in turn. Outputs: - Returns: ILLEGALFHANDLE - if unable to cache the named font A unique font handle if cached Purpose: Given a font name try to cache all the data for that font so that we can actually us it. The cache will be checked first to make sure the font is not already installed. ********************************************************************************************/ WORD FontManager::CacheNamedFont(String_64* pFontName, FontClass Class) { ERROR2IF(pFontName==NULL, ILLEGALFHANDLE, "Bad fontname passed to CacheNamedFont"); // try to find the font in the cache first CachedFontItem *pItem = FindFont(pFontName, Class); if (pItem!=NULL) return pItem->Handle; // now scan all installed lists and set our local temp font data if (!TempCacheNamedFont(pFontName, Class, 1)) { // ok we couldn't find the exact font. It may be possible // to create the font we are after. ATM for instance allows // named font instances to be created from their base multiple // master outlines. TempCacheNamedFont(pFontName, Class, 2); } // add the font that has been returned to us, even if none has. // if no font has been installed then we will end up having a font cache // object which describes a font as invalid. This is fine as we now know // we've done a search for it and it does not exist so we'll use the default WORD hndle=ILLEGALFHANDLE; AddTempFont(pFontName, Class, hndle); TRACEUSER("wuerthne", _T("FontManager::CacheNamedFont = %d"), hndle); return (hndle); } /******************************************************************************************** > BOOL FontManager::TempCacheNamedFont(String_64 *pFontName, FontClass Class=FC_UNDEFINED, INT32 Pass=1) Author: Mike_Kenny (Xara Group Ltd) Created: 19/05/95 Inputs: pFontName : Name of font to search for Class : The class of font to cache FC_UNDEFINED - then try to cache any font Pass : 1 - first pass, try to match the font exactly : 2 - second pass, try to find a compatible font Outputs: - Returns: TRUE if the font has been temporarily installed Purpose: Search through all the installed sets of fonts for the named font and place the result in a temp font. ********************************************************************************************/ BOOL FontManager::TempCacheNamedFont(String_64* pFontName, FontClass Class, INT32 Pass) { return (OILFontMan::CacheNamedFont(pFontName, Class, Pass)); } /******************************************************************************************** > BOOL FontManager::IsFontInstalled(String_64* pFontName, FontClass Class = FC_UNDEFINED) Author: Mike_Kenny (Xara Group Ltd) Created: 19/05/95 Inputs: pFontName : Name of font to search for Class : The class of font to cache FC_UNDEFINED - then try to cache any font Outputs: - Returns: TRUE if the font has been installed Purpose: Search through all the installed sets of fonts for the named font ********************************************************************************************/ BOOL FontManager::IsFontInstalled(String_64* pFontName, FontClass Class) { return TempCacheNamedFont(pFontName, Class); } /******************************************************************************************** > BOOL FontManager::IsFullyCached(WORD Handle) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: Handle = The font manager font handle Outputs: - Returns: TRUE if the font exists and is cached FALSE if not Purpose: Find out if the font is fully cached and ready to use. This will generally be true of all fonts added by CacheNamedFont. If the font is not fully cached then call CacheFontData(). It will not be if AddFont has been used to add the font to the font list. ********************************************************************************************/ BOOL FontManager::IsFullyCached(WORD Handle) { CachedFontItem* pItem = GetCachedFont(Handle); if (pItem!=NULL) return pItem->IsFullyCached(); return FALSE; } /******************************************************************************************** > void FontManager::RefreshCache() Author: Mike_Kenny (Xara Group Ltd) Created: 13/9/95 Purpose: Scans all the cached fonts and checks to see if any are invalid. If a font is invalid it is attempted to be made valid. This function is generally called when the external worlds fonts have changed via install/deinstall. ********************************************************************************************/ void FontManager::RefreshCache() { InvalidateCache(); OILFontMan::ValidateCache(); ResetDefaultFont(); } /******************************************************************************************** void FontManager::ValidateItem(FontClass Class, String_64 * pFontName, ENUMLOGFONT * lpelf) Author: Mike_Kenny (Xara Group Ltd) Created: 13/9/95 Purpose: Used as a way of revalidating a cached font. This function is called from the various oil level font managers when we've asked them to refresh our cache. They simply need to scan their font lists and call this function with the new data. ********************************************************************************************/ void FontManager::ValidateItem(FontClass Class, String_64 * pFontName, ENUMLOGFONT * lpelf) { CachedFontItem *pItem = FindFont(pFontName,Class); if (pItem) { pItem->SetCacheData(lpelf); pItem->SetIsReplaced(FALSE); } } /******************************************************************************************** > void FontManager::InvalidateCache() Author: Mike_Kenny (Xara Group Ltd) Created: 13/9/95 Purpose: Scans all the cached fonts deletes all cached data. If the entries are not recached all visible fonts will be replaced by the default font. ********************************************************************************************/ void FontManager::InvalidateCache() { CachedFontItem *pItem = GetFirstFont(); while (pItem) { pItem->DeleteMetrics(); pItem->SetIsCorrupt(FALSE); pItem->SetIsReplaced(TRUE); pItem = GetNextFont(pItem); } } /******************************************************************************************** > void FontManager::DumpFontCache() Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Purpose: Dubugging facitity - dumps out the contents of our cache. ********************************************************************************************/ void FontManager::DumpFontCache() { CachedFontItem *pItem = GetFirstFont(); while (pItem) { pItem->Dump(); pItem = GetNextFont(pItem); } } /******************************************************************************************** > void FontManager::DumpFont(WORD Handle) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Purpose: Dubugging facitity - dumps out the contents of a font from our cache. ********************************************************************************************/ void FontManager::DumpFont(WORD Handle) { CachedFontItem *pItem = FindFont(Handle); if (pItem) pItem->Dump(); } /******************************************************************************************** > void FontManager::ClearTempFont() Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Purpose: Throws away any font data stored in the temp font. ********************************************************************************************/ void FontManager::ClearTempFont() { TempFontClass=FC_UNDEFINED; TempFontName.Empty(); } /******************************************************************************************** > void FontManager::SetTempFont(FontClass Class, String_64 * pFontName, ENUMLOGFONT * lpelf) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Purpose: This function is used by the oil level font managers to set a temporary font. There are various other font manager functions which can process the temp font. ********************************************************************************************/ void FontManager::SetTempFont(FontClass Class, String_64 * pFontName, ENUMLOGFONT * lpelf) { ERROR3IF(lpelf==NULL,"FontManager::SetTempFont() given a null ENUMLOGFONT structure"); ERROR3IF(Class==FC_UNDEFINED, "FontManager::SetTempFont() given an illegal font class"); TempFontClass=Class; TempFontName=(*pFontName); TempEnumLogFont=(*lpelf); } /******************************************************************************************** > CachedFontItem* FontManager::AddTempFont(String_64* pFontName, FontClass Class, WORD& hndle) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: pFontName = a pointer to the font name Class = describes the type of class (see typedef for details) FC_UNDEFINED then ignore the class match and match the first item with the same name whatever font class it is Outputs: Handle = ILLEGALFHANDLE if the font could not be added Handle = The font handle if ok Returns: NULL if the font could not be added A pointer to the font record Purpose: Given the temp font data, this function goes and caches that data under the provided name and returns the font handle ********************************************************************************************/ CachedFontItem* FontManager::AddTempFont(String_64* pFontName, FontClass Class, WORD& hndle) { CachedFontItem* pItem = NULL; if (TempFontClass==FC_UNDEFINED) { if (Class!=FC_UNDEFINED) pItem = AddFont(pFontName, Class, hndle); else { // ERROR3("Trying to add a font of an unknown class"); pItem = AddFont(pFontName, FC_TRUETYPE, hndle); } } else { pItem = AddFont(pFontName, TempFontClass, hndle); if (pItem) pItem->SetCacheData(&TempEnumLogFont); } return pItem; } /******************************************************************************************** > BOOL FontManager::TempFontValid() Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Returns: TRUE if the temp font has been set to a valid font FALSE if not ********************************************************************************************/ BOOL FontManager::TempFontValid() { return (TempFontClass!=FC_UNDEFINED); } /******************************************************************************************** > void FontManager::EncodeFontName(String_64& FontName, String_64& Encoded, INT32 Styles) Author: Mike_Kenny (Xara Group Ltd) Created: 18/4/95 Inputs: FontName A reference to a font name to encode Encoded 'none constant' string reference to a output string buffer Styles = 1 then try to append 'Bold' = 2 then try to append 'Italic' = 3 then try to append 'BoldItalic' Outputs: Encoded contains the string built by this function suitable for output to an Illustrator 3.0, 5.0 format file. Returns: - Purpose: Output a font name with bold and italic flags attached. All spaces are converted to dashes. The font is first checked for the existance of style words bold and italic before new styles are added. Notes: FontNames --------- Encodings: FaceName (Bold) (BoldItalic) GaramondE GaramondE-Bold GaramondE-BoldItalic EuropeExtraBold EuropeExtraBold-Bold EuropeExtraBold-BoldItalic European Bold Oblique European-Bold-Oblique European-Bold-Oblique deGaulleBlack Italic deGualleBlack-BoldItalic deGualleBlack-BoldItalic ********************************************************************************************/ void FontManager::EncodeFontName(String_64& FontName, String_64& Encoded, INT32 Styles) { String_64 Copy(FontName); String_32 Match; // Replace all spaces with a hyphen. Copy.SwapChar(_T(' '),_T('-')); INT32 Length = Copy.Length(); // Find the last hyphen in the font's name. INT32 LastHyphen = Copy.ReverseFind ( '-' ); // If there is a -XX extension to the name, remove the hyphen. if ( LastHyphen == Length - 3 ) { Copy.Remove ( LastHyphen, 1 ); } // Check for bold/italic. Match = _R(IDS_FONTMAN_MINUS_BOLD); //"-Bold"; INT32 Bld = (Copy.Sub(Match,0,0)); Match = _R(IDS_FONTMAN_MINUS_ITALIC); //"-Italic"; INT32 Ital = (Copy.Sub(Match,0,0)); switch (Styles) { case 1: { if (Bld<0 && Ital<0) { Copy += String_16(_R(IDS_FONTMAN_MINUS_BOLD)); // "-Bold"; break; } if( ( Bld < 0 ) && ( Ital > -1 ) && ( Length - 7 == Ital ) ) { Copy.Insert( String_32(_R(IDS_FONTMAN_BOLD)), Ital ); } break; } case 2: { if (Bld<0 && Ital<0) { Copy += String_16(_R(IDS_FONTMAN_MINUS_ITALIC)); // "-Italic"; break; } if ((Ital<0) && (Bld>-1) && (Length-5==Bld)) Copy += String_16(_R(IDS_FONTMAN_ITALIC)); //"Italic"; break; } case 3: { if (Bld<0 && Ital<0) { Copy += String_16(_R(IDS_FONTMAN_MINUS_BOLDITALIC)); // "-BoldItalic"; break; } // If the font contains the word bold at the end, append italic if( ( Ital < 0 ) && ( Bld > -1 ) && ( Length - 5 == Bld ) ) { Copy += String_16(_R(IDS_FONTMAN_ITALIC)); //"Italic"; break; } // If the font already has italic, insert Bold if( ( Bld < 0 ) && ( Ital > -1 ) && ( Length - 7 == Ital ) ) { Copy.Insert( String_32(_R(IDS_FONTMAN_BOLD)), Ital ); } break; } } // Set the encoded output string Encoded=Copy; } /******************************************************************************************** > void FontManager::EncodeAndMapFontName ( String_64& FontName, String_64& Encoded, INT32 Styles ) Author: Graeme_Sutherland (Xara Group Ltd) Created: 31/3/00 Inputs: FontName - The TrueType font name. Encoded - A string into which the PostScript font name will be written. Styles - Whether the font is bold, italic, or a combination. Outputs: Encoded - Populated with the encoded font name. Returns: - Purpose: This function first calls EncodeFontName, to generate an approximated PostScript font name, before calling a second function to get the PostScript font mapping. ********************************************************************************************/ void FontManager::EncodeAndMapFontName ( String_64& FontName, String_64& Encoded, INT32 Styles ) { String_64 Mapped; // First encode the font name. EncodeFontName ( FontName, Encoded, Styles ); // And then make the mapping. if ( Camelot.GetPrefDirect ( _T("EPSFontMapping"), ( TCHAR * ) Encoded, &Mapped ) ) { // There is a PostScript equivalent stored for this font, so use the mapped // version as the encoded name. Encoded = Mapped; } } /******************************************************************************************** void FontManager::GetCompatibleFont(const String_64& EncodedName, String_64& CompatibleFont, INT32& Style) Author: Mike_Kenny (Xara Group Ltd) Created: 18/4/95 Inputs: EncodedName the encoded font name to find a compatible font for. encoded names are those read direct from the native file. Outputs: CompatibleFont contains the decoded fontname suitable for font matching Style b0 = 1 then Bold style should be enabled b1 = 1 then Italic style should be enabled Returns: Purpose: Find a compatible font to that specified in the encoded font name. An encoded name looks something like.... Times-New-Roman Times-New-Roman-Bold Times-New-Roman-Italic Times-New-Roman-BoldItalic ChiversCond-Bold-Oblique The algorithm used is based on diminishing returns, ie try to find the exact font first, then break the fontname up in various increasingly complex ways until a valid substitution is found. This substitution can then be used for font caching. Note if the fontmanager fails to find any match it will return the encodedname as a last resort. When this is cached, its metrics will be NULL and hence be replaced by the default font automatically be the font manager. extras: This function tries to use the font name as specified. If it does not exist the function will attempt to use the fontname without styles and create styles to fit but only if this new fontname exists. ie it will do the following FontName Styles NameExists StylesOutput (1) Times New Roman BoldItalic Yes BoldOff / ItalicOff (2) Times New Roman Bold/Italic Yes BoldOn / ItalicOn (3) Times New Roman BoldItalic No BoldOn / ItalicOn Errors: ********************************************************************************************/ void FontManager::GetCompatibleFont(const String_64& EncodedName, String_64& CompatibleFont, INT32& Style) { // first make a copy of the encoded name String_64 TryFont(EncodedName); // now set the return style Style=0; // Usually the fontnames in the file are saved as /_FontName.Attr-BoldItalic format if( TryFont.Sub( String_32( _T("_") ),0 ,0 ) == 0 ) TryFont.Remove(0,1); // remove our inserted - symbols which are encoded as separators on saving TryFont.SwapChar('-',' '); // Try to find the specified font name, search internal and external caches INT32 found = DoesFontExist(&TryFont,TRUE,TRUE); if (found>0) { CompatibleFont=TryFont; return; } // Ok, if we can't find the whole thing, try decoding String_64 DecodedName; Style = DecodeFontName(EncodedName, DecodedName); // find out what styles this font has BOOL Bold,Italic; Bold=((Style & 1) != 0); Italic=((Style & 2) != 0); // if both bold and italic found if (Bold && Italic) { String_64 HoldName(TryFont); // try to find bold first INT32 pos = HoldName.Sub( String_32( _T("Italic") ), 0, 0 ); HoldName.Remove(pos,6); found = DoesFontExist(&HoldName,TRUE,TRUE); if (found>0) { CompatibleFont=HoldName; return; } // Then try Italic HoldName=TryFont; pos = HoldName.Sub( String_32( _T("Bold") ), 0, 0 ); HoldName.Remove(pos,4); found = DoesFontExist(&HoldName,TRUE,TRUE); if (found>0) { CompatibleFont=HoldName; return; } } // Does the decoded name exist?, so we can make the rest up in styles? found = DoesFontExist(&DecodedName,TRUE,TRUE); if (found>0) { CompatibleFont=DecodedName; return; } // otherwise, we have a font with an extension, eg Trinity.Bold // (1) Trinity.Bold - does not exist // (2) Trinity - does not exist // now we set the font to (1), which will be replaced by Times-Roman. // Now we should also set the font styles too to give us TimesRoman bold CompatibleFont=TryFont; } /******************************************************************************************** > INT32 FontManager::DecodeFontName(String_64& IStringRef, String_64& OStringRef) Author: Mike_Kenny (Xara Group Ltd) Created: 18/4/95 Inputs: IStringRef the string to decode. Outputs: OStringRef contains the decoded fontname suitable for font matching Returns: Flags b0 = 1 then Bold style is enabled b1 = 1 then Italic style is enabled Purpose: Given a fontname encoded for EPS files, return the actual font name suitable for font matching and its style definintions (if applicable) ********************************************************************************************/ INT32 FontManager::DecodeFontName(const String_64& IStringRef, String_64& OStringRef) { String_32 Match; String_64 Temp; INT32 pos,Flags; OStringRef.Empty(); Flags=0; Temp=IStringRef; Match = _R(IDS_FONTMAN_MINUS_BOLDITALIC); // "-BoldItalic"; pos = Temp.Sub(Match,0,0); if (pos>-1) { Flags |= 3; Temp.Left(&OStringRef,pos); Temp=OStringRef; } Match = _R(IDS_FONTMAN_MINUS_BOLD); // "-Bold"; pos = Temp.Sub(Match,0,0); if (pos>-1) { Flags |= 1; Temp.Left(&OStringRef,pos); Temp=OStringRef; } Match = _R(IDS_FONTMAN_MINUS_ITALIC); // "-Italic"; pos = Temp.Sub(Match,0,0); if (pos>-1) { Flags |= 2; Temp.Left(&OStringRef,pos); Temp=OStringRef; } // Remove the front _ char Match = _T("_"); if (Temp.Sub(Match,0,0)==0) Temp.Remove(0,1); Temp.SwapChar('-',' '); OStringRef = Temp; return Flags; } /******************************************************************************************** > virtual BOOL EnumAllFonts::NewFont(FontClass Class, ENUMLOGFONT FAR* lpelf) Author: Mike_Kenny (Xara Group Ltd) Created: 12/9/95 Inputs: Class = the class of font returned (ATM,TrueType etc) lpelf = a pointer to the font design data Returns: TRUE if the next font should be enumerated FALSE if not ********************************************************************************************/ BOOL EnumAllFonts::NewFont(FontClass Class, ENUMLOGFONT FAR* lpelf) { // dont enumerate any more please. return FALSE; }