fontcomp.cpp

Go to the documentation of this file.
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 }

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