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