fontman.cpp

Go to the documentation of this file.
00001 // $Id: fontman.cpp 1642 2006-08-02 10:15:44Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 // implementation file for Camelots Font Managler, supposidly
00099 
00100 /*
00101 */
00102 
00103 #include "camtypes.h"
00104 // #include "fontbase.h" - included in fontman.h
00105 #include "nodetxts.h"
00106 #include "nodetxtl.h"
00107 #include "nodetext.h"
00108 #include "fontman.h"
00109 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 //#include "txtattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 //#include "richard2.h"
00112 
00113 DECLARE_SOURCE( "$Revision: 1642 $" );
00114 
00115 CC_IMPLEMENT_DYNCREATE( CachedFontItem, ListItem )
00116 CC_IMPLEMENT_DYNCREATE( FontManager, CCObject )
00117 CC_IMPLEMENT_DYNCREATE( EnumAllFonts, OILEnumFonts )
00118 
00119 
00120 // Declare smart memory handling in Debug builds
00121 #define new CAM_DEBUG_NEW     
00122 
00123 
00124 /*
00125     THEORY N ALL
00126 
00127     (1) The font manager controls its fonts in a simple list. Each entry contains a
00128         font description which knows what kind of font it is.
00129     (2) All access to fonts should be via the font manager, which in turn asks each
00130         font list item.
00131     (3) For speed and general lack of gobbling memory, the font list is initialised with
00132         font names only. If someone actually wants information about a fonts metrics
00133         or its log font structure (heaven forbid) they call the fontmanagers functions
00134         to return these items. If the items are null at the time then the info has not
00135         been cached yet and will immediately get cached (cor cache on demand!). A little
00136         slower for the first use but nice there after.
00137     (4) A font name is now no longer enough to uniquely specify a font. The name and class
00138         need to be used as you can be using an ATM font called Courier as well as a
00139         True Type font of the same name. Eeek.
00140     (5) Any new stuff added should NOT be naughty and follow its own guide lines. The idea
00141         is simple. Provide a function in the font manager that the external user can call,
00142         then implement the same function inside CachedFontItem (ie the font manager usually
00143         asks the font item if it wants information from it (it does not simply dig the
00144         data straight out itself!). The font item then asks a virtual function derived
00145         from FontBase cause the actually font class only knows whats going on at the
00146         device level.
00147         That way we might even be able to get risc os fonts working one day. Ha Ha Ha Ha!
00148     (6) THOU SHALL'T NOT CHANGE SCOPE!
00149         Anyone found leaping into structures having promoted things from private to public
00150         will be shot.
00151     (7) To add a new font controller, simply derive from FontBase and implement the necessary
00152         functionality, simple as that although currently we do not have our own internal
00153         font descriptors, we currently rely on the one API structure: ENUMLOGFONT
00154         The structure OUTLINETEXTMETRIC is cached on demand, since its 'expensive' to
00155         retrieve. The only time we need to do it for all the fonts should be when the
00156         new file format needs to do some smart font subsitution.
00157 */
00158 
00159 
00160 /********************************************************************************************
00161 
00162 >   CachedFontItem::CachedFontItem() 
00163 
00164     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00165     Created:    12/09/95                
00166     Purpose:    Default constructor
00167 
00168 ********************************************************************************************/
00169 
00170 CachedFontItem::CachedFontItem()
00171 {
00172     pFontClass          = NULL;
00173     Handle              = ILLEGALFHANDLE;
00174     pEnumLogFont        = NULL;
00175     pOutlineTextMetric  = NULL;
00176     FlagIsCorrupt       = FALSE;
00177     FlagIsReplaced      = FALSE;
00178 }
00179 
00180 CachedFontItem::~CachedFontItem()
00181 {
00182     Delete();
00183 }
00184 
00185 /********************************************************************************************
00186     For all the rest of these functions see their FontManager equivalents
00187 ********************************************************************************************/
00188 
00189 /********************************************************************************************
00190 
00191 >   ENUMLOGFONT* CachedFontItem::GetEnumLogFont()
00192 
00193     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00194     Created:    12/09/95
00195     Inputs:     -
00196     Returns:    A pointer to the ENUMLOGFONT structure for this font                
00197     Purpose:    Returns the ENUMLOGFONT structure for this cached font.
00198 
00199 ********************************************************************************************/
00200 
00201 ENUMLOGFONT* CachedFontItem::GetEnumLogFont()
00202 {
00203     ERROR2IF(pFontClass==NULL, NULL, "structure exists without a FontClass!!!");
00204 
00205     if (pEnumLogFont!=NULL)
00206         return pEnumLogFont;
00207 
00208     return NULL;
00209 }
00210 
00211 /********************************************************************************************
00212 
00213 >   OUTLINETEXTMETRIC* CachedFontItem::GetOutlineTextMetric()
00214 
00215     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
00216     Created:    15/08/96
00217     Inputs:     -
00218     Returns:    A pointer to the OUTLINETEXTMETRIC structure for this font, or NULL if
00219                 one doesn't exist (non-truetype fonts).
00220     Purpose:    Returns the OUTLINETEXTMETRIC structure for this cached font.
00221 
00222 ********************************************************************************************/
00223 
00224 OUTLINETEXTMETRIC* CachedFontItem::GetOutlineTextMetric()
00225 {
00226     ERROR2IF(pFontClass==NULL, NULL, "this.pFontClass==NULL.");
00227     ERROR2IF(pEnumLogFont==NULL, NULL, "this.pEnumLogFont==NULL.");
00228 
00229     if (pOutlineTextMetric==NULL)
00230     {
00231         // ask the font class for this structure, and cache it
00232         FontClass Class = GetFontClass();
00233         pOutlineTextMetric=OILFontMan::GetOutlineTextMetric(Class, &(pEnumLogFont->elfLogFont));
00234     }
00235 
00236     // return the result.
00237     return pOutlineTextMetric;
00238 }
00239 
00240 /********************************************************************************************
00241 
00242 >   String_64* CachedFontItem::GetFontName()
00243 
00244     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00245     Created:    12/09/95
00246     Inputs:     -
00247     Returns:    A font name
00248     Purpose:    Get this items name
00249 
00250 ********************************************************************************************/
00251 
00252 String_64* CachedFontItem::GetFontName()
00253 {
00254     ERROR2IF(pFontClass==NULL, NULL, "structure exists without a FontClass!!!");
00255     return pFontClass->GetFontName();
00256 }
00257 
00258 /********************************************************************************************
00259 
00260 >   FontClass CachedFontItem::GetFontClass()
00261 
00262     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00263     Created:    12/09/95
00264     Inputs:     -
00265     Returns:    A font class
00266     Purpose:    Get this items class
00267 
00268 ********************************************************************************************/
00269 
00270 FontClass CachedFontItem::GetFontClass()
00271 {
00272     ERROR3IF(pFontClass==NULL, "structure exists without a FontClass!!!");
00273     return pFontClass->GetFontClass();
00274 }
00275 
00276 /********************************************************************************************
00277 
00278 >   void CachedFontItem::DeleteMetrics()
00279 
00280     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00281     Created:    12/09/95
00282     Inputs:     -
00283     Returns:    -
00284     Purpose:    Delete this items LOGFONT cached structure
00285 
00286 ********************************************************************************************/
00287 
00288 void CachedFontItem::DeleteMetrics()
00289 {
00290     if( NULL == pFontClass )
00291     {
00292         TRACE( _T("structure exists without a FontClass!!!") );
00293     }
00294     
00295     if (pEnumLogFont!=NULL)
00296     {
00297         delete pEnumLogFont;
00298         pEnumLogFont = NULL;
00299     }
00300     
00301     if (pOutlineTextMetric!=NULL)
00302     {
00303         delete pOutlineTextMetric;
00304         pOutlineTextMetric = NULL;
00305     }
00306 }
00307 
00308 void CachedFontItem::DeleteFontClass()
00309 {
00310     if (pFontClass!=NULL)
00311     {
00312         delete pFontClass;
00313         pFontClass=NULL;
00314     }
00315 }
00316 
00317 void CachedFontItem::Delete()
00318 {
00319     DeleteMetrics();    
00320     DeleteFontClass();
00321 }
00322 
00323 /********************************************************************************************
00324 
00325 >   BOOL CachedFontItem::IsFullyCached()
00326 
00327     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00328     Created:    12/09/95
00329     Inputs:     -
00330     Returns:    TRUE if this item is fully cached, FALSE if not
00331     Purpose:    See if this item has all its cached structures resident
00332 
00333 ********************************************************************************************/
00334 
00335 BOOL CachedFontItem::IsFullyCached()
00336 {
00337     PORTNOTE("text","CachedFontItem::IsFullyCached - do nothing");
00338 #ifndef DISABLE_TEXT_RENDERING
00339     // TRACEUSER("wuerthne", _T("CachedFontItem::IsFullyCached called") );
00340     ERROR2IF(pFontClass==NULL, FALSE, "A CachedFontItem structure exists without a FontClass!!!");
00341     return (pEnumLogFont!=NULL);
00342 #else
00343     return TRUE;
00344 #endif
00345 }
00346 
00347 /********************************************************************************************
00348 
00349 >   BOOL CachedFontItem::Compare(String_64* pFontName)
00350 
00351     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00352     Created:    12/09/95
00353     Inputs:     pFontName = A pointer to a font name
00354     Returns:    TRUE if the font name on entry matchs that of this cached font
00355                 FALSE if not
00356     Purpose:    See if this font has the same name as that passed as a param.
00357 
00358 ********************************************************************************************/
00359 
00360 BOOL CachedFontItem::Compare(String_64 *pFontName)
00361 {
00362     if( pFontClass == NULL )
00363     {
00364         TRACE( _T("A CachedFontItem structure exists without a FontClass!!!") );
00365         return FALSE;
00366     }
00367     
00368     return pFontClass->Compare( pFontName );
00369 }   
00370 
00371 
00372 /********************************************************************************************
00373 
00374 >   void CachedFontItem::Dump()
00375 
00376     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00377     Created:    12/09/95
00378     Purpose:    Dump the contents of this cache entry out
00379 
00380 ********************************************************************************************/
00381 
00382 
00383 void CachedFontItem::Dump()
00384 {
00385 #ifdef _DEBUG
00386     ERROR3IF(pFontClass==NULL, "A CachedFontItem structure exists without a FontClass!!!");
00387     TRACE( _T("Font item:\n Handle = %d\n"),Handle);
00388     if (IsFullyCached())
00389     {       
00390         TRACE( _T(" Fully cached\n"));
00391         OILFontMan::DumpEnumLogFont(pEnumLogFont);
00392     }
00393     else
00394     {
00395         TRACE( _T(" Not fully cached\n"));
00396     }
00397     pFontClass->Dump();
00398 #endif
00399 }
00400 
00401 
00402 /********************************************************************************************
00403 
00404 >   BOOL CachedFontItem::SetCacheData(ENUMLOGFONT FAR* lpelf)
00405 
00406     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00407     Created:    12/09/95
00408     Inputs:     lpelf   = a pointer to the logical font description
00409     Returns:    TRUE if we manage to cache this data
00410                 FALSE if not (out of memory)                
00411     Purpose:    This function is called to set the cached data (or metrics) for a particular
00412                 font item. The metrics will have been returned to us from an oil layer
00413                 font manager after a request from us to it to cache them.
00414 
00415 ********************************************************************************************/
00416 
00417 BOOL CachedFontItem::SetCacheData(ENUMLOGFONT FAR* lpelf)
00418 {
00419     ERROR2IF(lpelf==NULL,FALSE,"CachedFontItem::SetCacheData() given a null ENUMLOGFONT structure");
00420     ERROR3IF(pFontClass==NULL, "A CachedFontItem structure exists without a FontClass!!!");
00421 
00422     if (pEnumLogFont!=NULL)
00423     {
00424         ERROR3("Replacing ENUMLOGFONT structure inside CachedFontItem::SetCacheData()");
00425         delete pEnumLogFont;
00426         pEnumLogFont=NULL;
00427     }
00428 
00429     // try a claim memory for the new structure
00430     ENUMLOGFONT * MyEnumLogFont = new ENUMLOGFONT;
00431 
00432     if (MyEnumLogFont==NULL)
00433     {
00434         return FALSE;
00435     }
00436     
00437     // copy the the contents of the structures given as arguments into the new structures
00438     *MyEnumLogFont = *lpelf;
00439 
00440     // and point the pointers to these new structures
00441     pEnumLogFont = MyEnumLogFont;
00442 
00443     return TRUE;
00444 }
00445 
00446 
00447 
00448 // ---------------------- End of CachedFontItem functions -----------------------------------
00449 
00450 
00451 /********************************************************************************************
00452 
00453 >   FontManager::FontManager() 
00454 
00455     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00456     Created:    12/09/95                
00457     Purpose:    Constructor for the font manager class
00458 
00459 ********************************************************************************************/
00460 
00461 FontManager::FontManager()
00462 {
00463     UniqueHandle  = FIRSTFONTHANDLE;
00464     DefaultHandle = DEFAULTHANDLE;
00465     TempFontClass = FC_UNDEFINED;
00466 }
00467 
00468 FontManager::~FontManager()
00469 {
00470     TheFontList.DeleteAll();
00471 }
00472 
00473 /********************************************************************************************
00474 
00475 >   BOOL FontManager::LegalFontClass(INT32 Class, FontClass& RealClass)
00476 
00477     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00478     Created:    12/09/95                
00479     Inputs:     A INT32 describing the font class
00480     Outputs:    The real font class to use for this numeric value
00481     Returns:    TRUE if the font class is supported, FALSE if not
00482     Purpose:    Check whether a numeric value actually indicates a valid class of font
00483                 ie lies in the range of supported font types. This is used generally for
00484                 loading purpose where the font class is loaded as a numeric value.
00485 
00486 ********************************************************************************************/
00487 
00488 BOOL FontManager::LegalFontClass(INT32 Class, FontClass& RealClass)
00489 {
00490     return OILFontMan::LegalFontClass(Class, RealClass);
00491 }
00492 
00493 
00494 /********************************************************************************************
00495 
00496 >   WORD FontManager::GetNextHandle()
00497 
00498     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00499     Created:    12/9/95
00500     Inputs:     -
00501     Outputs:    The next font handle. 
00502     Returns:    -
00503     Purpose:    Return a unique handle for the font cache handler
00504                 Handles range from 1..n, 0 is explicitly reserved for the default
00505                 handle, 0x7FFF is defined as an illegal handle.
00506 
00507 ********************************************************************************************/
00508 
00509 WORD FontManager::GetNextHandle()
00510 {
00511     WORD CurrHandle=UniqueHandle;
00512     UniqueHandle++;
00513     return (CurrHandle);
00514 }
00515 
00516 /********************************************************************************************
00517 
00518 >   BOOL FontManager::Init()
00519 
00520     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00521     Created:    12/09/95                
00522     Inputs:     -
00523     Outputs:    -
00524     Returns:    TRUE if the fontmanager was able to initialise correctly
00525                 FALSE if not
00526     Purpose:    Get Camelots Font manager going. We simply cache the default font so
00527                 unknown fonts can be sensibly replaced.
00528     
00529 ********************************************************************************************/
00530 
00531 BOOL FontManager::Init()
00532 {
00533     // initialise the OIL cache of enumerated fonts by simply enumerating them
00534     // and ignoring the result - since we do not want to see the names, we do
00535     // not even have to create a subclass
00536     OILEnumFonts enumerator;
00537     enumerator.Execute();
00538     if (!CacheDefaultFont())    
00539     {
00540         ERROR3("FontManager::Init() - Unable to cache the default font");
00541     }
00542     return TRUE;
00543 }
00544 
00545 /********************************************************************************************
00546 
00547 >   CachedFontItem* FontManager::GetFirstFont()
00548 
00549     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00550     Created:    12/9/95
00551     Returns:    A pointer to the first cached font item (NULL if none)
00552 
00553 ********************************************************************************************/
00554 
00555 CachedFontItem* FontManager::GetFirstFont()
00556 {
00557     return (CachedFontItem*)TheFontList.GetHead();
00558 }
00559 
00560 /********************************************************************************************
00561 
00562 >   CachedFontItem* FontManager::GetNextFont(CachedFontItem *pItem)
00563 
00564     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00565     Created:    12/9/95
00566     Inputs:     A pointer to a font item to find the next from.
00567     Returns:    A pointer to the next cached font item from pItem 
00568                 (NULL if none)
00569 
00570 ********************************************************************************************/
00571 
00572 CachedFontItem* FontManager::GetNextFont(CachedFontItem* pItem)
00573 {
00574     return (CachedFontItem*)TheFontList.GetNext(pItem);
00575 }
00576 
00577 
00578 
00579 /********************************************************************************************
00580 
00581 >   CachedFontItem* FontManager::AddFont(String_64* Name, FontClass fclass, WORD& Handle)
00582 
00583     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00584     Created:    12/9/95
00585     Inputs:     Name    = a pointer to the font name
00586                 fclass  = a reference to the class of font to add
00587     Outputs:    Handle = ILLEGALFHANDLE if the font could not be added
00588                 Handle = The font handle if ok
00589     Returns:    NULL if the font could not be added
00590                 A pointer to the font record
00591     Purpose:    Creates a new font item for this named font. The font will not be fully
00592                 cached. To cache all the data for the font, call CacheFontData(Handle)
00593 
00594 ********************************************************************************************/
00595 
00596 CachedFontItem* FontManager::AddFont(String_64* Name, FontClass fclass, WORD& retHandle)
00597 {
00598     TRACEUSER("wuerthne", _T("FontManager::AddFont %s"), (TCHAR*)*Name);
00599     CachedFontItem* pItem = new CachedFontItem;
00600     if (pItem==NULL)
00601         return NULL;
00602 
00603     FontBase* pClass = OILFontMan::CreateNewFont(fclass,Name);
00604     if (pClass==NULL)
00605     {
00606         delete pItem;
00607         pItem=NULL;
00608         return NULL;
00609     }
00610 
00611     pItem->pFontClass = pClass;
00612     pItem->Handle = GetNextHandle();
00613     TheFontList.AddTail(pItem);
00614 
00615     retHandle = pItem->Handle;
00616     TRACEUSER("wuerthne", _T("AddFont, returning %d"), retHandle);
00617 
00618     return pItem;
00619 }
00620 
00621 /********************************************************************************************
00622 
00623 >   CachedFontItem* FontManager::FindFont(WORD Handle)
00624 
00625     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00626     Created:    12/9/95
00627     Inputs:     Handle = The font manager font handle
00628     Outputs:    -
00629     Returns:    A pointer to the font managers cached font record for this handle
00630     Purpose:    Find the entry in the font managers font cache which corresponds to this
00631                 handle.
00632 
00633 ********************************************************************************************/
00634 
00635 CachedFontItem* FontManager::FindFont(WORD Handle)
00636 {
00637     // Check the cache first
00638     CachedFontItem* pItem = GetFirstFont();
00639     while (pItem!=NULL)
00640     {
00641         if (pItem->Handle == Handle)
00642             return pItem;
00643         pItem = GetNextFont(pItem);
00644     }
00645     return NULL;
00646 }
00647 
00648 /********************************************************************************************
00649 
00650 >   CachedFontItem* FontManager::FindFont(String_64* pFontName, FontClass Class=FC_UNDEFINED)
00651 
00652     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00653     Created:    12/9/95
00654     Inputs:     pFontName = a pointer to a font name
00655                 Class     = describes the type of class (see typedef for details)
00656                             FC_UNDEFINED then ignore the class match and match the first
00657                             item with the same name whatever font class it is
00658     Outputs:    -
00659     Returns:    A pointer to the font managers cached font record for this font
00660                 NULL if unable to find the font
00661     Purpose:    Find the entry in the font managers font list which corresponds to this
00662                 fontname and font class
00663     Note:       One might be tempted to include the default font item in the comparison
00664                 and return the default font handle when the default font name is passed,
00665                 but this does not happen and this is by design. See OnDocumentLoaded for
00666                 further information.
00667 
00668 ********************************************************************************************/
00669 
00670 CachedFontItem* FontManager::FindFont(String_64* pFontName, FontClass Class)
00671 {
00672     CachedFontItem* pItem = GetFirstFont();
00673 
00674     if (Class==FC_UNDEFINED)
00675     {
00676         while (pItem!=NULL)
00677         {
00678             if (pItem->Compare(pFontName))
00679                 return pItem;
00680             pItem = GetNextFont(pItem); 
00681         }
00682     }
00683     else
00684     {
00685         while (pItem!=NULL)
00686         {
00687             if (pItem->Compare(pFontName))
00688             {
00689                 if (pItem->GetFontClass() == Class)
00690                     return pItem;
00691             }
00692             pItem = GetNextFont(pItem); 
00693         }
00694     }
00695     return NULL;
00696 }
00697 
00698 /********************************************************************************************
00699 
00700 >   CachedFontItem* FontManager::GetCachedFont(WORD Handle)
00701 
00702     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00703     Created:    12/9/95
00704     Inputs:     Handle = The font manager font handle
00705     Outputs:    -
00706     Returns:    A pointer to a cached font record or NULL
00707     Purpose:    This function returns the font associated with the handle passed. If the
00708                 font is not in the cache it will return NULL. It differs from GetFont in
00709                 that it will not attempt to return the DefaultFontItem if it cannot find
00710                 the item specified.
00711 
00712 ********************************************************************************************/
00713 
00714 CachedFontItem* FontManager::GetCachedFont(WORD Handle)
00715 {
00716     if (Handle==DefaultHandle) return (&DefaultFontItem);
00717     return FindFont(Handle);
00718 }
00719 
00720 /********************************************************************************************
00721 
00722 >   WORD FontManager::GetFontHandle(String_64* pFontName, FontClass Class=FC_UNDEFINED)
00723 
00724     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00725     Created:    12/9/95
00726     Inputs:     pFontName = a pointer to a font name
00727                 Class     = describes the class of font to get the handle of
00728     Outputs:    -
00729     Returns:    The handle of the font if the font exists
00730                 The default handle if the font does not exist and Replace is true
00731                 ILLEGALFHANDLE if not
00732     Purpose:    Get the handle on a cached font (if cached) otherwise return the default
00733                 font handle.
00734 
00735 ********************************************************************************************/
00736 
00737 WORD FontManager::GetFontHandle(String_64* pFontName, FontClass Class)
00738 {
00739     ERROR2IF(pFontName==NULL, 0, "FontManager::GetFontHandle() called with an illegal font name pointer");
00740     CachedFontItem* pItem=FindFont(pFontName,Class);
00741     if (pItem!=NULL)
00742         return pItem->GetFontHandle();
00743     
00744     return DefaultHandle;
00745 }
00746 
00747 /********************************************************************************************
00748 
00749 >   CachedFontItem* FontManager::GetFont()
00750 
00751     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00752     Created:    12/9/95
00753     Inputs:     -
00754     Outputs:    -
00755     Returns:    A pointer to a cached font record or NULL
00756     Purpose:    Return the precached default font data to use for rendering.
00757     
00758 ********************************************************************************************/
00759 
00760 CachedFontItem* FontManager::GetFont()
00761 {
00762     return &DefaultFontItem;
00763 }
00764 
00765 /********************************************************************************************
00766 
00767 >   CachedFontItem* FontManager::GetFont(WORD Handle)
00768 
00769     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00770     Created:    12/9/95
00771     Inputs:     Handle = The font manager font handle
00772     Outputs:    -
00773     Returns:    A pointer to a cached font record or NULL
00774     Purpose:    Return the font data to use for rendering. This function performs a specific
00775                 job in avoiding caching the font data. If the font is already cached then
00776                 fine, it is returned for use. If not, the default font is returned.
00777 
00778 ********************************************************************************************/
00779 
00780 CachedFontItem* FontManager::GetFont(WORD Handle)
00781 {
00782     CachedFontItem* pItem = FindFont(Handle);
00783     if ((pItem!=NULL) && (pItem->IsFullyCached()))
00784         return pItem;
00785     return &DefaultFontItem;
00786 }
00787 
00788 /********************************************************************************************
00789 
00790 >   CachedFontItem* FontManager::GetFont(String_64* pFontName, FontClass Class=FC_UNDEFINED)
00791 
00792     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00793     Created:    12/9/95
00794     Inputs:     pFontName = a pointer to a font name
00795                 Class     = describes the type of class (see typedef for details)
00796                             FC_UNDEFINED then ignore the class match and match the first
00797                             item with the same name whatever font class it is
00798     Outputs:    -
00799     Returns:    A pointer to a cached font record or NULL
00800     Purpose:    Return the font data to use for rendering. This function performs a specific
00801                 job in avoiding caching the font data. If the font is already cached then
00802                 fine, it is returned for use. If not, the default font is returned.
00803 
00804 ********************************************************************************************/
00805 
00806 CachedFontItem* FontManager::GetFont(String_64 *pFontName, FontClass Class)
00807 {
00808     CachedFontItem* pItem = FindFont(pFontName, Class);
00809     if ((pItem!=NULL) && (pItem->IsFullyCached()))
00810         return pItem;
00811     return &DefaultFontItem;
00812 }
00813 
00814 /********************************************************************************************
00815 
00816 >   INT32 FontManager::DoesFontExist(String_64* pFontName, 
00817                                     BOOL SearchCache,
00818                                     BOOL SearchInstalled) 
00819 
00820     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00821     Created:    19/05/95
00822     Inputs:     FontName : Name of font to find
00823                 SearchCache : TRUE then search our internal cached fonts
00824                 SearchInstalled: TRUE then search through the installed set of fonts too
00825     Outputs:    -
00826     Returns:    0 if the font cannot be found in the specified search areas
00827                 1 if the font has been installed
00828                 2 if the font has been cached
00829     Purpose:    First check in the cache if necessary, then through the installed set of
00830                 fonts to find whether the named font actually exists
00831 
00832 ********************************************************************************************/
00833 
00834 INT32 FontManager::DoesFontExist(String_64 *pFontName, BOOL SearchCache, BOOL SearchInstalled)
00835 {
00836     if (SearchCache)
00837         if (FindFont(pFontName) != NULL)
00838             return 2;
00839 
00840     if (SearchInstalled)
00841         if (IsFontInstalled(pFontName))
00842             return 1;
00843 
00844     return 0;
00845 }
00846 
00847 /********************************************************************************************
00848 
00849 >   BOOL FontManager::IsFontValid(WORD Handle)
00850 
00851     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00852     Created:    12/9/95
00853     Inputs:     Handle = The font manager font handle
00854     Outputs:    -
00855     Returns:    TRUE if the font is valid and ready to use
00856                 FALSE if not.
00857     Purpose:    Check to see if the font described is actually valid, ie all the metrics
00858                 for the font have been cached correctly.
00859 
00860 ********************************************************************************************/
00861     
00862 BOOL FontManager::IsFontValid(WORD Handle)
00863 {
00864     CachedFontItem* pItem = GetCachedFont(Handle);
00865     return ( (pItem!=NULL) && (pItem->IsFullyCached()) );
00866 }
00867 
00868 /********************************************************************************************
00869 
00870 >   BOOL FontManager::IsFontReplaced(WORD FontHandle)
00871     BOOL FontManager::IsFontReplaced(String_64* pFontName, FontClass Class=FC_UNDEFINED)
00872 
00873     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00874     Created:    12/9/95
00875     Inputs:     pFontName = a pointer to a font name
00876                 Class     = describes the type of class (see typedef for details)
00877                             FC_UNDEFINED then ignore the class match and match the first
00878                             item with the same name whatever font class it is
00879     Outputs:    -
00880     Returns:    TRUE if the font has been replaced by the default
00881                 FALSE if not.
00882     Purpose:    Check to see if the font described has been replaced.
00883 
00884 ********************************************************************************************/
00885 
00886 BOOL FontManager::IsFontReplaced(WORD FontHandle)
00887 {
00888     BOOL Result = FALSE;
00889 
00890     // check whether its the default font, if it is then obviously it's not been replaced.
00891     if (IsFontDefault(FontHandle))
00892     {
00893         Result = FALSE;
00894     }
00895     else
00896     {
00897         CachedFontItem *pItem = FindFont(FontHandle);
00898 
00899         if (pItem==NULL)
00900         {
00901             Result = TRUE;      // font doesn't exist
00902         }
00903         else if (pItem->IsReplaced())
00904         {
00905             Result = TRUE;      // IsReplaced flag is set
00906         }
00907         else if (!pItem->IsValid())
00908         {
00909             Result = TRUE;      // The font isn't valid
00910         }
00911     }
00912 
00913     return Result;
00914 }
00915 
00916 BOOL FontManager::IsFontReplaced(String_64* pFontName, FontClass Class)
00917 {
00918     BOOL Result = FALSE;
00919 
00920     // Check whether its the default font, if it is then obviously it's not been replaced.
00921     if (DefaultFontItem.Compare(pFontName))
00922     {
00923         Result = FALSE;
00924     }
00925     else
00926     {
00927         CachedFontItem *pItem = FindFont(pFontName, Class);
00928 
00929         if (pItem==NULL)
00930         {
00931             Result = TRUE;      // font doesn't exist
00932         }
00933         else if (pItem->IsReplaced())
00934         {
00935             Result = TRUE;      // IsReplaced flag is set
00936         }
00937         else if (!pItem->IsValid())
00938         {
00939             Result = TRUE;      // The font isn't valid
00940         }
00941     }
00942 
00943     return Result;
00944 }
00945 
00946 /********************************************************************************************
00947 
00948 >   BOOL FontManager::IsFontDefault(WORD Handle)
00949 
00950     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00951     Created:    12/9/95
00952     Inputs:     Handle = The font manager font handle
00953     Outputs:    -
00954     Returns:    TRUE if the font handle is the handle describing the default font
00955                 FALSE if not.
00956     Purpose:    Check to see if the font handle described is the handle of the default font
00957                 ie the font which is used to replace unknown fonts (fonts not resident on
00958                 the host machine)
00959 
00960 ********************************************************************************************/
00961 
00962 BOOL FontManager::IsFontDefault(WORD Handle)
00963 {
00964     return (Handle==DefaultHandle);
00965 }
00966 
00967 BOOL FontManager::IsFontDefault(CachedFontItem* pItem)
00968 {
00969     return (pItem == (&DefaultFontItem));
00970 }
00971 
00972 /********************************************************************************************
00973 
00974 >   BOOL FontManager::IsFontUsedInSiblings(Node* pNode, WORD Handle, WORD CurrentHandle, UINT32 Level)
00975 
00976     Author:     Martin Wuerthner <xara@mw-software.com>
00977     Created:    01/08/06
00978     Inputs:     pNode - the root node of the subtree to check
00979                 Handle - a font handle
00980                 CurrentHandle - the font handle applying to the current subtree
00981                 Level - level in the tree (level 0 is NodeDocument, level 1 are default attributes)
00982     Returns:    Returns TRUE if a font attribute with the given handle applies to a text
00983                 object.
00984     Purpose:    Find out whether a given font is used in a document.
00985 
00986 ********************************************************************************************/
00987 
00988 BOOL FontManager::IsFontUsedInSiblings(Node* pNode, WORD Handle, WORD CurrentHandle, UINT32 Level)
00989 {
00990     // perform a standard child-first recursion keeping track of the current font
00991     while(pNode)
00992     {
00993         Node* pFirstChild = pNode->FindFirstChild();
00994         if (pFirstChild && IsFontUsedInSiblings(pFirstChild, Handle, CurrentHandle, Level + 1)) return TRUE;
00995         if (IS_A(pNode, AttrTxtFontTypeface))
00996         {
00997             AttrTxtFontTypeface* pAttr = (AttrTxtFontTypeface*)pNode;
00998             CurrentHandle = pAttr->Value.HTypeface;
00999             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");
01000         }
01001         if (CurrentHandle == Handle && (IS_A(pNode, TextStory) || IS_A(pNode, TextLine) || IS_A(pNode, TextChar)))
01002             return TRUE;
01003         pNode = pNode->FindNext();
01004     }
01005     return FALSE;
01006 }
01007 
01008 /********************************************************************************************
01009 
01010 >   BOOL FontManager::IsFontUsedInDoc(WORD Handle, Document* pDocument)
01011 
01012     Author:     Martin Wuerthner <xara@mw-software.com>
01013     Created:    01/08/06
01014     Inputs:     Handle - a font handle
01015                 pDocument - pointer to a document
01016     Returns:    When called with Handle == DEFAULTHANDLE it returns TRUE if the default
01017                 attribute applies to a text object. Otherwise, it returns TRUE if the supplied
01018                 font handle is used in the document
01019     Purpose:    Find out whether a given font is used in a document.
01020 
01021 ********************************************************************************************/
01022 
01023 BOOL FontManager::IsFontUsedInDoc(WORD Handle, Document* pDocument)
01024 {
01025     Node* pNode = pDocument->GetFirstNode();
01026     return IsFontUsedInSiblings(pNode, Handle, ILLEGALFHANDLE, 0);
01027 }
01028 
01029 /********************************************************************************************
01030 
01031 >   void FontManager::OnDocumentLoaded(Document* pDocument)
01032 
01033     Author:     Martin Wuerthner <xara@mw-software.com>
01034     Created:    01/08/06
01035     Inputs:     pDocument - pointer to the newly created/loaded document
01036     Purpose:    Called after a document has been loaded - allows us to fix the current and
01037                 default fonts if they are not installed. They are only changed if they are
01038                 not used in the document.
01039 
01040                 Fixing the current font is useful because it stops "Arial (missing)" from
01041                 being displayed after start-up if Arial is not installed. The same happens
01042                 when loading a document with the current font set to Arial (or any other
01043                 font that is not installed). We do not touch the current font if it is
01044                 actually used in the document because then, it is possible that it was set
01045                 deliberately (maybe even in a template).
01046 
01047                 One might consider a similar approach for the default font, but by definition,
01048                 the default font is always installed (though it may or may not be Times New
01049                 Roman), so there is no need to change anything. The default attributes are not
01050                 saved with the document, so, in contrast to the current font, there cannot be
01051                 any surprises with fonts that are not installed. The font name referenced by
01052                 the default font does not matter because the default font attribute is never
01053                 inherited by any text object in the document.
01054 
01055                 This is down to the behaviour of FindFont(String_64*,FontClass), which never
01056                 returns the default font handle, so any font attribute created by the text tool
01057                 based on a font name (which involves calling FindFont at some stage) is always
01058                 different from the default attribute (even if it happens to be the same font as
01059                 the default font) and hence this attribute is not optimised away. Therefore, each
01060                 and every text object has a non-default font attribute applied to it.
01061 
01062 ********************************************************************************************/
01063 
01064 void FontManager::OnDocumentLoaded(Document* pDocument)
01065 {
01066     // check if the current font is installed and change it in case it is not (only if the font is not used)
01067     NodeAttribute* pAttr = pDocument->GetAttributeMgr().GetCurrentAttribute(CC_RUNTIME_CLASS(BaseTextClass),
01068                                                                             CC_RUNTIME_CLASS(AttrTxtFontTypeface));
01069     if (pAttr)
01070     {
01071         AttrTxtFontTypeface* pTypeface = (AttrTxtFontTypeface*)pAttr;
01072         WORD Handle = pTypeface->Value.HTypeface;
01073         TRACEUSER("wuerthne", _T("found current font attribute, handle = %d"), Handle);
01074         CachedFontItem *pItem = FindFont(Handle);
01075         if (pItem)
01076         {
01077             String_64* SurfaceFontName = pItem->GetFontName();
01078             TRACEUSER("wuerthne", _T("current font name is %s"), (TCHAR*)*SurfaceFontName);
01079             ENUMLOGFONT *pEnumLogFont = pItem->GetEnumLogFont();
01080             if (pEnumLogFont)
01081             {
01082                 if (!IsFontInstalled(SurfaceFontName) && !IsFontUsedInDoc(Handle, pDocument))
01083                 {
01084                     // the current font is not installed and not used in the document,
01085                     // so find out what the replacement font is and use that instead
01086                     TRACEUSER("wuerthne", _T("font replaced and not used"));
01087                     String_64* NativeFontName = OILFontMan::GetNativeFontName(pItem->GetFontClass(),
01088                                                                               &pEnumLogFont->elfLogFont);
01089                     WORD NewHandle = CacheNamedFont(NativeFontName, pItem->GetFontClass());
01090                     if (NewHandle != ILLEGALFHANDLE)
01091                     {
01092                         TRACEUSER("wuerthne", _T("change current font to handle %d"), NewHandle);
01093                         // modify the current attribute directly
01094                         pTypeface->Value.HTypeface = NewHandle;
01095                     }
01096                 }
01097             }
01098         }
01099     }
01100 }
01101 
01102 /********************************************************************************************
01103 
01104 >   CachedFontItem* FontManager::GetFirstFontType(FontClass Class)
01105 
01106     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01107     Created:    12/9/95
01108     Inputs:     Class = the class of font to retrieve
01109     Outputs:    -
01110     Returns:    A pointer to a cached font record or NULL
01111     Purpose:    Find the entry in the font managers font list which corresponds to the first
01112                 'FontClass' font cached.
01113 
01114 ********************************************************************************************/
01115 
01116 CachedFontItem* FontManager::GetFirstFontType(FontClass Class)
01117 {
01118     CachedFontItem* pItem = GetFirstFont();
01119     while (pItem!=NULL)
01120     {
01121         if (pItem->GetFontClass() == Class)
01122             return pItem;
01123         pItem = GetNextFont(pItem);
01124     }
01125     return NULL;
01126 }
01127 
01128 /********************************************************************************************
01129 
01130 >   ENUMLOGFONT* FontManager::GetEnumLogFont(WORD Handle)
01131 
01132     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01133     Created:    12/9/95
01134     Inputs:     Handle = The font manager font handle
01135     Outputs:    -
01136     Returns:    A pointer to the ENUMLOGFONT structure for this font
01137                 NULL if none
01138     Purpose:    Return the ENUMLOGFONT structure for this font handle.
01139                 Note the function will automatically substitute the default font if the
01140                 handle provided is invalid or the font it describes is not fully cached.
01141 
01142 ********************************************************************************************/
01143 
01144 ENUMLOGFONT* FontManager::GetEnumLogFont(WORD Handle)
01145 {
01146     // ok, we need to get the font data for this particular font item   
01147     CachedFontItem *pItem = GetFont(Handle);
01148     if (pItem!=NULL)
01149     {
01150         return (pItem->GetEnumLogFont());
01151     }
01152     else
01153     {
01154         return NULL;
01155     }
01156 }
01157 
01158 /********************************************************************************************
01159 
01160 >   OUTLINETEXTMETRIC* FontManager::GetOutlineTextMetric(WORD Handle)
01161 
01162     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
01163     Created:    15/08/96
01164     Inputs:     Handle = the font manager handle
01165     Returns:    Pointer to the OUTLINETEXTMETRIC structure for this font, NULL if none
01166     Purpose:    Return the ENUMLOGFONT structure for this font handle
01167                 Note the function will automatically substitute the default font if the
01168                 handle provided is invalid or the font it describes is not fully cached.
01169 
01170 ********************************************************************************************/
01171 
01172 OUTLINETEXTMETRIC* FontManager::GetOutlineTextMetric(WORD Handle)
01173 {
01174     // ok, we need to get the font data for this particular font item
01175     CachedFontItem *pItem = GetFont(Handle);
01176     if (pItem!=NULL)
01177     {
01178         return pItem->GetOutlineTextMetric();
01179     }
01180     else
01181     {
01182         return NULL;
01183     }
01184 }
01185 
01186 /********************************************************************************************
01187 
01188 >   String_64* FontManager::GetFontName(WORD Handle)
01189 
01190     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01191     Created:    12/9/95
01192     Inputs:     Handle = The font manager font handle
01193     Outputs:    -
01194     Returns:    A pointer to the font name associated with this handle
01195                 NULL if the handle is illegal
01196     Purpose:    Return a pointer to the font name given its font handle
01197 
01198 ********************************************************************************************/
01199 
01200 String_64* FontManager::GetFontName(WORD Handle)
01201 {
01202     CachedFontItem* pItem = GetCachedFont(Handle);
01203     if (pItem==NULL)
01204     {
01205         ERROR3("FontManager::GetFontName() - given an illegal handle");
01206         return NULL;
01207     }
01208     return pItem->GetFontName();
01209 }
01210 
01211 
01212 BOOL FontManager::GetFontName(WORD Handle, String_64& OutputString)
01213 {
01214     CachedFontItem* pItem = GetCachedFont(Handle);
01215     if (pItem==NULL)
01216     {
01217         ERROR3("FontManager::GetFontName() - given an illegal handle");
01218         return FALSE;
01219     }
01220     OutputString = *(pItem->GetFontName());
01221     return TRUE;
01222 }
01223 
01224 /********************************************************************************************
01225 
01226 >   FontClass FontManager::GetFontClass(WORD Handle)
01227 
01228     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01229     Created:    12/9/95
01230     Inputs:     Handle = The font manager font handle
01231     Outputs:    -
01232     Returns:    A font class
01233                 FC_UNDEFINED if the handle is unknown
01234     Purpose:    Return what class of font this handle is. 
01235 
01236 ********************************************************************************************/
01237 
01238 FontClass FontManager::GetFontClass(WORD Handle)
01239 {
01240     CachedFontItem* pItem = GetCachedFont(Handle);
01241     if (pItem==NULL)
01242     {
01243         ERROR3("FontManager::GetFontClass() - given an illegal handle");
01244         return FC_UNDEFINED;
01245     }
01246     return pItem->GetFontClass();
01247 }
01248     
01249 /********************************************************************************************
01250 
01251 >   WORD FontManager::FindTypeface(String_64 &TypeFacename,
01252                                    FontClass Class)
01253 
01254     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
01255     Created:    19/08/96
01256     Inputs:     TypeFaceName    - Typeface name of font to search for
01257                 Class           - font class to search for
01258     Returns:    Font handle of typeface, or ILLEGALFHANDLE if not found
01259     Purpose:    Used by the new file format, to check if a particular typeface (and font class)
01260                 is installed and available.
01261     See Also:   class FontComponent
01262 
01263 ********************************************************************************************/
01264 
01265 WORD FontManager::FindTypeface(String_64 &TypeFaceName, FontClass Class)
01266 {
01267     WORD FontHandle = ILLEGALFHANDLE;
01268 
01269     CachedFontItem *pItem=FindFont(&TypeFaceName, Class);
01270 
01271     if (pItem!=NULL)
01272     {
01273         // font is in the cached font list.
01274         FontHandle=pItem->Handle;
01275     }
01276     // now scan the installed lists for this font, and set the local temp font data
01277     else if (TempCacheNamedFont(&TypeFaceName, Class, 1))
01278     {
01279         AddTempFont(&TypeFaceName, Class, FontHandle);
01280     }
01281     // Okay, so we couldn't find the exact font. It may be possible to create the
01282     // font we are after. ATM for instance allows named font instances to be created
01283     // from the base multiple master outlines.
01284     else if (TempCacheNamedFont(&TypeFaceName, Class, 2))
01285     {
01286         AddTempFont(&TypeFaceName, Class, FontHandle);
01287     }
01288     else
01289     // completly unsuccessful. :(
01290     {
01291         FontHandle=ILLEGALFHANDLE;
01292     }
01293 
01294     return FontHandle;
01295 }
01296 
01297 /********************************************************************************************
01298 
01299 >   WORD FontManager::FindClosestFont(const CCPanose &PanoseNumber)
01300 
01301     Author:     Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com>
01302     Created:    20/08/96
01303     Inputs:     PanoseNumber    - panose number to search against
01304     Returns:    Font handle of the closest font
01305     Purpose:    Performs panose matching on the installed fonts
01306 
01307 ********************************************************************************************/
01308 
01309 WORD FontManager::FindClosestFont(const CCPanose &PanoseNumber)
01310 {
01311     // check, is this a 'simple' panose number with just Weight and Letterform components?
01312     if (PanoseNumber.GetFamilyType()==PAN_ANY &&
01313         PanoseNumber.GetSerifStyle()==PAN_ANY &&
01314         PanoseNumber.GetProportion()==PAN_ANY &&
01315         PanoseNumber.GetContrast()==PAN_ANY &&
01316         PanoseNumber.GetStrokeVariation()==PAN_ANY &&
01317         PanoseNumber.GetArmStyle()==PAN_ANY &&
01318         PanoseNumber.GetMidline()==PAN_ANY &&
01319         PanoseNumber.GetXHeight()==PAN_ANY)
01320     {
01321         // These 'simple' panose numbers get saved out for old files and ATM fonts. Obviously
01322         // we can't do any sensible font matching, so just return the default font handle.
01323         return DEFAULTHANDLE;
01324     }
01325     else
01326     {
01327         // shove the data we need into class members.
01328         FindClosestFontHandle = ILLEGALFHANDLE;
01329         FindClosestPanoseNumber = PanoseNumber;
01330         FindClosestDistance = 0xffffffff;
01331         FindClosestTypeFaceName = _T("");
01332         FindClosestFontClass = FC_UNDEFINED;
01333 
01334         // normalise the panose number.
01335         FindClosestPanoseNumber.BodgeToNormal();
01336 
01337         // choose whichever panose font matching algorithm you require:
01338 PORTNOTE("text","TrueType/Win specific code removed")
01339 #ifndef EXCLUDE_FROM_XARALX
01340         // quick - just checks the seven fonts from the Microsoft(tm) Web Font Pack(tm)
01341         return FindClosestFontQuick(PanoseNumber);
01342 #endif
01343 
01344         // full - checks all the fonts installed on the machine.
01345         return FindClosestFontFull(PanoseNumber);
01346     }
01347 } 
01348 
01349 PORTNOTE("text","TrueType/Win specific code removed")
01350 #ifndef EXCLUDE_FROM_XARALX
01351 WORD FontManager::FindClosestFontQuick(const CCPanose &PanoseNumber)
01352 {
01353     WORD MyFontHandle;
01354     String_64 MyFontName;
01355 
01356     // try "Arial"
01357     MyFontName = _T("Arial");
01358     MyFontHandle = CacheNamedFont(&MyFontName, FC_TRUETYPE);
01359     FindClosestFontQuickTry(MyFontHandle);
01360 
01361     // try "Arial Black"
01362     MyFontName = _T("Arial Black");
01363     MyFontHandle = CacheNamedFont(&MyFontName, FC_TRUETYPE);
01364     FindClosestFontQuickTry(MyFontHandle);
01365 
01366     // try "Comic Sans"
01367     MyFontName = _T("Comic Sans");
01368     MyFontHandle = CacheNamedFont(&MyFontName, FC_TRUETYPE);
01369     FindClosestFontQuickTry(MyFontHandle);
01370 
01371     // try "Courier New"
01372     MyFontName = _T("Courier New");
01373     MyFontHandle = CacheNamedFont(&MyFontName, FC_TRUETYPE);
01374     FindClosestFontQuickTry(MyFontHandle);
01375 
01376     // try "Impact"
01377     MyFontName = _T("Impact");
01378     MyFontHandle = CacheNamedFont(&MyFontName, FC_TRUETYPE);
01379     FindClosestFontQuickTry(MyFontHandle);
01380 
01381     // try "Times New Roman"
01382     MyFontName = _T("Times New Roman");
01383     MyFontHandle = CacheNamedFont(&MyFontName, FC_TRUETYPE);
01384     FindClosestFontQuickTry(MyFontHandle);
01385 
01386     // try "Verdana"
01387     MyFontName = _T("Verdana");
01388     MyFontHandle = CacheNamedFont(&MyFontName, FC_TRUETYPE);
01389     FindClosestFontQuickTry(MyFontHandle);
01390 
01391     return FindClosestFontHandle;
01392 } 
01393 
01394 
01395 BOOL FontManager::FindClosestFontQuickTry(WORD MyFontHandle)
01396 {
01397     OUTLINETEXTMETRIC *pOutlineTextMetric = GetOutlineTextMetric(MyFontHandle);
01398 
01399     if (pOutlineTextMetric!=NULL)
01400     {
01401         CCPanose MyPanoseNumber = pOutlineTextMetric->otmPanoseNumber;
01402 
01403         MyPanoseNumber.BodgeToNormal();
01404 
01405         UINT32 MyDistance = CCPanose::Distance(FindClosestPanoseNumber, MyPanoseNumber);
01406 
01407         if (MyDistance<FindClosestDistance)
01408         {
01409             FindClosestFontHandle = MyFontHandle;
01410             FindClosestDistance = MyDistance;
01411         }
01412     }
01413 
01414     return TRUE;
01415 }
01416 #endif
01417 
01418 WORD FontManager::FindClosestFontFull(const CCPanose &PanoseNumber)
01419 {
01420     WORD MyFontHandle;
01421     CachedFontItem *pCachedFontItem;
01422 
01423     // this is particularly rubbish code, since we ask the OS for information about each font
01424     // (the OUTLINETEXTMETRIC structure) and then throw it away if its not needed, rather than
01425     // caching it for the next time. Of course, if this font manager actually held information
01426     // about all the fonts on the system, rather than those in use, it would all be much easier.
01427 
01428     // call the OILFontMan to find the closest font.
01429     OILFontMan::FindClosestFont();
01430 
01431     // We've got the typeface name and font class of the best match, so get the font handle
01432     pCachedFontItem = FindFont(&FindClosestTypeFaceName, FindClosestFontClass);
01433 
01434     if (pCachedFontItem!=NULL)
01435     {
01436         // the font is already cached, so grab the font handle from the CachedFontItem
01437         MyFontHandle=pCachedFontItem->Handle;
01438     }
01439     else
01440     {
01441         // the font hasn't been cached yet, so cache it now.
01442         pCachedFontItem = AddFont(&FindClosestTypeFaceName, FindClosestFontClass, MyFontHandle);
01443         pCachedFontItem->SetCacheData(&FindClosestEnumLogFont);
01444     }
01445 
01446     // return with this font handle
01447     return MyFontHandle;
01448 }
01449 
01450 BOOL FontManager::FindClosestFontFullTry(FontClass Class, String_64 *pTypeFaceName, ENUMLOGFONT *pEnumLogFont)
01451 {
01452     ERROR2IF(pEnumLogFont==NULL, FALSE, "FindClosestTry called with pEnumLogFont==NULL.");
01453 
01454     OUTLINETEXTMETRIC *pOutlineTextMetric;
01455     CCPanose MyPanoseNumber;
01456     UINT32 MyDistance;
01457 
01458     pOutlineTextMetric = OILFontMan::GetOutlineTextMetric(Class, &(pEnumLogFont->elfLogFont));
01459 
01460     if (pOutlineTextMetric!=NULL)
01461     {
01462         MyPanoseNumber = (pOutlineTextMetric->otmPanoseNumber);
01463         MyPanoseNumber.BodgeToNormal();
01464 
01465         MyDistance = CCPanose::Distance(FindClosestPanoseNumber, MyPanoseNumber);
01466 
01467         if (MyDistance<FindClosestDistance)
01468         {
01469             FindClosestDistance = MyDistance;
01470             FindClosestFontClass = Class;
01471             FindClosestTypeFaceName = *(pTypeFaceName);
01472             FindClosestEnumLogFont = *(pEnumLogFont);
01473         }
01474 
01475         free(pOutlineTextMetric);
01476     }
01477     
01478     return TRUE;
01479 }
01480 
01481 /********************************************************************************************
01482 >   void FontManager::InvalidateCharMetrics()
01483 
01484     Author:     Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
01485     Created:    15/1/96
01486     Purpose:    Invalidate char metrics cache
01487 ********************************************************************************************/
01488 
01489 void FontManager::InvalidateCharMetrics()
01490 {
01491     OILFontMan::InvalidateCharMetrics();
01492 }
01493 
01494 /********************************************************************************************
01495 >   BOOL FontManager::GetCharMetrics(CDC* pDC, WCHAR ch, CharDescription& FontDesc, CharMetrics* pCharMetrics);
01496 
01497     Author:     Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
01498     Created:    15/1/96
01499     Inputs:     pDC      - pointer to DC (rather than creating one each time)
01500                 ch       - the char whose metrics are required
01501                 FontDesc - the font
01502     Outputs:    pCharMetrics - the metrics
01503     Returns:    FALSE if fails
01504     Purpose:    Get the char metrics for the given char and font
01505                 Just dispenses the call to the FontMetricsCache
01506 ********************************************************************************************/
01507 
01508 BOOL FontManager::GetCharMetrics(CNativeDC* pDC, WCHAR ch, CharDescription& FontDesc, CharMetrics* pCharMetrics)
01509 {
01510     return OILFontMan::GetCharMetrics(pDC, ch, FontDesc, pCharMetrics);
01511 }
01512 
01513 /********************************************************************************************
01514 >   MILLIPOINT FontManager::GetCharsKerning(CDC* pDC, WCHAR chLeft, WCHAR chRight, CharDescription& FontDesc);
01515 
01516     Author:     Jonathan_Payne (Xara Group Ltd) <camelotdev@xara.com>
01517     Created:    15/10/2000
01518     Inputs:     pDC         - pointer to DC (rather than creating one each time)
01519                 chLeft      - the left char of a kerning pair
01520                 chRight     - the right char of a kerning pair
01521                 FontDesc    - the font
01522     Returns:    Kern distance between chars or 0 on error or no kern
01523     Purpose:    Finds the kerning distance between two chars
01524 ********************************************************************************************/
01525 
01526 MILLIPOINT FontManager::GetCharsKerning(CNativeDC* pDC, WCHAR chLeft, WCHAR chRight, CharDescription& FontDesc)
01527 {
01528     // TRACEUSER("wuerthne", _T("FontManager::GetCharsKerning called\n") );
01529     return OILFontMan::GetCharsKerning(pDC, chLeft, chRight, FontDesc);
01530 }
01531 
01532 /********************************************************************************************
01533 
01534 >   static BOOL FontManager::GetCharPath(CharDescription& ChDesc,
01535                                          DocCoord** ppCoords,
01536                                          PathVerb** ppVerbs,
01537                                          UINT32* pNumCoords,
01538                                          CDC* pDC=NULL)
01539 
01540     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01541     Created:    28/9/95
01542     Inputs:     ChDesc  = description of char
01543                 pDC     = (possible) pointer to a DC (for optimisation) defaults to NULL
01544     Outputs:    ppCoords    = pointer to path coords buffer
01545                 ppVerbs     = pointer to path verbs buffer
01546                 pNumCoords  = number of elements in path
01547     Returns:    FALSE if unable to return the outline
01548     Purpose:    Get the path associated with a given char
01549 
01550 ********************************************************************************************/
01551 
01552 BOOL FontManager::GetCharPath(CharDescription& ChDesc,
01553                               DocCoord** ppCoords,
01554                               PathVerb** ppVerbs,
01555                               UINT32* pNumCoords,
01556                               CNativeDC* pDC)
01557 {
01558     ERROR2IF(ppCoords==NULL,FALSE,"FontManager::GetCharPath pCoords==NULL");
01559     ERROR2IF(ppVerbs==NULL,FALSE,"FontManager::GetCharPath ppVerbs==NULL");
01560     ERROR2IF(pNumCoords==NULL,FALSE,"FontManager::GetCharPath pNumCoords==NULL");
01561 
01562     CachedFontItem* pItem = GetFont(ChDesc.GetTypefaceHandle());
01563     if (pItem==NULL)
01564         return FALSE;
01565 
01566     if (pItem->IsCorrupt())
01567         return FALSE;
01568 
01569     BOOL Success = OILFontMan::GetCharPath(pItem->GetFontClass(), ChDesc, ppCoords, ppVerbs, pNumCoords, pDC);
01570     if (!Success)
01571         pItem->SetIsCorrupt(TRUE);
01572 
01573     return Success;
01574 }
01575 
01576 /********************************************************************************************
01577 
01578 >   BOOL FontManager::CacheDefaultFont()
01579 
01580     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01581     Created:    12/9/95
01582     Inputs:     -
01583     Outputs:    -
01584     Returns:    TRUE if the default font has been cached
01585                 FALSE if not
01586     Purpose:    Cache the default font so we can use this as a replacement when unable to
01587                 find strange fonts.
01588 
01589 ********************************************************************************************/
01590 
01591 BOOL FontManager::CacheDefaultFont()
01592 {
01593     PORTNOTE("text","FontManager::CacheDefaultFont - do nothing");
01594 #ifndef DISABLE_TEXT_RENDERING
01595     if (DefaultFontItem.pFontClass!=NULL)
01596     {
01597         ERROR3("CacheDefaultFont called but a default font is already resident");
01598         return TRUE;
01599     }
01600 
01601     // now scan all installed lists an set out local temp font data
01602     String_64 DefFont(DEFAULTFONTNAME);
01603 
01604     if (!TempCacheNamedFont(&DefFont))
01605         if (!TempCacheNamedFont(NULL))
01606             return FALSE;
01607 
01608     FontBase* pClass = OILFontMan::CreateNewFont(TempFontClass,&TempFontName);
01609     if (pClass==NULL)
01610         return FALSE;
01611 
01612     DefaultFontItem.pFontClass = pClass;
01613     DefaultFontItem.Handle = DEFAULTHANDLE;
01614 
01615     if (!DefaultFontItem.SetCacheData(&TempEnumLogFont))
01616     {
01617         DefaultFontItem.Delete();
01618         return FALSE;
01619     }
01620 
01621     return TRUE;
01622 #else
01623     return TRUE;
01624 #endif
01625 }
01626 
01627 /********************************************************************************************
01628 
01629 >   void FontManager::ResetDefaultFont()
01630 
01631     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01632     Created:    12/9/95
01633     Inputs:     -
01634     Outputs:    -
01635     Returns:    -
01636     Purpose:    Cache the default font so we can use this as a replacement when unable to
01637                 find strange fonts. The cache is checked first to see if the default font
01638                 is already there.
01639 
01640 ********************************************************************************************/
01641 
01642 void FontManager::ResetDefaultFont()
01643 {
01644     DefaultFontItem.Delete();
01645     CacheDefaultFont();
01646 }
01647 
01648 /********************************************************************************************
01649 
01650 >   WORD FontManager::CacheNamedFont(String_64* pFontName, FontClass Class = FC_UNDEFINED)
01651 
01652     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01653     Created:    12/9/95
01654     Inputs:     pFontName = a pointer to a font name
01655                 Class     : the class of font to cache
01656                             FC_UNDEFINED - then try to cache any font by asking each
01657                             font manager in turn.
01658 
01659     Outputs:    -
01660     Returns:    ILLEGALFHANDLE - if unable to cache the named font
01661                 A unique font handle if cached
01662     Purpose:    Given a font name try to cache all the data for that font so that we can
01663                 actually us it. The cache will be checked first to make sure the font
01664                 is not already installed.
01665 
01666 ********************************************************************************************/
01667 
01668 WORD FontManager::CacheNamedFont(String_64* pFontName, FontClass Class)
01669 {
01670     ERROR2IF(pFontName==NULL, ILLEGALFHANDLE, "Bad fontname passed to CacheNamedFont");
01671 
01672     // try to find the font in the cache first
01673     CachedFontItem *pItem = FindFont(pFontName, Class);
01674     if (pItem!=NULL)
01675         return pItem->Handle;
01676     
01677     // now scan all installed lists and set our local temp font data
01678     if (!TempCacheNamedFont(pFontName, Class, 1))
01679     {
01680         // ok we couldn't find the exact font. It may be possible
01681         // to create the font we are after. ATM for instance allows
01682         // named font instances to be created from their base multiple
01683         // master outlines.
01684         TempCacheNamedFont(pFontName, Class, 2);
01685     }
01686     
01687     // add the font that has been returned to us, even if none has.
01688     // if no font has been installed then we will end up having a font cache
01689     // object which describes a font as invalid. This is fine as we now know
01690     // we've done a search for it and it does not exist so we'll use the default
01691     WORD hndle=ILLEGALFHANDLE;
01692     AddTempFont(pFontName, Class, hndle);
01693 
01694     TRACEUSER("wuerthne", _T("FontManager::CacheNamedFont = %d"), hndle);
01695     return (hndle);
01696 }
01697 
01698 /********************************************************************************************
01699 
01700 >   BOOL FontManager::TempCacheNamedFont(String_64 *pFontName, FontClass Class=FC_UNDEFINED, INT32 Pass=1) 
01701 
01702     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01703     Created:    19/05/95                
01704     Inputs:     pFontName : Name of font to search for
01705                 Class     : The class of font to cache
01706                             FC_UNDEFINED - then try to cache any font
01707                 Pass      : 1 - first pass, try to match the font exactly
01708                           : 2 - second pass, try to find a compatible font
01709     Outputs:    -
01710     Returns:    TRUE if the font has been temporarily installed
01711     Purpose:    Search through all the installed sets of fonts for the named font and
01712                 place the result in a temp font.
01713 
01714 ********************************************************************************************/
01715 
01716 BOOL FontManager::TempCacheNamedFont(String_64* pFontName, FontClass Class, INT32 Pass)
01717 {
01718     return (OILFontMan::CacheNamedFont(pFontName, Class, Pass));
01719 }
01720 
01721 /********************************************************************************************
01722 
01723 >   BOOL FontManager::IsFontInstalled(String_64* pFontName, FontClass Class = FC_UNDEFINED)
01724 
01725     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01726     Created:    19/05/95                
01727     Inputs:     pFontName : Name of font to search for
01728                 Class     : The class of font to cache
01729                             FC_UNDEFINED - then try to cache any font
01730     Outputs:    -
01731     Returns:    TRUE if the font has been installed
01732     Purpose:    Search through all the installed sets of fonts for the named font
01733 
01734 ********************************************************************************************/
01735 
01736 BOOL FontManager::IsFontInstalled(String_64* pFontName, FontClass Class)
01737 {
01738     return TempCacheNamedFont(pFontName, Class);
01739 }
01740 
01741 /********************************************************************************************
01742 
01743 >   BOOL FontManager::IsFullyCached(WORD Handle)
01744 
01745     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01746     Created:    12/9/95
01747     Inputs:     Handle = The font manager font handle
01748     Outputs:    -
01749     Returns:    TRUE if the font exists and is cached
01750                 FALSE if not
01751     Purpose:    Find out if the font is fully cached and ready to use. This will generally
01752                 be true of all fonts added by CacheNamedFont. If the font is not fully
01753                 cached then call CacheFontData(). It will not be if AddFont has been used
01754                 to add the font to the font list.
01755 
01756 ********************************************************************************************/
01757 
01758 BOOL FontManager::IsFullyCached(WORD Handle)
01759 {
01760     CachedFontItem* pItem = GetCachedFont(Handle);
01761     if (pItem!=NULL)
01762         return pItem->IsFullyCached();
01763     return FALSE;
01764 }
01765 
01766 /********************************************************************************************
01767 
01768 >   void FontManager::RefreshCache() 
01769 
01770     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01771     Created:    13/9/95
01772     Purpose:    Scans all the cached fonts and checks to see if any are invalid. If a font
01773                 is invalid it is attempted to be made valid.
01774                 This function is generally called when the external worlds fonts have
01775                 changed via install/deinstall.
01776 
01777 ********************************************************************************************/
01778 
01779 void FontManager::RefreshCache()
01780 {
01781     InvalidateCache();
01782     OILFontMan::ValidateCache();
01783     ResetDefaultFont();
01784 }
01785 
01786 /********************************************************************************************
01787 
01788     void FontManager::ValidateItem(FontClass Class, String_64 * pFontName, ENUMLOGFONT * lpelf)
01789 
01790     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01791     Created:    13/9/95
01792     Purpose:    Used as a way of revalidating a cached font. This function is called from
01793                 the various oil level font managers when we've asked them to refresh our
01794                 cache. They simply need to scan their font lists and call this function with
01795                 the new data.
01796 
01797 ********************************************************************************************/
01798 
01799 void FontManager::ValidateItem(FontClass Class, String_64 * pFontName, ENUMLOGFONT * lpelf)
01800 {
01801     CachedFontItem *pItem = FindFont(pFontName,Class);
01802     if (pItem)
01803     {
01804         pItem->SetCacheData(lpelf);
01805         pItem->SetIsReplaced(FALSE);
01806     }
01807 }
01808 
01809 /********************************************************************************************
01810 
01811 >   void FontManager::InvalidateCache()
01812 
01813     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01814     Created:    13/9/95
01815     Purpose:    Scans all the cached fonts deletes all cached data. If the entries are not
01816                 recached all visible fonts will be replaced by the default font.
01817 
01818 ********************************************************************************************/
01819 
01820 void FontManager::InvalidateCache()
01821 {
01822     CachedFontItem *pItem = GetFirstFont();
01823     while (pItem)
01824     {
01825         pItem->DeleteMetrics();
01826         pItem->SetIsCorrupt(FALSE);
01827         pItem->SetIsReplaced(TRUE);
01828         pItem = GetNextFont(pItem);
01829     }
01830 }
01831 
01832 /********************************************************************************************
01833 
01834 >   void FontManager::DumpFontCache()
01835 
01836     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01837     Created:    12/9/95
01838     Purpose:    Dubugging facitity - dumps out the contents of our cache.
01839     
01840 ********************************************************************************************/
01841 
01842 void FontManager::DumpFontCache()
01843 {
01844     CachedFontItem *pItem = GetFirstFont();
01845     while (pItem)
01846     {
01847         pItem->Dump();
01848         pItem = GetNextFont(pItem);
01849     }
01850 }   
01851 
01852 /********************************************************************************************
01853 
01854 >   void FontManager::DumpFont(WORD Handle)
01855 
01856     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01857     Created:    12/9/95
01858     Purpose:    Dubugging facitity - dumps out the contents of a font from our cache.
01859     
01860 ********************************************************************************************/
01861 
01862 void FontManager::DumpFont(WORD Handle)
01863 {
01864     CachedFontItem *pItem = FindFont(Handle);
01865     if (pItem)
01866         pItem->Dump();
01867 }   
01868 
01869 /********************************************************************************************
01870 
01871 >   void FontManager::ClearTempFont()
01872 
01873     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01874     Created:    12/9/95
01875     Purpose:    Throws away any font data stored in the temp font.
01876     
01877 ********************************************************************************************/
01878 
01879 void FontManager::ClearTempFont()
01880 {
01881     TempFontClass=FC_UNDEFINED;
01882     TempFontName.Empty();
01883 }
01884 
01885 /********************************************************************************************
01886 
01887 >   void FontManager::SetTempFont(FontClass Class, String_64 * pFontName, ENUMLOGFONT * lpelf)
01888     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01889     Created:    12/9/95
01890     Purpose:    This function is used by the oil level font managers to set a temporary
01891                 font. There are various other font manager functions which can process the
01892                 temp font.
01893     
01894 ********************************************************************************************/
01895 
01896 void FontManager::SetTempFont(FontClass Class, String_64 * pFontName, ENUMLOGFONT * lpelf)
01897 {
01898     ERROR3IF(lpelf==NULL,"FontManager::SetTempFont() given a null ENUMLOGFONT structure");
01899     ERROR3IF(Class==FC_UNDEFINED, "FontManager::SetTempFont() given an illegal font class");
01900     
01901     TempFontClass=Class;
01902     TempFontName=(*pFontName);
01903     TempEnumLogFont=(*lpelf);
01904 }
01905 
01906 /********************************************************************************************
01907 
01908 >   CachedFontItem* FontManager::AddTempFont(String_64* pFontName, FontClass Class, WORD& hndle)
01909 
01910     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01911     Created:    12/9/95
01912     Inputs:     pFontName = a pointer to the font name
01913                 Class     = describes the type of class (see typedef for details)
01914                             FC_UNDEFINED then ignore the class match and match the first
01915                             item with the same name whatever font class it is
01916     Outputs:    Handle    = ILLEGALFHANDLE if the font could not be added
01917                 Handle    = The font handle if ok
01918     Returns:    NULL if the font could not be added
01919                 A pointer to the font record
01920     Purpose:    Given the temp font data, this function goes and caches that data under
01921                 the provided name and returns the font handle
01922     
01923 ********************************************************************************************/
01924 
01925 CachedFontItem* FontManager::AddTempFont(String_64* pFontName, FontClass Class, WORD& hndle)
01926 {
01927     CachedFontItem* pItem = NULL;
01928     if (TempFontClass==FC_UNDEFINED)
01929     {
01930         if (Class!=FC_UNDEFINED)
01931             pItem = AddFont(pFontName, Class, hndle);
01932         else
01933         {
01934 //          ERROR3("Trying to add a font of an unknown class");
01935             pItem = AddFont(pFontName, FC_TRUETYPE, hndle);
01936         }
01937     }
01938     else
01939     {   
01940         pItem = AddFont(pFontName, TempFontClass, hndle);
01941         if (pItem)
01942             pItem->SetCacheData(&TempEnumLogFont);
01943     }   
01944     return pItem;
01945 }
01946 
01947 /********************************************************************************************
01948 
01949 >   BOOL FontManager::TempFontValid()
01950 
01951     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01952     Created:    12/9/95
01953     Returns:    TRUE if the temp font has been set to a valid font
01954                 FALSE if not
01955     
01956 ********************************************************************************************/
01957 
01958 BOOL FontManager::TempFontValid()
01959 {
01960     return (TempFontClass!=FC_UNDEFINED);
01961 }
01962 
01963 /********************************************************************************************
01964 
01965 >   void FontManager::EncodeFontName(String_64& FontName, String_64& Encoded, INT32 Styles)
01966 
01967     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01968     Created:    18/4/95
01969     Inputs:     FontName    A reference to a font name to encode
01970                 Encoded     'none constant' string reference to a output string buffer
01971                 Styles      = 1 then try to append 'Bold'
01972                             = 2 then try to append 'Italic'
01973                             = 3 then try to append 'BoldItalic'
01974 
01975     Outputs:    Encoded     contains the string built by this function suitable for output
01976                             to an Illustrator 3.0, 5.0 format file.
01977     Returns:    -
01978     Purpose:    Output a font name with bold and italic flags attached. All spaces are
01979                 converted to dashes. The font is first checked for the existance of style
01980                 words bold and italic before new styles are added.
01981 
01982     Notes:      
01983 
01984     FontNames
01985     ---------
01986                             Encodings:
01987     FaceName                (Bold)                      (BoldItalic)
01988     GaramondE               GaramondE-Bold              GaramondE-BoldItalic
01989     EuropeExtraBold         EuropeExtraBold-Bold        EuropeExtraBold-BoldItalic
01990     European Bold Oblique   European-Bold-Oblique       European-Bold-Oblique
01991     deGaulleBlack Italic    deGualleBlack-BoldItalic    deGualleBlack-BoldItalic
01992 
01993 ********************************************************************************************/
01994 
01995 void FontManager::EncodeFontName(String_64& FontName, String_64& Encoded, INT32 Styles)
01996 {
01997     String_64 Copy(FontName);
01998     String_32 Match;
01999     
02000     // Replace all spaces with a hyphen.
02001     Copy.SwapChar(_T(' '),_T('-'));
02002 
02003     INT32 Length = Copy.Length();
02004 
02005     // Find the last hyphen in the font's name.
02006     INT32 LastHyphen = Copy.ReverseFind ( '-' );
02007 
02008     // If there is a -XX extension to the name, remove the hyphen.
02009     if ( LastHyphen == Length - 3 )
02010     {
02011         Copy.Remove ( LastHyphen, 1 );
02012     }
02013 
02014     // Check for bold/italic.
02015     Match = _R(IDS_FONTMAN_MINUS_BOLD); //"-Bold";
02016     INT32 Bld = (Copy.Sub(Match,0,0));
02017 
02018     Match = _R(IDS_FONTMAN_MINUS_ITALIC); //"-Italic";
02019     INT32 Ital = (Copy.Sub(Match,0,0));
02020 
02021     switch (Styles)
02022     {
02023         case 1:
02024         {
02025             if (Bld<0 && Ital<0)
02026             {
02027                 Copy += String_16(_R(IDS_FONTMAN_MINUS_BOLD)); // "-Bold";
02028                 break;
02029             }
02030 
02031             if( ( Bld < 0 ) && ( Ital > -1 ) && ( Length - 7 == Ital ) )
02032             {
02033                 Copy.Insert( String_32(_R(IDS_FONTMAN_BOLD)), Ital );
02034             }
02035             break;
02036         }
02037 
02038         case 2: 
02039         {   
02040             if (Bld<0 && Ital<0)
02041             {
02042                 Copy += String_16(_R(IDS_FONTMAN_MINUS_ITALIC)); // "-Italic";
02043                 break;
02044             }
02045             
02046             if ((Ital<0) && (Bld>-1) && (Length-5==Bld))
02047                 Copy += String_16(_R(IDS_FONTMAN_ITALIC)); //"Italic";
02048             break;
02049         }
02050 
02051         case 3:
02052         {   
02053             if (Bld<0 && Ital<0)
02054             {
02055                 Copy += String_16(_R(IDS_FONTMAN_MINUS_BOLDITALIC)); // "-BoldItalic";
02056                 break;
02057             }
02058 
02059             // If the font contains the word bold at the end, append italic
02060             if( ( Ital < 0 ) && ( Bld > -1 ) && ( Length - 5 == Bld ) )
02061             {
02062                 Copy += String_16(_R(IDS_FONTMAN_ITALIC)); //"Italic";
02063                 break;
02064             }
02065                                     
02066             // If the font already has italic, insert Bold
02067             if( ( Bld < 0 ) && ( Ital > -1 ) && ( Length - 7 == Ital ) )
02068             {
02069                 Copy.Insert( String_32(_R(IDS_FONTMAN_BOLD)), Ital );
02070             }
02071             break;
02072 
02073         }
02074     }
02075 
02076     // Set the encoded output string
02077     Encoded=Copy;
02078 }
02079 
02080 /********************************************************************************************
02081 
02082 >   void FontManager::EncodeAndMapFontName ( String_64& FontName,
02083                                              String_64& Encoded,
02084                                              INT32 Styles )
02085 
02086     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02087     Created:    31/3/00
02088     Inputs:     FontName    - The TrueType font name.
02089                 Encoded     - A string into which the PostScript font name will be written.
02090                 Styles      - Whether the font is bold, italic, or a combination.
02091     Outputs:    Encoded     - Populated with the encoded font name.
02092     Returns:    -
02093     Purpose:    This function first calls EncodeFontName, to generate an approximated
02094                 PostScript font name, before calling a second function to get the PostScript
02095                 font mapping.
02096 
02097 ********************************************************************************************/
02098 
02099 void FontManager::EncodeAndMapFontName ( String_64& FontName,
02100                                          String_64& Encoded,
02101                                          INT32 Styles )
02102 {
02103     String_64   Mapped;
02104 
02105     // First encode the font name.
02106     EncodeFontName ( FontName, Encoded, Styles );
02107 
02108     // And then make the mapping.
02109     if ( Camelot.GetPrefDirect ( _T("EPSFontMapping"), ( TCHAR * ) Encoded, &Mapped ) )
02110     {
02111         // There is a PostScript equivalent stored for this font, so use the mapped
02112         // version as the encoded name.
02113         Encoded = Mapped;
02114     }
02115 }
02116 
02117 /********************************************************************************************
02118 
02119     void FontManager::GetCompatibleFont(const String_64& EncodedName,
02120                                         String_64& CompatibleFont,
02121                                         INT32& Style)
02122 
02123     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02124     Created:    18/4/95
02125     Inputs:     EncodedName     the encoded font name to find a compatible font for.
02126                                 encoded names are those read direct from the native file.
02127     Outputs:    CompatibleFont  contains the decoded fontname suitable for font matching
02128                 Style           b0 = 1 then Bold style should be enabled
02129                                 b1 = 1 then Italic style should be enabled
02130     Returns:    
02131     Purpose:    Find a compatible font to that specified in the encoded font name.
02132                 An encoded name looks something like....
02133 
02134                 Times-New-Roman
02135                 Times-New-Roman-Bold
02136                 Times-New-Roman-Italic
02137                 Times-New-Roman-BoldItalic
02138                 ChiversCond-Bold-Oblique
02139 
02140                 The algorithm used is based on diminishing returns, ie try to find
02141                 the exact font first, then break the fontname up in various increasingly
02142                 complex ways until a valid substitution is found. This substitution
02143                 can then be used for font caching. Note if the fontmanager fails to find
02144                 any match it will return the encodedname as a last resort. When this
02145                 is cached, its metrics will be NULL and hence be replaced by the default
02146                 font automatically be the font manager.
02147 
02148                 extras:
02149                 This function tries to use the font name as specified. If it does not
02150                 exist the function will attempt to use the fontname without styles and
02151                 create styles to fit but only if this new fontname exists. ie it will 
02152                 do the following
02153             
02154                 FontName                    Styles         NameExists     StylesOutput
02155         (1)     Times New Roman BoldItalic                 Yes            BoldOff / ItalicOff
02156         (2)     Times New Roman             Bold/Italic    Yes            BoldOn / ItalicOn
02157         (3)     Times New Roman BoldItalic                 No             BoldOn / ItalicOn
02158 
02159     Errors:
02160 
02161 ********************************************************************************************/
02162 
02163 void FontManager::GetCompatibleFont(const String_64& EncodedName, String_64& CompatibleFont, INT32& Style)
02164 {
02165     // first make a copy of the encoded name
02166     String_64 TryFont(EncodedName);
02167     
02168     // now set the return style
02169     Style=0;
02170 
02171     // Usually the fontnames in the file are saved as /_FontName.Attr-BoldItalic format
02172     if( TryFont.Sub( String_32( _T("_") ),0 ,0 ) == 0 )
02173         TryFont.Remove(0,1);
02174 
02175     // remove our inserted - symbols which are encoded as separators on saving
02176     TryFont.SwapChar('-',' ');
02177 
02178     // Try to find the specified font name, search internal and external caches
02179     INT32 found = DoesFontExist(&TryFont,TRUE,TRUE);
02180     if (found>0)
02181     {
02182         CompatibleFont=TryFont;
02183         return;
02184     }
02185 
02186     // Ok, if we can't find the whole thing, try decoding
02187     String_64 DecodedName;
02188     Style = DecodeFontName(EncodedName, DecodedName);
02189 
02190     // find out what styles this font has
02191     BOOL Bold,Italic;
02192     Bold=((Style & 1) != 0);
02193     Italic=((Style & 2) != 0);
02194 
02195     // if both bold and italic found
02196     if (Bold && Italic)
02197     {
02198         String_64 HoldName(TryFont);
02199         // try to find bold first
02200         INT32 pos = HoldName.Sub( String_32( _T("Italic") ), 0, 0 );
02201         HoldName.Remove(pos,6);
02202         found = DoesFontExist(&HoldName,TRUE,TRUE);
02203         if (found>0)
02204         {
02205             CompatibleFont=HoldName;
02206             return;
02207         }       
02208 
02209         // Then try Italic
02210         HoldName=TryFont;
02211         pos = HoldName.Sub( String_32( _T("Bold") ), 0, 0 );
02212         HoldName.Remove(pos,4);
02213         found = DoesFontExist(&HoldName,TRUE,TRUE);
02214         if (found>0)
02215         {
02216             CompatibleFont=HoldName;
02217             return;
02218         }       
02219     }
02220 
02221     // Does the decoded name exist?, so we can make the rest up in styles?
02222     found = DoesFontExist(&DecodedName,TRUE,TRUE);
02223     if (found>0)
02224     {
02225         CompatibleFont=DecodedName;
02226         return;
02227     }
02228         
02229     // otherwise, we have a font with an extension, eg Trinity.Bold
02230     // (1) Trinity.Bold   - does not exist
02231     // (2) Trinity        - does not exist
02232     // now we set the font to (1), which will be replaced by Times-Roman.
02233     // Now we should also set the font styles too to give us TimesRoman bold
02234 
02235     CompatibleFont=TryFont;
02236 }
02237 
02238 /********************************************************************************************
02239 
02240 >   INT32 FontManager::DecodeFontName(String_64& IStringRef, String_64& OStringRef)
02241 
02242     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02243     Created:    18/4/95
02244     Inputs:     IStringRef  the string to decode.
02245     Outputs:    OStringRef  contains the decoded fontname suitable for font matching
02246     Returns:    Flags       b0 = 1 then Bold style is enabled
02247                             b1 = 1 then Italic style is enabled
02248     Purpose:    Given a fontname encoded for EPS files, return the actual font name suitable
02249                 for font matching and its style definintions (if applicable)
02250 
02251 ********************************************************************************************/
02252 
02253 INT32 FontManager::DecodeFontName(const String_64& IStringRef, String_64& OStringRef)
02254 {
02255     String_32 Match;
02256     String_64 Temp;
02257     INT32 pos,Flags;
02258 
02259     OStringRef.Empty();
02260     Flags=0;
02261     Temp=IStringRef;
02262 
02263     Match = _R(IDS_FONTMAN_MINUS_BOLDITALIC); // "-BoldItalic";
02264     pos = Temp.Sub(Match,0,0);
02265     if (pos>-1)
02266     {
02267         Flags |= 3;
02268         Temp.Left(&OStringRef,pos); 
02269         Temp=OStringRef;        
02270     }
02271     
02272     Match = _R(IDS_FONTMAN_MINUS_BOLD); // "-Bold";
02273     pos = Temp.Sub(Match,0,0);
02274     if (pos>-1)
02275     {
02276         Flags |= 1;
02277         Temp.Left(&OStringRef,pos); 
02278         Temp=OStringRef;        
02279     }
02280 
02281     Match = _R(IDS_FONTMAN_MINUS_ITALIC); // "-Italic";
02282     pos = Temp.Sub(Match,0,0);
02283     if (pos>-1)
02284     {
02285         Flags |= 2;
02286         Temp.Left(&OStringRef,pos); 
02287         Temp=OStringRef;        
02288     }
02289 
02290     // Remove the front _ char
02291     Match = _T("_");
02292     if (Temp.Sub(Match,0,0)==0)
02293         Temp.Remove(0,1);
02294 
02295     Temp.SwapChar('-',' ');
02296     OStringRef = Temp;
02297     return Flags;
02298 }
02299 
02300 /********************************************************************************************
02301 
02302 >   virtual BOOL EnumAllFonts::NewFont(FontClass Class, ENUMLOGFONT FAR* lpelf)
02303 
02304     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02305     Created:    12/9/95
02306     Inputs:     Class = the class of font returned (ATM,TrueType etc)
02307                 lpelf = a pointer to the font design data
02308     Returns:    TRUE if the next font should be enumerated
02309                 FALSE if not
02310     
02311 ********************************************************************************************/
02312 
02313 BOOL EnumAllFonts::NewFont(FontClass Class, ENUMLOGFONT FAR* lpelf)
02314 {
02315     // dont enumerate any more please.
02316     return FALSE;
02317 }

Generated on Sat Nov 10 03:45:21 2007 for Camelot by  doxygen 1.4.4