00001 // $Id: fontcomp.cpp 1464 2006-07-18 12:32:26Z gerry $ 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 /******************************************************************************************** 00099 00100 > fontcomp.cpp 00101 00102 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00103 Created: 06/08/96 00104 Purpose: Implementation of the document font component 00105 00106 ********************************************************************************************/ 00107 00108 // Just a brief summary of the horrors of the way in which Camelot handles fonts. 00109 // 00110 // There seem to be three independent systems handling fonts. The font 00111 // manager looks after installed fonts, specifically those used in 00112 // documents. The font gallery deals with both installed fonts and those 00113 // available (i.e. on the CD) and the text tool infobar deals with the 00114 // installed font families. 00115 // 00116 // Each of these systems enumerates the fonts seperately, independently and 00117 // stores different information about the fonts. The biggedt gripe is with 00118 // the font gallery. When a font gets dragged form the font gallery to a 00119 // text story (to apply the font to the text story) the following steps are 00120 // done: 00121 // 00122 // From the font gallery we know the LOGFONT structure for the font. We 00123 // remember the typeface name and whether its bold or italic (we store 00124 // these as booleans, even though the weight has at least 10 different 00125 // values). Then we ask the font manager for cache a font with the same 00126 // typeface name (doesn't care which font, just any font with the same 00127 // typeface name) and return a font handle. We then create a typeface 00128 // attribute with this font handle and the bold, italic booleans we 00129 // remembered. 00130 // 00131 // The problem is that the font handle just points to any font with the 00132 // same typeface name, _not_ the font that was originally dragged from the 00133 // font manager. i.e. we could end up with the following situations. 00134 // 00135 // Arial Bold Italic dragged from the font gallery 00136 // Typeface attribute: 00137 // font handle -> Arial Regular 00138 // bold -> True 00139 // italic -> True 00140 // 00141 // Arial Regular dragged from the font gallery 00142 // Typeface attribute: 00143 // font handle -> Arial Bold Italic 00144 // bold -> False 00145 // italic -> False 00146 // 00147 // (These do actually happen. The font found by the font manager when asked 00148 // for a font with a particular typeface is the first font installed with 00149 // that typeface. Try deinstalled the arial font family, install Arial Bold 00150 // Italic and then the other members of that family. Then see what happens 00151 // in the debug tree.) 00152 // 00153 // Another point of evidence: 00154 // create four text stories, drag Arial to the first, Arial Bold to the 00155 // second, Arial Italic to the third and Arial Bold Italic to the fourth. 00156 // Then look at the debug tree - the text stories all have typeface 00157 // attributes, all with the same font handle but different bold and italic 00158 // flags. 00159 // 00160 // Summary - after dragging a font from the font gallery to the document 00161 // there's absolutly no way to determine the name of the font originally 00162 // dragged. 00163 // 00164 // Shame really, since this information is required by the new file format. 00165 // The old .xar format gets around this by saving the typeface na,e and the 00166 // two flags and assuming that there are never more than 4 fonts with the 00167 // same typeface; one regular, one bold, one italic and one bold italic 00168 // (great - we'll assume the problem doesn't exist). 00169 // 00170 // So, how can we correct this, since for the new file format we require 00171 // the full font name (we can't get this, remember?), the typeface name and 00172 // the PANOSE number for the original font (which we don't know, since we 00173 // don't know what the font originally dragged was). 00174 // 00175 // Solution 00176 // * ignore the full font name, just save out an empty string 00177 // * save out the typeface name (at least we have something) 00178 // * get the PANOSE number for the font we do have, alter the Weight 00179 // and Letterform members to take into account the bold and italic 00180 // flags. 00181 // 00182 // On import we'll have to get a list of all the fonts with the typeface 00183 // and choose the closest using a metric on the PANOSE numbers - this may 00184 // work, but no guarentees. :( 00185 // 00186 // In order to manage all this information and to provide a method of 00187 // retained font information should we load a file with contains font 00188 // definitions to fonts we don't have, I offer another method of handling 00189 // fonts the FontComponent document component. 00190 // 00191 // When importing a new format file font defintions get matched immediatly 00192 // to one of the installed fonts using the font name, face name and PANOSE 00193 // number. All this information is then added to the font list maintained 00194 // by the FontComponent object attached to the document. Whe we reach a 00195 // font typeface attribute we can just retrieve the necessary information 00196 // and put it into the tree. 00197 // 00198 // Whe exporting a new format file font definitions get requested by the 00199 // font typeface attribute code. We first search the list for a matching 00200 // item in the list, so we can immediatly get the relevant font information 00201 // (in case we're dealiing with a font not installed on this machine). 00202 // Otherwise we'll ask the font manager nicely for the typeface name and 00203 // PANOSE number (We can't get the font name because its all so screwed 00204 // up). Then we'll have to bodge the PANOSE nubmer using the IsBold and 00205 // IsItalic flags in the typeface attribute. Finally we'll put this 00206 // information into our list, write out a font definition record, store the 00207 // record number along side the rest of the information about this font and 00208 // return the record number. 00209 // 00210 // Of course subsequent times we get asked for a font definition record we 00211 // can search the list and return the record number of the original font 00212 // definition record. 00213 // 00214 // Before import and export we need to set all the record numbers to NULL 00215 // to show that they're not valid (i.e. to allow multiple imports and 00216 // exports to and from the same document). 00217 // 00218 // Some of this information could be merged with the font manager (font 00219 // name, face name, PANOSE number), some of this is document specific 00220 // (record number). 00221 // 00222 // There's bound to be some information I've missed out - so go and read 00223 // the code and work out for yourself how its all held together. 00224 // 00225 // Ach. 00226 00227 #include "camtypes.h" 00228 00229 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00230 #include "ccpanose.h" 00231 //#include "fontbase.h" 00232 #include "fontman.h" 00233 00234 #include "cxftags.h" 00235 //#include "cxfrec.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00236 //#include "camfiltr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00237 //#include "filtrres.h" // _R(IDS_NATIVE_FONTWARNING) 00238 00239 //#include "doccomp.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00240 #include "fontcomp.h" 00241 00242 #include "ttfonts.h" 00243 //#include "atmfonts.h" 00244 00245 CC_IMPLEMENT_DYNAMIC(FontComponentClass, DocComponentClass) 00246 CC_IMPLEMENT_DYNAMIC(FontComponentListItem, ListItem) 00247 CC_IMPLEMENT_DYNAMIC(FontComponentList, List) 00248 CC_IMPLEMENT_DYNAMIC(FontComponent, DocComponent) 00249 00250 // Declare smart memory handling in Debug builds 00251 #define new CAM_DEBUG_NEW 00252 00253 /******************************************************************************************** 00254 00255 > BOOL FontComponentClass::Init() 00256 00257 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00258 Created: 06/08/96 00259 Inputs: - 00260 Returns: TRUE if successful, FALSE otherwise 00261 Purpose: Registers the font component with the main application 00262 See Also: class DocComponentClass 00263 00264 ********************************************************************************************/ 00265 00266 BOOL FontComponentClass::Init() 00267 { 00268 // Instantiate a component class to register with the application 00269 FontComponentClass *pClass = new FontComponentClass; 00270 if (pClass==NULL) 00271 { 00272 return FALSE; 00273 } 00274 else 00275 { 00276 GetApplication()->RegisterDocComponent(pClass); 00277 return TRUE; 00278 } 00279 } 00280 00281 /******************************************************************************************** 00282 00283 > BOOL FontComponentClass::AddComponent(BaseDocument *pDoc) 00284 00285 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00286 Created: 06/08/96 00287 Inputs: pDoc - pointer to the document to which we add a component to 00288 Returns: TRUE if successful, FALSE otherwise 00289 Purpose: Adds a font component to the specified document 00290 See Also: class FontComponent 00291 00292 ********************************************************************************************/ 00293 00294 BOOL FontComponentClass::AddComponent(BaseDocument *pDoc) 00295 { 00296 // check to see if this document already has a font component, if so we leave it alone 00297 if (pDoc->GetDocComponent(CC_RUNTIME_CLASS(FontComponent)) != NULL) 00298 { 00299 return TRUE; 00300 } 00301 else 00302 { 00303 // no document component - try to create one for this document 00304 FontComponent *pFontComponent = new FontComponent; 00305 00306 // now add this to the document 00307 pDoc->AddDocComponent(pFontComponent); 00308 00309 // success! 00310 return TRUE; 00311 } 00312 } 00313 00314 /******************************************************************************************** 00315 00316 > FontComponentListItem::FontComponentListItem() 00317 00318 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00319 Created: 09/08/96 00320 Inputs: - 00321 Returns: - 00322 Purpose: Constructor 00323 See Also: class FontComponentList, class FontComponent 00324 00325 ********************************************************************************************/ 00326 00327 FontComponentListItem::FontComponentListItem() 00328 { 00329 mIsBold = FALSE; 00330 mIsItalic = FALSE; 00331 mRecentlyCreated = TRUE; // set to FALSE before any imports or exports 00332 mFontHandle = ILLEGALFHANDLE; 00333 mRecordNumber = 0; 00334 mFullFontName = _T(""); 00335 mTypeFaceName = _T(""); 00336 mFontClass = FC_UNDEFINED; 00337 mPanoseNumber.SetAllToAny(); 00338 } 00339 00340 /******************************************************************************************** 00341 00342 > FontComponentListItem::~FontComponentListItem() 00343 00344 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00345 Created: 09/08/96 00346 Inputs: - 00347 Returns: - 00348 Purpose: Destructor 00349 See Also: class FontComponentList, class FontComponent 00350 00351 ********************************************************************************************/ 00352 00353 FontComponentListItem::~FontComponentListItem() 00354 { 00355 } 00356 00357 /******************************************************************************************** 00358 00359 > FontComponentList::FontComponentList() 00360 00361 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00362 Created: 09/08/96 00363 Inputs: - 00364 Returns: - 00365 Purpose: Constructor 00366 See Also: class FontComponent 00367 00368 ********************************************************************************************/ 00369 00370 FontComponentList::FontComponentList() 00371 { 00372 ExportInitialised=FALSE; 00373 ImportInitialised=FALSE; 00374 } 00375 00376 /******************************************************************************************** 00377 00378 > FontComponentList::~FontComponentList() 00379 00380 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00381 Created: 09/08/96 00382 Inputs: - 00383 Returns: - 00384 Purpose: Destructor 00385 See Also: class FontComponent 00386 00387 ********************************************************************************************/ 00388 00389 FontComponentList::~FontComponentList() 00390 { 00391 ERROR3IF(ExportInitialised==TRUE, "Deconstructor called when ExportInitialised==TRUE"); 00392 ERROR3IF(ImportInitialised==TRUE, "Deconstructor called when ImportInitialised==TRUE"); 00393 00394 DeleteAll(); 00395 } 00396 00397 /******************************************************************************************** 00398 00399 > BOOL FontComponentList::ExportStart() 00400 00401 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00402 Created: 09/08/96 00403 Inputs: - 00404 Returns: TRUE if successful, FALSE otherwise 00405 Purpose: Gives objects of this type a chance to prepare for an export operation. 00406 See Also: class FontComponent 00407 00408 ********************************************************************************************/ 00409 00410 BOOL FontComponentList::ExportStart() 00411 { 00412 ERROR2IF(ExportInitialised!=FALSE, FALSE, "ExportStart called when ExportInitialised!=FALSE."); 00413 00414 FontComponentListItem *pItem = (FontComponentListItem *) GetHead(); 00415 00416 // need to set the mRecentlyCreated and mRecordNumber member of all the elements in the list to NULL 00417 while (pItem!=NULL) 00418 { 00419 pItem->mRecentlyCreated = FALSE; 00420 pItem->mRecordNumber = 0; 00421 pItem = (FontComponentListItem *) GetNext(pItem); 00422 } 00423 00424 ExportInitialised = TRUE; 00425 00426 return TRUE; 00427 } 00428 00429 /******************************************************************************************** 00430 00431 > BOOL FontComponentList::ExportEnd(BOOL Success) 00432 00433 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00434 Created: 09/08/96 00435 Inputs: Success - succcess status of the export operation 00436 Returns: TRUE if successful, FALSE otherwise 00437 Purpose: Gives objects if this class a chance to recover from an export operation, 00438 tidying up if neccessary. 00439 See Also: class FontComponent 00440 00441 ********************************************************************************************/ 00442 00443 BOOL FontComponentList::ExportEnd(BOOL Success) 00444 { 00445 //ERROR2IF(ExportInitialised==FALSE, FALSE, "ExportEnd called when ExportInitialised==FALSE."); 00446 // If we error about the ExportInitialised then we assume that the StartExport has been called. 00447 // This may not be the case if we are in clean up mode. So just handle it! 00448 00449 if (Success==FALSE && ExportInitialised) 00450 { 00451 // export operation was unsuccessful, so need to delete all the entries in the list 00452 // made during the export. this is easy; since the mRecentlyCreated member of all the 00453 // elements in the list was set to FALSE before the export any element with an non-FALSE 00454 // mRecentlyCreated member. 00455 00456 FontComponentListItem *pItem = (FontComponentListItem *) GetHead(); 00457 FontComponentListItem *qItem; 00458 00459 while (pItem!=NULL) 00460 { 00461 qItem = pItem; 00462 pItem = (FontComponentListItem *) GetNext(qItem); 00463 00464 if (qItem->mRecentlyCreated==TRUE) 00465 { 00466 RemoveItem(qItem); 00467 delete qItem; 00468 } 00469 } 00470 } 00471 //else // Removed due to the change to the if statement above 00472 //{ 00473 // // oh well, the export operation was successful, so do nothing 00474 //} 00475 00476 ExportInitialised=FALSE; 00477 return TRUE; 00478 } 00479 00480 /******************************************************************************************** 00481 00482 > FontComponentListItem *FontComponentList::ExportFind(WORD FontHandle, BOOL IsBold, BOOL IsItalic) 00483 00484 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00485 Created: 09/08/96 00486 Inputs: FontHandle : font handle to search for 00487 IsBold : bold flag to search for 00488 IsItalic : italic flag to search for 00489 Returns: Pointer to the matching FontComponentListItem if found, or NULL 00490 Purpose: Searches the list of FontComponentListItem's for a match 00491 See Also: class FontComponentListItem 00492 00493 ********************************************************************************************/ 00494 00495 FontComponentListItem *FontComponentList::ExportFind(WORD FontHandle, BOOL IsBold, BOOL IsItalic) 00496 { 00497 ERROR2IF(ExportInitialised==FALSE, FALSE, "ExportFind called when ExportInitialised==FALSE."); 00498 00499 // auxillary functions, searches using tail recursion. the msvc compiler should 00500 // optimise this quite well - at least, it should 00501 return ExportFindAux((FontComponentListItem *) GetHead(), FontHandle, IsBold, IsItalic); 00502 } 00503 00504 /******************************************************************************************** 00505 00506 > FontComponentListItem *FontComponentList::ExportFindAux(FontComponentListItem *pItem, WORD FontHandle, BOOL IsBold, BOOL IsItalic) 00507 00508 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00509 Created: 09/08/96 00510 Inputs: pItem : current FontComponentListItem of interest 00511 FontHandle : font handle to search for 00512 IsBold : bold flag to search for 00513 IsItalic : italic flag to search for 00514 Returns: Pointer to a matching FontComponentListItem, or null if not found 00515 Purpose: Searches the list of FontComponentListItems for match 00516 See Also: class FontComponentListItem, class FontComponent 00517 00518 ********************************************************************************************/ 00519 00520 FontComponentListItem *FontComponentList::ExportFindAux(FontComponentListItem *pItem, WORD FontHandle, BOOL IsBold, BOOL IsItalic) 00521 { 00522 ERROR2IF(ExportInitialised==FALSE, FALSE, "ExportFindAux called when ExportInitialised==FALSE."); 00523 ERROR2IF(FontHandle==ILLEGALFHANDLE, FALSE, "ExportFindAux called with an illegal font handle."); 00524 00525 if (pItem==NULL) 00526 { 00527 return NULL; 00528 } 00529 else if (pItem->mFontHandle==FontHandle && pItem->mIsBold==IsBold && pItem->mIsItalic==IsItalic) 00530 { 00531 return pItem; 00532 } 00533 else 00534 { 00535 // tail recursion ;) 00536 return ExportFindAux((FontComponentListItem *) GetNext(pItem), FontHandle, IsBold, IsItalic); 00537 } 00538 } 00539 00540 /******************************************************************************************** 00541 00542 > BOOL FontComponentList::ImportStart() 00543 00544 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00545 Created: 09/08/96 00546 Inputs: - 00547 Returns: TRUE if successful, FALSE otherwise 00548 Purpose: Allows objects of this class a chance to initialise before an import operation 00549 See Also: class FontComponent 00550 00551 ********************************************************************************************/ 00552 00553 BOOL FontComponentList::ImportStart() 00554 { 00555 ERROR2IF(ImportInitialised!=FALSE, FALSE, "ImportStart called when ImportInitialised!=FALSE"); 00556 00557 FontComponentListItem *pItem = (FontComponentListItem *) GetHead(); 00558 00559 // need to set the mRecentlyCreated and mRecordNumber members of all the elements in the list 00560 // to FALSE and NULL respectively. 00561 while (pItem!=NULL) 00562 { 00563 pItem->mRecentlyCreated=FALSE; 00564 pItem->mRecordNumber = 0; 00565 pItem = (FontComponentListItem *) GetNext(pItem); 00566 } 00567 00568 ImportInitialised=TRUE; 00569 00570 return TRUE; 00571 } 00572 00573 /******************************************************************************************** 00574 00575 > BOOL FontComponentList::ImportEnd(BOOL Success) 00576 00577 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00578 Created: 09/08/96 00579 Inputs: Success - success status of the import operation 00580 Returns: TRUE if successful, FALSE otherwise 00581 Purpose: Allows objects of this class a chance to recover from an import operation 00582 See Also: class FontComponent 00583 00584 ********************************************************************************************/ 00585 00586 BOOL FontComponentList::ImportEnd(BOOL Success) 00587 { 00588 //ERROR2IF(ImportInitialised==FALSE, FALSE, "ImportEnd called when ImportInitialised==FALSE."); 00589 // If we error about the ImportInitialised then we assume that the StartExport has been called. 00590 // This may not be the case if we are in clean up mode. So just handle it! 00591 00592 if (Success==FALSE && ImportInitialised) 00593 { 00594 // import operation was not successful, so we need to delete any elements in the list 00595 // created during the import. this is easy since all the elements in the list had 00596 // their mRecentlyCreated member set to FALSE before the import - any new elements will 00597 // have mRecentlyCreated==TRUE (thanks to the FontComponentListItem constructor). 00598 00599 FontComponentListItem *pItem = (FontComponentListItem *) GetHead(); 00600 FontComponentListItem *qItem = NULL; 00601 00602 while (pItem!=NULL) 00603 { 00604 qItem = pItem; 00605 pItem = (FontComponentListItem *) GetNext(qItem); 00606 00607 if (qItem->mRecentlyCreated==TRUE) 00608 { 00609 RemoveItem(qItem); 00610 delete qItem; 00611 } 00612 } 00613 } 00614 //else // Removed due to the change to the if statement above 00615 //{ 00616 // // import operation was successful, so just return. 00617 //} 00618 00619 ImportInitialised=FALSE; 00620 return TRUE; 00621 } 00622 00623 /******************************************************************************************** 00624 00625 > FontComponentListItem *FontComponentList::ImportFind(INT32 RecordNumber) 00626 00627 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00628 Created: 09/08/96 00629 Inputs: RecordNumber - record number to search for 00630 Returns: pointer to the matching FontComponentListItem, or NULL if not found. 00631 Purpose: Searches the list for a matching FontComponentListItem. 00632 See Also: class FontComponentListItem, class FontComponent 00633 00634 ********************************************************************************************/ 00635 00636 FontComponentListItem *FontComponentList::ImportFind(INT32 RecordNumber) 00637 { 00638 ERROR2IF(ImportInitialised==FALSE, FALSE, "ImportFind callled when ImportInitialied==FALSE."); 00639 00640 return ImportFindAux((FontComponentListItem *) GetHead(), RecordNumber); 00641 } 00642 00643 /******************************************************************************************** 00644 00645 > FontComponentListItem *FontComponentList::ImportFindAux(FontComponentListItem *pItem, INT32 RecordNumber) 00646 00647 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00648 Created: 09/08/96 00649 Inputs: pItem - current FontComponentListItem of interest 00650 RecordNumber - record number to search for 00651 Returns: pointer to the matching FontComponentListItem or NULL if not found 00652 Purpose: Searches the list for a matching FontComponentListItem 00653 See Also: class FontComponentListItem, class FontComponent 00654 00655 ********************************************************************************************/ 00656 00657 FontComponentListItem *FontComponentList::ImportFindAux(FontComponentListItem *pItem, INT32 RecordNumber) 00658 { 00659 ERROR2IF(ImportInitialised==FALSE, FALSE, "ImportFindAux called when ImportInitialised==FALSE."); 00660 00661 if (pItem==NULL) 00662 { 00663 return NULL; 00664 } 00665 else if (pItem->mRecordNumber==RecordNumber) 00666 { 00667 return pItem; 00668 } 00669 else 00670 { 00671 // tail recursion ;) 00672 return ImportFindAux((FontComponentListItem *) GetNext(pItem), RecordNumber); 00673 } 00674 } 00675 00676 /******************************************************************************************** 00677 00678 > FontComponent::FontComponent() 00679 00680 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00681 Created: 09/08/96 00682 Inputs: - 00683 Returns: - 00684 Purpose: Constructor 00685 See Also: class FontComponent 00686 00687 ********************************************************************************************/ 00688 00689 FontComponent::FontComponent() 00690 { 00691 // constructor for this class, ho hum, 00692 ExportInitialised = FALSE; 00693 ImportInitialised = FALSE; 00694 00695 pFontList = new FontComponentList; 00696 pFontManager = GetApplication()->GetFontManager(); 00697 00698 // Our link to the BaseCamelotFilter 00699 pCamFilter = NULL; 00700 // Set our variable so that we warn about a possible replacement only once 00701 WarnedBefore = FALSE; 00702 } 00703 00704 /******************************************************************************************** 00705 00706 > FontComponent::~FontComponent() 00707 00708 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00709 Created: 09/08/96 00710 Inputs: - 00711 Returns: - 00712 Purpose: Destructor 00713 See Also: class FontComponent 00714 00715 ********************************************************************************************/ 00716 00717 FontComponent::~FontComponent() 00718 { 00719 ERROR3IF(ImportInitialised!=FALSE, "Deconstructor called when ImportInitialised!=FALSE"); 00720 ERROR3IF(ExportInitialised!=FALSE, "Deconstructor called when ExportInitialised!=FALSE"); 00721 00722 if (pFontList) 00723 { 00724 delete pFontList; 00725 pFontList = NULL; 00726 } 00727 } 00728 00729 /******************************************************************************************** 00730 00731 > BOOL FontComponent::StartExport(BaseCamelotFilter *pFilter) 00732 00733 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00734 Created: 09/08/96 00735 Inputs: - 00736 Returns: TRUE if successful, FALSE otherwise 00737 Purpose: Allows the font component a chance to prepare for an export operation 00738 See Also: class FontComponent 00739 00740 ********************************************************************************************/ 00741 00742 BOOL FontComponent::StartExport(BaseCamelotFilter *pFilter) 00743 { 00744 ERROR2IF(ExportInitialised!=FALSE, FALSE, "StartExport called when ExportInitialised!=FALSE"); 00745 ERROR2IF(pFontList==NULL, FALSE, "StartExport called when pFontList==NULL."); 00746 00747 BOOL ok = TRUE; 00748 00749 if (ok) ok = pFontList->ExportStart(); 00750 if (ok) ExportInitialised=TRUE; 00751 00752 return ok; 00753 } 00754 00755 /******************************************************************************************** 00756 00757 > BOOL FontComponent::EndExport(BaseCamelotFilter *pFilter, BOOL Success) 00758 00759 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00760 Created: 09/08/96 00761 Inputs: - 00762 Returns: TRUE if successful, FALSE otherwise 00763 Purpose: Allows the font component a chance to recover from an export operation 00764 See Also: class FontComponent 00765 00766 ********************************************************************************************/ 00767 00768 BOOL FontComponent::EndExport(BaseCamelotFilter *pFilter, BOOL Success) 00769 { 00770 //ERROR2IF(ExportInitialised==FALSE, FALSE, "EndExport called when ExportInitialised==FALSE."); 00771 //ERROR2IF(pFontList==NULL, FALSE, "EndExport called when pFontList==NULL."); 00772 // If we error about the pFontList and ExportInitialised then we assume that the StartExport has been called. 00773 // This may not be the case if we are in clean up mode. So just handle it! 00774 00775 BOOL ok = TRUE; 00776 00777 if (ok && pFontList) ok = pFontList->ExportEnd(Success); 00778 if (ok) ExportInitialised=FALSE; 00779 00780 return ok; 00781 } 00782 00783 /******************************************************************************************** 00784 00785 > INT32 FontComponent::WriteFontDefinition(BaseCamelotFilter *pFilter, WORD FontHandle, BOOL IsBold, BOOL IsItalic) 00786 00787 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00788 Created: 09/08/96 00789 Inputs: pFilter - filter to write font defintion record to 00790 FontHandle - font handle of font definition to write 00791 IsBold - bold flag of font definition 00792 IsItalic - italic flag of font definition 00793 Returns: RecordNumber of font definition, or NULL if unsuccessful 00794 Purpose: Writes a font definition record to the filter, and returns with the record number 00795 of this font definition record. 00796 See Also: class FontComponent, class FontComponentList, class FontComponentListItem 00797 00798 ********************************************************************************************/ 00799 00800 INT32 FontComponent::WriteFontDefinition(BaseCamelotFilter *pFilter, WORD FontHandle, BOOL IsBold, BOOL IsItalic) 00801 { 00802 ERROR2IF(ExportInitialised==FALSE, FALSE, "EndExport called when ExportInitialised==FALSE."); 00803 ERROR2IF(pFilter==NULL, FALSE, "Parameter pFilter==NULL."); 00804 ERROR2IF(FontHandle==ILLEGALFHANDLE, FALSE, "Parameter FontHandle==ILLEGALFHANDLE."); 00805 ERROR2IF(pFontList==NULL, FALSE, "member variable pFontList==NULL."); 00806 00807 INT32 RecordNumber = 0; 00808 FontComponentListItem *pItem; 00809 00810 // is this item already cached? 00811 pItem = pFontList->ExportFind(FontHandle, IsBold, IsItalic); 00812 00813 if (pItem==NULL) 00814 { 00815 // first time we've come across this font, so cache some information about it. 00816 pItem = new FontComponentListItem; 00817 pItem->mFontHandle = FontHandle; 00818 pItem->mIsBold = IsBold; 00819 pItem->mIsItalic = IsItalic; 00820 00821 (void) ExportCacheFont(pItem); // cache the rest of the information about this font 00822 00823 pFontList->AddTail(pItem); 00824 } 00825 00826 // by now, pItem!=NULL, otherwise we've got serious problems 00827 00828 if (pItem!=NULL) 00829 { 00830 // have we already written a font defintion record for this font? i.e. is 00831 // mRecordNumber!=NULL? 00832 if (pItem->mRecordNumber != 0) 00833 { 00834 RecordNumber = pItem->mRecordNumber; 00835 } 00836 else 00837 { 00838 RecordNumber = WriteFontRecord(pFilter, pItem); 00839 pItem->mRecordNumber=RecordNumber; 00840 } 00841 } 00842 else 00843 { 00844 ERROR3("pItem==NULL, and it shouldn't!"); 00845 RecordNumber=0; 00846 } 00847 00848 return RecordNumber; 00849 } 00850 00851 /******************************************************************************************** 00852 00853 > INT32 FontComponent::WriteFontRecord(BaseCamelotFilter *pFilter, FontComponentListItem *pItem) 00854 INT32 FontComponent::WriteTrueTypeRecord(BaseCamelotFilter *pFilter, FontComponentListItem *pItem) 00855 INT32 FontComponent::WriteATMRecord(BaseCamelotFilter *pFilter, FontComponentListItem *pItem) 00856 INT32 FontComponent::WriteUnknownRecord(BaseCamelotFilter *pFilter, FontComponentListItem *pItem) 00857 00858 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00859 Created: 09/08/96 00860 Inputs: pFilter - filter to write 00861 pItem - fontto write a definition for 00862 Returns: Record number of font definition record, or 0 if unsuccessful 00863 Purpose: Writes a font definition record to the filter, and returns with the record number 00864 See Also: class FontComponent, class FontComponentListItem 00865 00866 ********************************************************************************************/ 00867 00868 INT32 FontComponent::WriteFontRecord(BaseCamelotFilter *pFilter, FontComponentListItem *pItem) 00869 { 00870 ERROR2IF(ExportInitialised==FALSE, FALSE, "EndExport called when ExportInitialised==FALSE."); 00871 ERROR2IF(pFilter==NULL, 0, "Parameter pFilter==NULL."); 00872 ERROR2IF(pItem==NULL, 0, "Parameter pItem==NULL."); 00873 00874 INT32 RecordNumber; 00875 00876 switch (pItem->mFontClass) 00877 { 00878 case FC_TRUETYPE : RecordNumber = WriteTrueTypeRecord(pFilter, pItem); break; 00879 case FC_ATM : RecordNumber = WriteATMRecord(pFilter, pItem); break; 00880 default : RecordNumber = WriteUnknownRecord(pFilter, pItem); break; 00881 } 00882 00883 return RecordNumber; 00884 } 00885 00886 INT32 FontComponent::WriteTrueTypeRecord(BaseCamelotFilter *pFilter, FontComponentListItem *pItem) 00887 { 00888 ERROR2IF(ExportInitialised==FALSE, FALSE, "EndExport called when ExportInitialised==FALSE."); 00889 ERROR2IF(pFilter==NULL, 0, "Parameter pFilter==NULL."); 00890 ERROR2IF(pItem==NULL, 0, "Parameter pItem==NULL."); 00891 00892 BOOL ok = TRUE; 00893 INT32 RecordNumber = 0; 00894 00895 CamelotFileRecord Rec(pFilter, TAG_FONT_DEF_TRUETYPE, TAG_FONT_DEF_TRUETYPE_SIZE); 00896 00897 ok = Rec.Init(); 00898 00899 if (ok) ok = Rec.WriteUnicode((TCHAR*)pItem->mFullFontName); 00900 if (ok) ok = Rec.WriteUnicode((TCHAR*)pItem->mTypeFaceName); 00901 if (ok) ok = Rec.WriteCCPanose(pItem->mPanoseNumber); 00902 00903 if (ok) ok = (0 != (RecordNumber = pFilter->WriteDefinitionRecord(&Rec))); 00904 00905 // if ok==TRUE, then by the above line RecordNumber!=NULL. if ok==FALSE then 00906 // RecordNumber==NULL. so we don't need to check ok at this point. 00907 return RecordNumber; 00908 } 00909 00910 INT32 FontComponent::WriteATMRecord(BaseCamelotFilter *pFilter, FontComponentListItem *pItem) 00911 { 00912 ERROR2IF(ExportInitialised==FALSE, FALSE, "EndExport called when ExportInitialised==FALSE."); 00913 ERROR2IF(pFilter==NULL, 0, "Parameter pFilter==NULL."); 00914 ERROR2IF(pItem==NULL, 0, "Parameter pItem==NULL."); 00915 00916 BOOL ok = TRUE; 00917 INT32 RecordNumber = 0; 00918 00919 CamelotFileRecord Rec(pFilter, TAG_FONT_DEF_ATM, TAG_FONT_DEF_ATM_SIZE); 00920 00921 ok = Rec.Init(); 00922 00923 if (ok) ok = Rec.WriteUnicode((TCHAR*)pItem->mFullFontName); 00924 if (ok) ok = Rec.WriteUnicode((TCHAR*)pItem->mTypeFaceName); 00925 if (ok) ok = Rec.WriteCCPanose(pItem->mPanoseNumber); 00926 00927 if (ok) ok = (0 != (RecordNumber = pFilter->WriteDefinitionRecord(&Rec))); 00928 00929 // if ok==TRUE, then by the above line RecordNumber!=NULL. if ok==FALSE then 00930 // RecordNumber==NULL. so we don't need to check ok at this point. 00931 return RecordNumber; 00932 } 00933 00934 INT32 FontComponent::WriteUnknownRecord(BaseCamelotFilter *pFilter, FontComponentListItem *pItem) 00935 { 00936 ERROR2IF(ExportInitialised==FALSE, FALSE, "EndExport called when ExportInitialised==FALSE."); 00937 ERROR2IF(pFilter==NULL, 0, "Parameter pFilter==NULL."); 00938 ERROR2IF(pItem==NULL, 0, "Parameter pItem==NULL."); 00939 00940 ERROR3("Attempt to write an font definition for an unknown file type."); 00941 00942 return 0; 00943 } 00944 00945 /******************************************************************************************** 00946 00947 > BOOL FontComponent::StartImport(BaseCamelotFilter *pFilter) 00948 00949 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00950 Created: 12/08/96 00951 Inputs: pFilter - filter to use 00952 Returns: TRUE if successful, FALSE otherwise 00953 Purpose: Gives objects of type class FontComponent a chance to prepare themselves for 00954 an import operation 00955 See Also: class FontComponent 00956 00957 ********************************************************************************************/ 00958 00959 BOOL FontComponent::StartImport(BaseCamelotFilter *pFilter) 00960 { 00961 ERROR2IF(ImportInitialised!=FALSE, FALSE, "StartImport called when ImportInitialised!=FALSE."); 00962 ERROR2IF(pFontList==NULL, FALSE, "StartImport called when pFontList==NULL."); 00963 00964 // Save this in our link to the BaseCamelotFilter 00965 pCamFilter = pFilter; 00966 // Set our variable so that we warn about a possible replacement only once 00967 WarnedBefore = FALSE; 00968 00969 BOOL ok = TRUE; 00970 00971 if (ok) ok = pFontList->ImportStart(); 00972 if (ok) ImportInitialised=TRUE; 00973 00974 return ok; 00975 } 00976 00977 /******************************************************************************************** 00978 00979 > BOOL FontComponent::EndImport(BaseCamelotFilter *pFilter, BOOL Success) 00980 00981 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 00982 Created: 12/08/96 00983 Inputs: pFilter - filter to use 00984 Success - TRUE if import operation was successful, FALSE otherwise 00985 Returns: TRUE if successful, FALSE otherwise 00986 Purpose: Gives this class a chance to recover from an import operation 00987 See Also: class FontComponent 00988 00989 ********************************************************************************************/ 00990 00991 BOOL FontComponent::EndImport(BaseCamelotFilter *pFilter, BOOL Success) 00992 { 00993 //ERROR2IF(ImportInitialised==FALSE, FALSE, "EndImport called when ImportInitialised==FALSE."); 00994 //ERROR2IF(pFontList==NULL, FALSE, "EndImport called when pFontList==NULL."); 00995 // If we error about the pFontList and ImportInitialised then we assume that the EndExport has been called. 00996 // This may not be the case if we are in clean up mode. So just handle it! 00997 00998 BOOL ok = TRUE; 00999 01000 if (ok && pFontList) ok = pFontList->ImportEnd(Success); 01001 if (ok) ImportInitialised=FALSE; 01002 01003 // Null our link to the BaseCamelotFilter 01004 pCamFilter = NULL; 01005 // Set our variable so that we warn about a possible replacement only once 01006 WarnedBefore = FALSE; 01007 01008 return ok; 01009 } 01010 01011 /******************************************************************************************** 01012 01013 > BOOL FontComponent::ReadFontDefinition(CXaraFileRecord *pRec) 01014 BOOL FontComponent::ReadFontTrueType(CXaraFileRecord *pRec) 01015 BOOL FontComponent::ReadFontATM(CXaraFileRecord *pRec) 01016 BOOL FontComponent::ReadFontDefault(CXaraFileRecord *pRec) 01017 01018 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 01019 Created: 12/08/96 01020 Inputs: pRec : pointer to a CXaraFileRecord to read 01021 Returns: TRUE if successful, FALSE otherwise 01022 Purpose: Reads a font component record from the filter 01023 See Also: class FontComponent, class TextObjRecordHandler 01024 01025 ********************************************************************************************/ 01026 01027 BOOL FontComponent::ReadFontDefinition(CXaraFileRecord *pRec) 01028 { 01029 ERROR2IF(pRec==NULL, FALSE, "Parameter pRec==NULL."); 01030 ERROR2IF(ImportInitialised==FALSE, FALSE, "ReadFontDefinition called when ImportInitialised==FALSE."); 01031 01032 BOOL ok; 01033 01034 switch (pRec->GetTag()) 01035 { 01036 case TAG_FONT_DEF_TRUETYPE : ok = ReadFontTrueType(pRec); break; 01037 case TAG_FONT_DEF_ATM : ok = ReadFontATM(pRec); break; 01038 default : ok = ReadFontUnknown(pRec); break; 01039 } 01040 01041 return ok; 01042 } 01043 01044 BOOL FontComponent::ReadFontTrueType(CXaraFileRecord *pRec) 01045 { 01046 ERROR2IF(ImportInitialised==FALSE, FALSE, "ReadFontTrueType called when ImportInitialised==FALSE."); 01047 ERROR2IF(pRec==NULL, FALSE, "Parameter pRec==NULL."); 01048 ERROR2IF(pFontList==NULL, FALSE, "ReadFontTrueType called when pFontList==NULL."); 01049 01050 BOOL ok = TRUE; 01051 01052 TCHAR Buffer[256]; 01053 FontComponentListItem *pItem = new FontComponentListItem; 01054 01055 pItem->mRecordNumber = pRec->GetRecordNumber(); 01056 01057 pItem->mFontClass = FC_TRUETYPE; 01058 01059 if (ok) ok = pRec->ReadUnicode(Buffer, 256); 01060 pItem->mFullFontName = Buffer; 01061 01062 if (ok) ok = pRec->ReadUnicode(Buffer, 256); 01063 pItem->mTypeFaceName = Buffer; 01064 01065 if (ok) ok = pRec->ReadCCPanose( &(pItem->mPanoseNumber) ); 01066 01067 PORTNOTE("text","FontComponent::ReadFontTrueType - removed ImportCacheFont call"); 01068 #ifndef DISABLE_TEXT_RENDERING 01069 if (ok) ok = ImportCacheFont(pItem); // do all our clever matching 01070 01071 if (ok) pFontList->AddTail(pItem); 01072 #endif 01073 01074 return ok; 01075 } 01076 01077 BOOL FontComponent::ReadFontATM(CXaraFileRecord *pRec) 01078 { 01079 ERROR2IF(ImportInitialised==FALSE, FALSE, "ReadFontATM called when ImportInitialised==FALSE."); 01080 ERROR2IF(pRec==NULL, FALSE, "Parameter pRec==NULL."); 01081 ERROR2IF(pFontList==NULL, FALSE, "ReadFontATM called when pFontList==NULL."); 01082 01083 BOOL ok = TRUE; 01084 01085 TCHAR Buffer[256]; 01086 FontComponentListItem *pItem = new FontComponentListItem; 01087 01088 pItem->mRecordNumber = pRec->GetRecordNumber(); 01089 01090 pItem->mFontClass = FC_ATM; 01091 01092 if (ok) ok = pRec->ReadUnicode(Buffer, 256); 01093 pItem->mFullFontName = Buffer; 01094 01095 if (ok) ok = pRec->ReadUnicode(Buffer, 256); 01096 pItem->mTypeFaceName = Buffer; 01097 01098 if (ok) ok = pRec->ReadCCPanose( &(pItem->mPanoseNumber) ); 01099 01100 PORTNOTE("text","FontComponent::ReadFontATM - removed ImportCacheFont call"); 01101 #ifndef DISABLE_TEXT_RENDERING 01102 if (ok) ok = ImportCacheFont(pItem); // do all our clever matching 01103 01104 if (ok) pFontList->AddTail(pItem); 01105 #endif 01106 return ok; 01107 } 01108 01109 BOOL FontComponent::ReadFontUnknown(CXaraFileRecord *pRec) 01110 { 01111 ERROR2IF(ImportInitialised==FALSE, FALSE, "ReadFontTrueType called when ImportInitialised==FALSE."); 01112 ERROR2IF(pRec==NULL, FALSE, "Parameter pRec==NULL."); 01113 ERROR2IF(pFontList==NULL, FALSE, "ReadFontTrueType called when pFontList==NULL."); 01114 01115 ERROR3("Attempt to read an unrecognised font definition record."); 01116 01117 return FALSE; 01118 } 01119 01120 /******************************************************************************************** 01121 01122 > BOOL FontComponent::GetFontInformation(INT32 RecordNumber, WORD *pFontHandle, BOOL *pIsBold, BOOL *pIsItalic) 01123 01124 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 01125 Created: 12/08/96 01126 Inputs: RecordNumber - Record number of font definition record 01127 Outputs: pFontHandle - pointer to a WORD to return the font maangers font handle in 01128 pIsBold - pointer to a BOOL to return the bold flag in 01129 pIsItalic - pointer to a BOOL to return the italic flag in 01130 Returns: TRUE if successful, FALSE otherwise 01131 Purpose: Retrives information from the font definition record with the corresponding record number 01132 See Also: class FontComponent, class TextAttrRecordHandler 01133 01134 ********************************************************************************************/ 01135 01136 BOOL FontComponent::GetFontInformation(INT32 RecordNumber, WORD *pFontHandle, BOOL *pIsBold, BOOL *pIsItalic) 01137 { 01138 ERROR2IF(ImportInitialised==FALSE, FALSE, "GetFontInformation called when ImportInitialised==FALSE."); 01139 ERROR2IF(pFontList==NULL, FALSE, "GetFontInformation called when pFontList==NULL."); 01140 ERROR2IF(pFontHandle==NULL, FALSE, "GetFontInformation called when pFontHandle==NULL."); 01141 ERROR2IF(pIsBold==NULL, FALSE, "GetFontInformation called when pIsBold==NULL."); 01142 ERROR2IF(pIsItalic==NULL, FALSE, "GetFontInformation called when pIsItalic==NULL."); 01143 01144 BOOL ok; 01145 01146 FontComponentListItem *pItem = pFontList->ImportFind(RecordNumber); 01147 01148 if (pItem==NULL) 01149 { 01150 // oh dear, we can't find the font definition record - possibly an error in the file 01151 ok = TRUE; 01152 01153 // We will warn the user and use a replacement font instead 01154 // If we have a pFilter then ask the default warning handle to append our message 01155 if (pCamFilter) 01156 { 01157 if (!WarnedBefore) 01158 { 01159 pCamFilter->AppendWarning(_R(IDS_NATIVE_FONTWARNING)); 01160 WarnedBefore = TRUE; 01161 } 01162 } 01163 else 01164 ERROR3("FontComponent::GetFontInformation unkown font reference - using default"); 01165 01166 *pFontHandle = DEFAULTHANDLE; 01167 *pIsBold = FALSE; 01168 *pIsItalic = FALSE; 01169 } 01170 else 01171 { 01172 ok = TRUE; 01173 *pFontHandle = pItem->mFontHandle; 01174 *pIsBold = pItem->mIsBold; 01175 *pIsItalic = pItem->mIsItalic; 01176 } 01177 01178 return ok; 01179 } 01180 01181 /******************************************************************************************** 01182 01183 > BOOL FontComponent::ExportCacheFont(FontComponentListItem *pItem) 01184 BOOL FontComponent::ExportCacheFullFontName(FontComponentListItem *pItem) 01185 BOOL FontComponent::ExportCacheTypeFaceName(FontComponentListItem *pItem) 01186 BOOL FontComponent::ExportCacheFontClass(FontComponentListItem *pItem) 01187 BOOL FontComponent::ExportCacheCCPanose(FontComponentListItem *pItem) 01188 01189 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 01190 Created: 12/08/96 01191 Inputs: pItem : FontComponentListItem to complete 01192 Returns: TRUE if successful, FALSE otherwise 01193 Purpose: Caches information about a font in a FontComponentListItem object for export. 01194 See Also: class FontComponentListItem, class FontComponent 01195 01196 ********************************************************************************************/ 01197 01198 BOOL FontComponent::ExportCacheFont(FontComponentListItem *pItem) 01199 { 01200 ERROR2IF(pItem==NULL, FALSE, "Parameter pItem==NULL."); 01201 ERROR2IF(ExportInitialised==FALSE, FALSE, "ExportCacheFont called when ExportInitialised==FALSE."); 01202 ERROR2IF(pFontManager==NULL, FALSE, "ExportCacheFont called when pFontManager==NULL."); 01203 01204 BOOL ok = TRUE; 01205 01206 // members of class FontComponentListItem are: 01207 // BOOL mIsBold : should be already filled in 01208 // BOOL mIsItalic : should be already filled in 01209 // BOOL mRecentlyCreated : leave alone 01210 // WORD mFontHandle : should be already filled in 01211 // INT32 mRecordNumber : leave alone 01212 // String_64 mFullFontName : set to a null string 01213 // String_64 mTypeFaceName : get from the font manager 01214 // FontClass mFontClass : get from the font manager 01215 // CCPanose mPanoseNumber : get from the font manager 01216 01217 // the following order is important - don't change unless you need to. ach - 16/08/96 01218 if (ok) ok = ExportCacheFontClass(pItem); 01219 if (ok) ok = ExportCacheTypeFaceName(pItem); 01220 if (ok) ok = ExportCacheFullFontName(pItem); 01221 if (ok) ok = ExportCacheCCPanose(pItem); 01222 01223 return ok; 01224 } 01225 01226 BOOL FontComponent::ExportCacheFullFontName(FontComponentListItem *pItem) 01227 { 01228 PORTNOTETRACE("text","FontComponent::ExportCacheFullFontName - do nothing"); 01229 #ifndef EXCLUDE_FROM_XARALX 01230 ERROR2IF(pItem==NULL, FALSE, "ExportCacheFullFontName called with pItem==NULL."); 01231 01232 OUTLINETEXTMETRIC *pOutlineTextMetric; 01233 01234 if (NULL!=(pOutlineTextMetric=ExportGetOutlineTextMetricStage1(pItem))) 01235 { 01236 // successful! 01237 pItem->mFullFontName = (char *)(((INT32) pOutlineTextMetric) + ((INT32) pOutlineTextMetric->otmpFaceName)); 01238 } 01239 else 01240 { 01241 if (NULL!=(pOutlineTextMetric=ExportGetOutlineTextMetricStage2(pItem))) 01242 { 01243 // successful! 01244 pItem->mFullFontName = (char *)(((INT32) pOutlineTextMetric) + ((INT32) pOutlineTextMetric->otmpFaceName)); 01245 free(pOutlineTextMetric); // remember to free this result 01246 } 01247 else 01248 { 01249 // unsuccessful. :( 01250 pItem->mFullFontName=""; 01251 } 01252 } 01253 #endif 01254 return TRUE; 01255 } 01256 01257 01258 BOOL FontComponent::ExportCacheTypeFaceName(FontComponentListItem *pItem) 01259 { 01260 ERROR2IF(pItem==NULL, FALSE, "ExportCacheFaceName called with pItem==NULL."); 01261 ERROR2IF(pFontManager==NULL, FALSE, "pFontManager==NULL"); 01262 ERROR2IF(pItem->mFontHandle==ILLEGALFHANDLE, FALSE, "pItem->mFontHandle==ILLEGALFHANDLE."); 01263 01264 BOOL ok = TRUE; 01265 01266 if (ok) ok = pFontManager->GetFontName(pItem->mFontHandle, pItem->mTypeFaceName); 01267 01268 return ok; 01269 } 01270 01271 BOOL FontComponent::ExportCacheFontClass(FontComponentListItem *pItem) 01272 { 01273 ERROR2IF(pItem==NULL, FALSE, "ExportCacheFaceName called with pItem==NULL."); 01274 ERROR2IF(pFontManager==NULL, FALSE, "pFontManager==NULL"); 01275 ERROR2IF(pItem->mFontHandle==ILLEGALFHANDLE, FALSE, "pItem->mFontHandle==ILLEGALFHANDLE."); 01276 01277 BOOL ok = TRUE; 01278 01279 pItem->mFontClass = pFontManager->GetFontClass(pItem->mFontHandle); 01280 01281 return ok; 01282 } 01283 01284 BOOL FontComponent::ExportCacheCCPanose(FontComponentListItem *pItem) 01285 { 01286 ERROR2IF(pItem==NULL, FALSE, "ExportCacheFullFontName called with pItem==NULL."); 01287 01288 OUTLINETEXTMETRIC *pOutlineTextMetric; 01289 01290 if (NULL!=(pOutlineTextMetric=ExportGetOutlineTextMetricStage1(pItem))) 01291 { 01292 // successful! 01293 pItem->mPanoseNumber = pOutlineTextMetric->otmPanoseNumber; 01294 } 01295 else 01296 { 01297 if (NULL!=(pOutlineTextMetric=ExportGetOutlineTextMetricStage2(pItem))) 01298 { 01299 // successful! 01300 pItem->mPanoseNumber = pOutlineTextMetric->otmPanoseNumber; 01301 free(pOutlineTextMetric); // remember to free this result 01302 } 01303 else 01304 { 01305 // unsuccessful. :( 01306 pItem->mPanoseNumber.SetAllToAny(); 01307 } 01308 } 01309 01310 pItem->mPanoseNumber.BodgePanoseNumber(pItem->mIsBold, pItem->mIsItalic); 01311 01312 return TRUE; 01313 } 01314 01315 /******************************************************************************************** 01316 01317 > OUTLINETEXTMETRIC *FontComponent::ExportGetOutlineTextMetricStage1(FontComponentListItem *pItem); 01318 OUTLINETEXTMETRIC *FontComponent::ExportGetOutlineTextMetricStage2(FontComponentListItem *pItem); 01319 01320 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 01321 Created: 15/08/96 01322 Inputs: pItem - pointer to a FontComponentListItem to get the OUTLINETEXTMETRIC for 01323 Returns: Pointer to an OUTLINETEXTMETRIC, or NULL if not found 01324 Purpose: Tries to retrieve the OUTLINETEXTMETRIC structure for a font 01325 01326 Be careful, since the pointer returned by these functions is (and should be) deleted by the 01327 caller. 01328 01329 ********************************************************************************************/ 01330 01331 OUTLINETEXTMETRIC *FontComponent::ExportGetOutlineTextMetricStage1(FontComponentListItem *pItem) 01332 { 01333 PORTNOTETRACE("text","FontComponent::ExportGetOutlineTextMetricStage1 - do nothing"); 01334 #ifndef EXCLUDE_FROM_XARALX 01335 ERROR2IF(pItem==NULL, NULL, "ExportGetOutlineTextMetricStage1 with pItem==NULL."); 01336 01337 // stage 1 - does the font manager have the OUTLINETEXTMETRIC structure for this font? 01338 // 01339 // We'll ask it nicely and see what result it comes backwith. Because the font manager can 01340 // oly cope with one font per typeface (Doh!) we'll ask it for the OUTLINETEXTMETRIC for 01341 // the typeface of the font we're trying to cache, and see if it bears any resemblance to the 01342 // font we originally asked for. 01343 01344 OUTLINETEXTMETRIC *pOutlineTextMetric = pFontManager->GetOutlineTextMetric(pItem->mFontHandle); 01345 01346 if (pOutlineTextMetric!=NULL) 01347 { 01348 // see if it bears any resemblance to the one we want 01349 // 01350 // Here we notice Microsoft's documentation and code don't quite agree. The OUTLINETEXTMETRIC 01351 // structure has 4 strings at the end, the 'family name', 'type name', 'style name' 01352 // and 'full name'. However for, say, Arial Bold: 01353 // 01354 // family name = "Arial" : what we call the typeface name 01355 // face name = "Arial Bold" : what we call the full name 01356 // style name = "Bold" : style name 01357 // full name = "blah blah blah" (not important). 01358 01359 const String_64 TypeFaceName = (char *) (((INT32)pOutlineTextMetric) + ((INT32)pOutlineTextMetric->otmpFamilyName)); 01360 const BOOL IsBold = pOutlineTextMetric->otmTextMetrics.tmWeight > FW_NORMAL; 01361 const BOOL IsItalic = pOutlineTextMetric->otmTextMetrics.tmItalic != 0; 01362 01363 if (TypeFaceName==pItem->mTypeFaceName && IsBold==pItem->mIsBold && IsItalic==pItem->mIsItalic) 01364 { 01365 // hurray, success - so return this result. 01366 } 01367 else 01368 { 01369 // doesn't match, so return NULL; 01370 pOutlineTextMetric = NULL; 01371 } 01372 } 01373 01374 return pOutlineTextMetric; 01375 #endif 01376 return NULL; 01377 } 01378 01379 OUTLINETEXTMETRIC *FontComponent::ExportGetOutlineTextMetricStage2(FontComponentListItem *pItem) 01380 { 01381 PORTNOTETRACE("text","FontComponent::ExportGetOutlineTextMetricStage2 - do nothing"); 01382 #ifndef EXCLUDE_FROM_XARALX 01383 ERROR2IF(pItem==NULL, NULL, "ExportGetOutlineTextMetricStage2 called with pItem==NULL."); 01384 ERROR2IF(pFontManager==NULL, NULL, "pFontManager==NULL."); 01385 ERROR2IF(pItem->mFontHandle==ILLEGALFHANDLE, NULL, "pItem->mFontHandle==ILLEGALFHANDLE."); 01386 01387 OUTLINETEXTMETRIC *pOutlineTextMetric = NULL; 01388 01389 // stage 2 - can we get the OUTLINETEXTMETRIC from one of the oil font managers 01390 // 01391 // Again, we'll ask nicely and see what result we get back. We'll get the LOGFONT from the font 01392 // manager, fill in the weight and italic entries like OSRenderRegion does and see what it comes back 01393 // with. And again we'll check to see if its anything like what we asked for. 01394 01395 ENUMLOGFONT *pEnumLogFont; 01396 LOGFONT MyLogFont; 01397 01398 pEnumLogFont = pFontManager->GetEnumLogFont(pItem->mFontHandle); 01399 01400 if (pEnumLogFont!=NULL) 01401 { 01402 MyLogFont = pEnumLogFont->elfLogFont; 01403 01404 // straight from OSRenderRegion. 01405 MyLogFont.lfWeight = (pItem->mIsBold) ? FW_BOLD : FW_NORMAL; 01406 MyLogFont.lfItalic = (pItem->mIsItalic) ? 1 : 0; 01407 01408 pOutlineTextMetric=OILFontMan::GetOutlineTextMetric(pItem->mFontClass, &MyLogFont); 01409 01410 if (pOutlineTextMetric!=NULL) 01411 { 01412 // we've got an OUTLINETEXTMETRIC, now check to see if its the right one 01413 // 01414 // Here we notice Microsoft's documentation and code don't quite agree. The OUTLINETEXTMETRIC 01415 // structure has 4 strings at the end, the 'family name', 'type name', 'style name' 01416 // and 'full name'. However for, say, Arial Bold: 01417 // 01418 // family name = "Arial" 01419 // face name = "Arial Bold" 01420 // style name = "Bold" 01421 // full name = "blah blah blah" (not important). 01422 01423 const String_64 TypeFaceName = (char *) (((INT32)pOutlineTextMetric) + ((INT32)pOutlineTextMetric->otmpFamilyName)); 01424 const BOOL IsBold = pOutlineTextMetric->otmTextMetrics.tmWeight > FW_NORMAL; 01425 const BOOL IsItalic = pOutlineTextMetric->otmTextMetrics.tmItalic != 0; 01426 01427 if (TypeFaceName==pItem->mTypeFaceName && IsBold==pItem->mIsBold && IsItalic==pItem->mIsItalic) 01428 { 01429 // hurray it is, so do nothing 01430 } 01431 else 01432 { 01433 // No, its not. Free the memory and return NULL. 01434 free(pOutlineTextMetric); 01435 pOutlineTextMetric=NULL; 01436 } 01437 } 01438 else 01439 { 01440 // pOutlineTextMetric==NULL, so we have to return NULL 01441 } 01442 } 01443 else 01444 { 01445 // unable to get the LOGFONT structure, so we'll return NULL 01446 pOutlineTextMetric=NULL; 01447 } 01448 01449 return pOutlineTextMetric; 01450 #endif 01451 return NULL; 01452 } 01453 01454 /******************************************************************************************** 01455 01456 > BOOL FontComponent::ImportCacheFont(FontComponentListItem *pItem) 01457 01458 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 01459 Created: 12/08/96 01460 Inputs: pItem : FontComponentListItem to complete 01461 Returns: TRUE if successful, FALSE otherwise 01462 Purpose: Caches information about a font in a FontComponentListItem for import 01463 See Also: class FontComponentListItem, class FontComponent 01464 01465 Finally, the guts of the clever font matching system for the new file format. From 01466 the font definition record we get the font name (null string), face name and panose 01467 number for a font. We need to find the closest matching font out of all those installed 01468 on this system. 01469 01470 ********************************************************************************************/ 01471 01472 BOOL FontComponent::ImportCacheFont(FontComponentListItem *pItem) 01473 { 01474 ERROR2IF(pItem==NULL, FALSE, "Parameter pItem==NULL."); 01475 ERROR2IF(ImportInitialised==FALSE, FALSE, "ImportCacheFont called when ImportInitialised==FALSE."); 01476 ERROR2IF(pFontManager==NULL, FALSE, "ImportCacheFont called when pFontManager==NULL."); 01477 01478 // members of class FontComponentListItem are: 01479 // BOOL mIsBold : bodge from the panose number 01480 // BOOL mIsItalic : bodge from the panose number 01481 // BOOL mRecentlyCreated : leave alone 01482 // WORD mFontHandle : from the font manager 01483 // INT32 mRecordNumber : leave alone 01484 // String_64 mFullFontName : should already be filled in 01485 // String_64 mTypeFaceName : should already be filled in 01486 // FontClass mFontClass : should already be filled in 01487 // CCPanose mPanoseNumber : should already be filled in 01488 01489 WORD FontHandle; 01490 01491 // Ask the kernel font manager to find this typeface name and class 01492 FontHandle = pFontManager->FindTypeface(pItem->mTypeFaceName, pItem->mFontClass); 01493 01494 if (FontHandle==ILLEGALFHANDLE) 01495 { 01496 // Failed, we ask the kernel font manager just to find this typeface name, ignoring the class 01497 FontHandle = pFontManager->FindTypeface(pItem->mTypeFaceName, FC_UNDEFINED); 01498 } 01499 else if (FALSE==(pFontManager->IsFontValid(FontHandle))) 01500 { 01501 // although the font is in the font cache it's not fully cached. i.e. 01502 // the font has been deinstalled during this session of Camelot. So 01503 // we find a replacement font now... 01504 01505 PORTNOTE("text","FontComponent::ImportCacheFont - Removed FindClosestFont usage"); 01506 #ifndef DISABLE_TEXT_RENDERING 01507 CachedFontItem *pCachedFontItem = pFontManager->GetFont(FontHandle); 01508 01509 WORD BestFontHandle = pFontManager->FindClosestFont(pItem->mPanoseNumber); 01510 ENUMLOGFONT MyEnumLogFont = *(pFontManager->GetEnumLogFont(BestFontHandle)); 01511 01512 // if necessary, get rid of the old ENUMLOGFONT structure 01513 pCachedFontItem->DeleteMetrics(); 01514 01515 pCachedFontItem->SetCacheData(&MyEnumLogFont); 01516 pCachedFontItem->SetIsReplaced(TRUE); 01517 #endif 01518 } 01519 01520 if (FontHandle==ILLEGALFHANDLE) 01521 { 01522 PORTNOTE("text","FontComponent::ImportCacheFont - Removed FindClosestFont usage"); 01523 #ifndef DISABLE_TEXT_RENDERING 01524 01525 // Failed again, so we try to find the closest font using PANOSE font matching. 01526 WORD BestFontHandle = pFontManager->FindClosestFont(pItem->mPanoseNumber); 01527 01528 // Get the correct fontclass for the subsituted font 01529 FontClass BestFontClass = pFontManager->GetFontClass(BestFontHandle); 01530 01531 // add our font to the font manager's list 01532 CachedFontItem *pCachedFontItem = pFontManager->AddFont(&(pItem->mTypeFaceName), BestFontClass, FontHandle); 01533 01534 // fix in the ENUMLOGFONT from the font found above. 01535 ENUMLOGFONT MyEnumLogFont = *(pFontManager->GetEnumLogFont(BestFontHandle)); 01536 pCachedFontItem->SetCacheData(&MyEnumLogFont); 01537 pCachedFontItem->SetIsReplaced(TRUE); 01538 #endif 01539 } 01540 01541 if (FontHandle==ILLEGALFHANDLE) 01542 { 01543 // something has gone wrong. complain, and fix the error 01544 ERROR2(FALSE, "Unable to find a font!."); 01545 FontHandle = DEFAULTHANDLE; 01546 } 01547 01548 pItem->mFontHandle = FontHandle; 01549 01550 // fill in the mIsBold and mIsItalic entries for the FontComponentListItem from the panose number. 01551 pItem->mIsBold = pItem->mPanoseNumber.GetWeight() > PAN_WEIGHT_MEDIUM; // !!HACK!! 01552 pItem->mIsItalic = pItem->mPanoseNumber.GetLetterform() > PAN_LETT_NORMAL_SQUARE; // !!HACK!! 01553 01554 return TRUE; // we succeed - we always succeed! 01555 }