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 }