filters.cpp

Go to the documentation of this file.
00001 // $Id: filters.cpp 1760 2006-09-22 10:13:32Z luke $
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 #include "camtypes.h"
00101 
00102 //#include "filters.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00103 #include "epsfiltr.h"
00104 //#include "coreleps.h"
00105 #include "aw_eps.h"
00106 #include "cameleps.h"
00107 #include "ai_eps.h"
00108 #include "ai5_eps.h"
00109 #include "ai8_eps.h"
00110 //#include "drawfltr.h"
00111 //#include "textfltr.h"
00112 //#include "oilfltrs.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00114 //#include "tim.h"
00115 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00116 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00117 //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00118 #include "progress.h"
00119 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00120 #include "chapter.h"
00121 //#include "group.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00122 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00123 #include "bmpfiltr.h"
00124 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00125 //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00126 #include "native.h"         // The new designed native filter, used for v2
00127 #include "nativeps.h"       // The old style EPS native filter, used in v1.1
00128 #include "layer.h"
00129 //#include "nev.h"
00130 //#include "coplfilr.h"
00131 //#include "cdrfiltr.h"
00132 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00133 //#include "ben.h"
00134 #include "freeeps.h"
00135 //#include "rik.h"
00136 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00137 #include "fontman.h"
00138 //#include "peter.h"
00139 #include "sgliboil.h"       // FileExists
00140 #include "cmxfiltr.h"
00141 //#include "will2.h"
00142 //#include "filtrres.h"
00143 //#include "cmxifltr.h"
00144 #include "exjpeg.h"         // JPEGExportFilter
00145 #include "filtimag.h"       // Imagemap filter
00146 #include "pngfiltr.h"       // for PNG filter class
00147 #include "imjpeg.h"         // for JPEGImportFilter
00148 #include "swffiltr.h"       // For the SWF export filter.
00149 //#include "extfilts.h"     // For the TIFF filter.
00150 #include "kerneldc.h"
00151 #include "xsepsops.h"
00152 
00153 #include "giffiltr.h"       // Transparent and interlaced GIF filter``
00154 #include "htmlfltr.h"       // HTML filter
00155 #include "lineattr.h"
00156 
00157 //#include "andy.h"         //For _R(IDM_OVERWRITE)
00158 //#include "resource.h"     //For _R(IDS_CANCEL)
00159 #include "helpuser.h"       //For SetNextMsgHelpContext()
00160 //#include "resimmap.h"     //For _R(IDM_EXPORT_OVERWRITE)
00161 #include "imgmgkft.h"
00162 
00163 #include "webfiltr.h"       // The new web filter which is the minimilistic form of the new native filter
00164 #include "ftfilter.h"
00165 #include "hardwaremanager.h"
00166 using namespace oilHardwareManager;
00167 
00168 // Ralph's CDR / CMX import state is currently in limbo land... To put
00169 // the filters back in, undefine NOCDRCMX and also add back the relevant
00170 // bits in winoil and kernel.mak
00171 #ifdef RALPH
00172 //#define NOCDRCMX 1
00173 #endif
00174 
00175 CC_IMPLEMENT_DYNAMIC(Filter, CCObject)
00176 
00177 CC_IMPLEMENT_DYNAMIC(VectorFilter,  Filter)
00178 CC_IMPLEMENT_DYNAMIC(BitmapFilter,  Filter)
00179 CC_IMPLEMENT_DYNAMIC(FilterFamily, Filter)
00180 CC_IMPLEMENT_DYNAMIC(GenericFilter, FilterFamily)
00181 CC_IMPLEMENT_DYNAMIC(VectorFilterFamily, FilterFamily)
00182 CC_IMPLEMENT_DYNAMIC(BitmapFilterFamily, FilterFamily)
00183 CC_IMPLEMENT_DYNAMIC(GenericEPSFilter, FilterFamily)
00184 #ifndef NOCDRCMX
00185 CC_IMPLEMENT_DYNAMIC(PaletteFilterFamily, FilterFamily)
00186 #endif
00187 
00188 #if BUILD_TEXT_FILTERS
00189 CC_IMPLEMENT_DYNAMIC(TextFilter,  Filter)
00190 CC_IMPLEMENT_DYNAMIC(TextFilterFamily, FilterFamily)
00191 #endif
00192 
00193 CC_IMPLEMENT_MEMDUMP(SnapShotList, CC_CLASS_MEMDUMP);
00194 CC_IMPLEMENT_MEMDUMP(SnapShotItem, ListItem);
00195 CC_IMPLEMENT_MEMDUMP(AttrRecordList, CC_CLASS_MEMDUMP);
00196 CC_IMPLEMENT_MEMDUMP(AttrRecordItem, ListItem);
00197 
00198 
00199 // Declare smart memory handling in Debug builds
00200 #define new CAM_DEBUG_NEW
00201 
00202 
00203 // Initialised to "no override".
00204 UINT32 Filter::m_nForcedStatusExportMessage = 0;
00205 
00206 ID Filter::m_NextFilterID   = FILTERID_ALDUS_END + 1;
00207 
00208 
00209 /********************************************************************************************
00210 
00211 >   BOOL FilterFlags::operator==(const FilterFlags Flags)
00212 
00213     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00214     Created:    29/03/94
00215     Inputs:     Flags - the flags to test against.
00216     Returns:    TRUE or FALSE!
00217     Purpose:    Test FilterFlags for equality!
00218 
00219 ********************************************************************************************/
00220 
00221 BOOL FilterFlags::operator==(const FilterFlags Flags)
00222 {
00223     return (CanImport == Flags.CanImport) && (CanExport == Flags.CanExport) &&
00224            (ShowFilter == Flags.ShowFilter) && (CanExportMultipleImages == Flags.CanExportMultipleImages);
00225 }
00226 
00227 
00228 
00229 
00230 // The global list of installed filters.
00231 List Filter::FilterList;
00232 
00233 // Er..dunno actually
00234 GenericFilter *Filter::pGenericFilter = NULL;
00235 
00236 //
00237 // Variables used for progress display update...
00238 //
00239 
00240 // The number of nodes saved out so far (also used for accumulating total
00241 // while scanning the tree.
00242 UINT32 Filter::NumNodes = 0;
00243 
00244 // Indicates how many 'nodes' should be saved before we update the progress bar.
00245 UINT32 Filter::UpdateEvery = 1;
00246 
00247 // The last time we updated the progress bar (in terms of nodes saved out).
00248 UINT32 Filter::LastExportProgressUpdate = 0;
00249 
00250 // The maximum limit on the current export sub-operation - i.e. this ensures that
00251 // incorrect exporting code cannot screw up the rest of the progress bar system.
00252 UINT32 Filter::CurrentProgressLimit = 0;
00253 
00254 // Allows a ExportRenderer to cope with rendering in strips where mulit-pass rendering
00255 // will be happening. If the progress is started with NumNodes * number of strips we
00256 // we need to have an offset for the start of each strip. This allows this to happen. 
00257 UINT32 Filter::ProgressOffset = 0;
00258 
00259 UINT32 Filter::m__StripStart = 0;
00260 
00261 // Preference settings
00262 
00263 /********************************************************************************************
00264 
00265     Preference: MinLineWidth
00266     Section:    Filters
00267     Range:      Between 0 and 10,000.
00268     Purpose:    Controls how line widths are handled - if a line width thinner than the
00269                 value of this preference is found, then the line width is forced to be
00270                 this width.  E.g. set it to 500 to make all imported lines be at least
00271                 0.5 points wide.  (It defaults to 0.25pt)
00272     SeeAlso:    AddUnnamedColours
00273 
00274 ********************************************************************************************/ 
00275 
00276 INT32 Filter::MinLineWidth = 250;
00277 
00278 /********************************************************************************************
00279 
00280     Preference: ImportWithLayers
00281     Section:    Filters
00282     Range:      TRUE or FALSE.
00283     Purpose:    Controls how files are imported:
00284                     TRUE => Layers are imported/created as necessary when importing.
00285                    FALSE => Layers are ignore when importing, and the whole imported
00286                             file is placed in the document as a group.
00287     SeeAlso:    Filter
00288 
00289 ********************************************************************************************/ 
00290 #ifdef WEBSTER
00291 // Layers are bad in Webster as it conflicts with frames
00292 INT32 Filter::ImportWithLayers = 0; // dont import layers
00293 #else
00294 INT32 Filter::ImportWithLayers = 2; // import layers with the names they were given
00295 #endif // WEBSTER
00296 
00297 /********************************************************************************************
00298 
00299     Preference: OpenWithLayers
00300     Section:    Filters
00301     Range:      TRUE or FALSE.
00302     Purpose:    Controls how files are opened:
00303                     TRUE => Layers are imported/created as necessary when opening a file.
00304                    FALSE => Layers are ignore when importing, and the whole opened
00305                             file is placed in the document as a group.
00306     Note:       Does not affect v2 Native file formats such as xar and web.
00307 
00308 ********************************************************************************************/ 
00309 #ifdef WEBSTER
00310 // Layers are bad in Webster as it conflicts with frames
00311 BOOL Filter::OpenWithLayers = FALSE;
00312 #else
00313 BOOL Filter::OpenWithLayers = TRUE;
00314 #endif // WEBSTER
00315 
00316 /********************************************************************************************
00317 
00318     Preference: ImportBitmapsOntoLayers
00319     Section:    Filters
00320     Range:      TRUE or FALSE.
00321     Purpose:    Controls how bitmap files are opened/imported:
00322                     TRUE => each bitmap is placed on a new layer.
00323                    FALSE => each bitmaps is placed on the current layer.
00324                 Applies to multiple format bitmaps such as animated GIFs
00325 
00326 ********************************************************************************************/ 
00327 
00328 BOOL Filter::ImportBitmapsOntoLayers = TRUE;
00329 
00330 /********************************************************************************************
00331 
00332     Preference: bDontWarnBitmapNonMixTransp
00333     Section:    Filters
00334     Range:      TRUE or FALSE.
00335     Purpose:    Controls how bitmap files are opened/imported:
00336                     TRUE => each bitmap is placed on a new layer.
00337                    FALSE => each bitmaps is placed on the current layer.
00338                 Applies to multiple format bitmaps such as animated GIFs
00339 
00340 ********************************************************************************************/ 
00341 
00342 BOOL Filter::bDontWarnBitmapNonMixTransp = FALSE;
00343 
00344 /********************************************************************************************
00345 
00346     Preference: AddUnnamedColours
00347     Section:    Filters
00348     Range:      TRUE or FALSE
00349     Purpose:    If it is TRUE then any colours used in the imported file but not explicitly
00350                 named by whatever colour table structure the file uses will be created
00351                 as named colours (usu. of the form Unnamed 1, Unnamed 2 and so on).
00352                 If FALSE, immediate colours will be used, and will not appear on the
00353                 document's colour bar.
00354                 Defaults to FALSE.
00355     SeeAlso:    MinLineWidth
00356 
00357 ********************************************************************************************/ 
00358 
00359 BOOL Filter::AddUnnamedColours = FALSE;
00360 
00361 /********************************************************************************************
00362 
00363 >   Filter::Filter ()
00364 
00365     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00366     Created:    22/02/94
00367     Purpose:    Set the Filter object up to be in a clean state.
00368     SeeAlso:    Filter; Filter::~Filter; OILFilter
00369 
00370 ********************************************************************************************/
00371 
00372 Filter::Filter ()
00373 {
00374     // Ensure destructor will not corrupt heap
00375     pOILFilter = NULL;
00376     CurrentAttrs = NULL;
00377     FillAttr.pAttr = NULL;
00378     FillAttr.Temp = FALSE;
00379     FillAttr.Ignore = FALSE;
00380 
00381     // Set default of no export message
00382     ExportMsgID = 0;
00383     
00384     // Set default message of none (use default message)
00385     StopExportMsgID = 0;
00386 
00387     // Set default of no import message
00388     ImportMsgID = 0;
00389 
00390     // No document yet...
00391     TheDocument = NULL;
00392 
00393     // No Preview Bitmap Please
00394     WantPreviewBmp = FALSE;
00395 
00396     // Ensure these are at known states, set them to do nothing so people have to change them
00397     Flags.CanImport = FALSE;
00398     Flags.CanExport = FALSE;
00399     Flags.CanExportMultipleImages = FALSE;
00400 
00401     // Want to show filters by default, unless the user specificaly requests otherwise
00402     Flags.ShowFilter = TRUE;
00403 
00404     // set the path filled flag to a sensible state
00405     PathFilled = TRUE;
00406 
00407     // Don't save attributes as default.
00408     SaveAttributes = FALSE;
00409 
00410     m_pSoleLayer = NULL;
00411 }
00412 
00413 /********************************************************************************************
00414 
00415 >   Filter::~Filter()
00416 
00417     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00418     Created:    22/02/94
00419     Purpose:    Destroys the OILFilter object and the current attribute array/values
00420                 associated with this Filter.
00421     SeeAlso:    Filter; OILFilter
00422 
00423 ********************************************************************************************/
00424 
00425 Filter::~Filter()
00426 {
00427     // Destroy the associated OILFilter object
00428     delete pOILFilter;
00429 
00430     // Destory any temporary saved fill attribute
00431     if (FillAttr.Temp)
00432         delete FillAttr.pAttr;
00433 }
00434 
00435 
00436 /********************************************************************************************
00437 
00438 >   virtual BOOL Filter::DeclareFilterPreferenceSection()
00439 
00440     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00441     Created:    30/10/96
00442     Returns:    TRUE if the preference section was declared correctly
00443                 FALSE otherwise
00444     Purpose:    Ensures all filter related preferences go to the same section
00445 
00446 ********************************************************************************************/
00447 BOOL Filter::DeclareFilterPreferenceSection()
00448 {
00449     return( Camelot.DeclareSection( _T("Filters"), 10 ) );
00450 }
00451 
00452 
00453 /********************************************************************************************
00454 
00455 >   virtual BOOL Filter::CanIncludePreviewBmp()
00456 
00457     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00458     Created:    2/2/95
00459     Returns:    TRUE if the filter is capable of having a preview bitmap put in it somehow.
00460                 FALSE if it can't. Most filters can not do this.
00461     Purpose:    Allows you to find out if a particular filter can produce a Preview Bitmap
00462                 in it.
00463 
00464 ********************************************************************************************/
00465 
00466 BOOL Filter::CanIncludePreviewBmp()
00467 {
00468     // Say no. Filters that can will have to say yes
00469     return FALSE;
00470 }
00471 
00472 
00473 /********************************************************************************************
00474 
00475 >   void Filter::IncludePreviewBmp(BOOL WantBmp)
00476 
00477     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00478     Created:    2/2/95
00479     Inputs:     WantBmp - TRUE if you want the filter to Include a Preview Bitmap.
00480                           FALSE if not.
00481     Purpose:    Asks the filter to include a Preview bitmap or not. NOTE: This only has
00482                 any effect if the Filter answered TRUE to a call to CanIncludePreviewBmp.
00483                 NOTE2: All the filters hang around even if they are not doing any filtering,
00484                 so if you set this flag one way it will stay like that for all future uses of
00485                 the filter until it is set again. The best method will be to swtich it on if
00486                 required, do the import and then switch it off again immediatly afterwards.
00487     SeeAlso:    Filter::CanIncludePreviewBmp
00488 
00489 ********************************************************************************************/
00490 
00491 void Filter::IncludePreviewBmp(BOOL WantBmp)
00492 {
00493     // Set the internal Flag
00494     WantPreviewBmp = WantBmp;
00495 }
00496 
00497 
00498 
00499 /********************************************************************************************
00500 
00501 >   BOOL Filter::SetUpCurrentAttrs()
00502 
00503     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00504     Created:    13/04/94
00505     Returns:    TRUE if attributes set up ok; 
00506                 FALSE otherwise.
00507     Purpose:    Obtains an attribute array from the attribute manager.  This array is the
00508                 set of default attributes - the filter should use them to maintain its
00509                 set of current attributes while importing.  It then asks the attribute
00510                 manager to add the correct attributes to each node based on this array.
00511                 This should be called when importing, not when intialising, otherwise
00512                 all filters will have this array hanging around all the time, which is bad.
00513     Errors:     Out of memory.
00514     SeeAlso:    AttributeManager; AttributeManager::ApplyBasedOnDefaults
00515 
00516 ********************************************************************************************/
00517 
00518 BOOL Filter::SetUpCurrentAttrs()
00519 {
00520     // Sanity check
00521     ENSURE(CurrentAttrs == NULL, "Filter::SetUpCurrentAttrs called unnecessarily!");
00522 
00523     // Get the array of default attributes to use as our current attributes.
00524     CurrentAttrs = AttributeManager::GetDefaultAttributes();
00525     if (CurrentAttrs == NULL)
00526         return FALSE;
00527 
00528     // Clear the 'ignore' flag on all attributes.
00529     INT32 NumAttrs = AttributeManager::GetNumAttributes();
00530     for (INT32 i = 0; i < NumAttrs; i++)
00531         CurrentAttrs[i].Ignore = FALSE;
00532 
00533     // All done
00534     return TRUE;
00535 }
00536 
00537 /********************************************************************************************
00538 
00539 >   void Filter::DeleteCurrentAttrs()
00540 
00541     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00542     Created:    13/04/94
00543     Purpose:    Deallocates any objects used to hold the current attributes for the filter.
00544                 Should be called after import has finished, so the attribute table isn't 
00545                 hanging around all the time.
00546     SeeAlso:    Filter::SetUpCurrentAttrs
00547 
00548 ********************************************************************************************/
00549 
00550 void Filter::DeleteCurrentAttrs()
00551 {
00552     // Delete any attribute values we created
00553     if (CurrentAttrs != NULL)
00554     {
00555         DeleteAttributeList(CurrentAttrs);
00556         // Lose the attribute value array
00557         CCFree(CurrentAttrs);
00558         CurrentAttrs = NULL;
00559     }
00560 }
00561 
00562 /********************************************************************************************
00563 
00564     void Filter::DeleteAttributeList(AttributeEntry* pAttrList)
00565 
00566     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00567     Created:    16/10/95
00568     Inputs:     pAttrList   = A pointer to the first item in the attribute list
00569     Returns:    -
00570     Purpose:    This function removes all temp attributes from the attribute list provided
00571                 All temp attributes will have their list entries updated with NULL pointers.
00572 
00573 *********************************************************************************************/
00574 
00575 void Filter::DeleteAttributeList(AttributeEntry* pAttrList)
00576 {
00577     // Delete any attribute values we created
00578     INT32 NumAttrs = AttributeManager::GetNumAttributes();
00579     for (INT32 i=0; i<NumAttrs; i++)
00580     {
00581         // Delete the object if it is temporary.
00582         if (pAttrList[i].Temp)
00583         {
00584             delete pAttrList[i].pAttr;
00585             pAttrList[i].pAttr = NULL;
00586             pAttrList[i].Temp = FALSE;
00587         }
00588     }
00589 }
00590 
00591 
00592 
00593 /********************************************************************************************
00594 
00595 >   BOOL Filter::SnapShotCurrentAttrs()
00596 
00597     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00598     Created:    16/10/95
00599     Inputs:     -
00600     Returns:    TRUE if the currentattrs list has been copied
00601                 FALSE if nothing has been copied
00602     Purpose:    This function grabs a snap shot of the filter managers current attributes.
00603                 It simply makes a new List identical to that of CurrentAttrs.
00604 
00605 *********************************************************************************************/
00606 
00607 BOOL Filter::SnapShotCurrentAttrs()
00608 {
00609     return FilterSnapShot.CreateSnapShot(CurrentAttrs);
00610 }
00611 
00612 /********************************************************************************************
00613 
00614 >   void Filter::DeleteSnapShot()
00615 
00616     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00617     Created:    16/10/95
00618     Inputs:     -
00619     Returns:    -
00620     Purpose:    This function removes the snap shot list allocated during SnapShotCurrentAttrs().
00621                 It should be called to match any successfull return of its sister function.
00622                 ie SnapShotCurrentAttrs() and DeleteSnapShot() should be paired.
00623                 Note, the calls are not recursive. ie a
00624                 SnapShot
00625                 SnapShot
00626                 Delete
00627                 Delete
00628                 is not currently supported
00629     SeeAlso:    SnapShotCurrentAttrs()
00630 
00631 *********************************************************************************************/
00632 
00633 void Filter::DeleteSnapShot()
00634 {
00635     FilterSnapShot.DestroySnapShot();
00636 }
00637 
00638 
00639 /********************************************************************************************
00640 
00641 >   BOOL Filter::ApplyChangedAttrs(Node* pNode)
00642 
00643     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00644     Created:    16/10/95
00645     Inputs:     -
00646     Returns:    TRUE if the changed attributes have been applied to pNode
00647                 FALSE if nothing has been applied
00648     Purpose:    This function uses the snapshot facility to work out which of the
00649                 current attributes have changed. Obviously it expects a snap shot to have
00650                 been taken some time earlier. Only those attributes that have changes will be
00651                 applied to the node described on entry. Note, any changed attributes which
00652                 now match defaults will not be applied as the function calls
00653                 ApplyBasedOnDefaults() with the changes list.
00654 
00655 *********************************************************************************************/
00656 
00657 BOOL Filter::ApplyChangedAttrs(Node* pNode)
00658 {
00659     return FilterSnapShot.ApplyChangedAttrs(pNode,CurrentAttrs);
00660 }
00661 
00662 
00663 
00664 /********************************************************************************************
00665 
00666 >   void Filter::PushCurrentAttrsBasedOnSnapShot()
00667 
00668     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00669     Created:    16/10/95
00670     Inputs:     -
00671     Returns:    -
00672     Purpose:    This function uses the snap shot facility. It checks the snap shot list
00673                 against the current attribute list to find attributes which differ. Those
00674                 that do are obviously new attributes. ie attributes which have been parsed
00675                 by the filter after the snap shot was taken. This function takes the current
00676                 attrubute list and removes all those attributes which have changed in this
00677                 way. It resets them to their default none temp attribute types.
00678 
00679 *********************************************************************************************/
00680 
00681 void Filter::PushCurrentAttrsBasedOnSnapShot()
00682 {
00683     FilterSnapShot.PushAttrsBasedOnSnapShot(CurrentAttrs);
00684 }
00685 
00686 
00687 /********************************************************************************************
00688 
00689 >   void Filter::PopCurrentAttrsBasedOnSnapShot()
00690 
00691     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00692     Created:    16/10/95
00693     Inputs:     -
00694     Returns:    -
00695     Purpose:    This function uses the snap shot facility. It checks the snap shot list
00696                 against the current attribute list to find attributes which differ. Those
00697                 that do are obviously new attributes. ie attributes which have been parsed
00698                 by the filter after the snap shot was taken. This function takes the current
00699                 attrubute list and removes all those attributes which have changed in this
00700                 way. It resets them to their default none temp attribute types.
00701 
00702 *********************************************************************************************/
00703 
00704 void Filter::PopCurrentAttrsBasedOnSnapShot()
00705 {
00706     FilterSnapShot.PopAttrsBasedOnSnapShot(CurrentAttrs);
00707 }
00708     
00709 
00710 
00711 
00712 
00713 
00714 #define ADD_FILTER(Classname) \
00715     /* Create, initialise and install the Generic import filter */                  \
00716     pFilter = new Classname;                                                        \
00717     if (pFilter == NULL) return FALSE;                                              \
00718                                                                                     \
00719     if (!pFilter->Init())                                                           \
00720     {                                                                               \
00721         /* Error occured - report it and stop trying to initialise filters. */      \
00722         InformError();                                                              \
00723         return TRUE;                                                                \
00724     }                                                                               \
00725                                                                                     \
00726     FilterList.AddTail(pFilter);
00727 
00728 /********************************************************************************************
00729 
00730 >   BOOL Filter::InitFilters()
00731 
00732     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00733     Created:    22/02/94
00734     Returns:    TRUE if initialised ok, FALSE if not.
00735     Purpose:    Scans all filters to find out which filters are available for use, and
00736                 instantiates one of each, and holds them in a list.
00737     Errors:     Out of memory (if a filter fails to initialise for other reasons then an 
00738                 error is reported, but Camelot will still start up ok, i.e. TRUE is 
00739                 returned).
00740     SeeAlso:    Filter
00741 
00742 ********************************************************************************************/
00743 
00744 BOOL Filter::InitFilters()
00745 {
00746     // Find the filters - the kernel ones are hard-wired.
00747     Filter*     pFilter;
00748 
00749     // Create, initialise and install the Generic import filter
00750     ADD_FILTER(GenericFilter)
00751 
00752     // Keep a pointer to this one, for handling drag'n'drop
00753     pGenericFilter = (GenericFilter *) pFilter;
00754 
00755     // Create, initialise and install the generic vector and bitmap filters
00756     ADD_FILTER(VectorFilterFamily)
00757     ADD_FILTER(BitmapFilterFamily)
00758 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX)
00759 #if BUILD_TEXT_FILTERS
00760     ADD_FILTER(TextFilterFamily)
00761 #endif
00762 #endif
00763     // Create, initialise and install the Generic EPS import filter
00764 #ifndef STANDALONE
00765     ADD_FILTER(GenericEPSFilter)
00766 #endif
00767 
00768 #ifndef EXCLUDE_FROM_XARALX
00769 // Remove this next line to add the CDR / CMX filters...
00770 #ifndef NOCDRCMX
00771     ADD_FILTER(PaletteFilterFamily)
00772 #endif
00773 #endif
00774 
00775     // Create, initialise and install the other supported filters:
00776     // This must be the first filter that uses .xar or "Save as" wont work
00777     ADD_FILTER(CamelotNativeFilter)     // The new designed native filter, used for v2
00778 PORTNOTETRACE("filter","Removed CamelotWebFilter usage");
00779 #ifndef EXCLUDE_FROM_XARALX
00780     ADD_FILTER(CamelotWebFilter)        // The minimalistic form of the v2 native filter
00781 #endif
00782     ADD_FILTER(CamelotEPSFilter)
00783     ADD_FILTER(CamelotNativeEPSFilter)  // The old style EPS native filter, used in v1.1
00784     // Winoil filters are initialised here to prevent the drop-down list from being
00785     // mis-ordered.
00786 
00787     // Graeme (25-9-00) - Primary filters, in the order that Mark requested.
00788     ADD_FILTER(JPEGExportFilter)
00789     ADD_FILTER(JPEGImportFilter)
00790 
00791     ADD_FILTER(PNGFilter)
00792 
00793     if (ImageMagickFilter::CheckPath())
00794     {
00795         // Most of these commented out whilst we have no useful interface for
00796         // filter selection
00797         ADD_FILTER(ImageMagickFilterBMP)
00798         //ADD_FILTER(ImageMagickFilterCUR)
00799         //ADD_FILTER(ImageMagickFilterCUT)
00800         //ADD_FILTER(ImageMagickFilterDCM)
00801         //ADD_FILTER(ImageMagickFilterDCX)
00802         //ADD_FILTER(ImageMagickFilterDIB)
00803         //ADD_FILTER(ImageMagickFilterDNG)
00804         //ADD_FILTER(ImageMagickFilterEPDF)
00805         //ADD_FILTER(ImageMagickFilterEPI)
00806         //ADD_FILTER(ImageMagickFilterEPS)
00807         //ADD_FILTER(ImageMagickFilterEPS2)
00808         //ADD_FILTER(ImageMagickFilterEPS3)
00809         //ADD_FILTER(ImageMagickFilterEPSF)
00810         //ADD_FILTER(ImageMagickFilterEPSI)
00811         //ADD_FILTER(ImageMagickFilterEPT)
00812         //ADD_FILTER(ImageMagickFilterFAX)
00813         //ADD_FILTER(ImageMagickFilterFITS)
00814         ADD_FILTER(ImageMagickFilterICO)
00815         //ADD_FILTER(ImageMagickFilterJNG)
00816         //ADD_FILTER(ImageMagickFilterMIFF)
00817         //ADD_FILTER(ImageMagickFilterMPC)
00818         //ADD_FILTER(ImageMagickFilterOTB)
00819         //ADD_FILTER(ImageMagickFilterP7)
00820         //ADD_FILTER(ImageMagickFilterPALM)
00821         //ADD_FILTER(ImageMagickFilterPAM)
00822         //ADD_FILTER(ImageMagickFilterPBM)
00823         ADD_FILTER(ImageMagickFilterPCD)
00824         //ADD_FILTER(ImageMagickFilterPCDS)
00825         //ADD_FILTER(ImageMagickFilterPCL)
00826         //ADD_FILTER(ImageMagickFilterPCX)
00827         //ADD_FILTER(ImageMagickFilterPDB)
00828         ADD_FILTER(ImageMagickFilterPDF)
00829         //ADD_FILTER(ImageMagickFilterPGM)
00830         ADD_FILTER(ImageMagickFilterPICT)
00831         //ADD_FILTER(ImageMagickFilterPIX)
00832         ADD_FILTER(ImageMagickFilterPNM)
00833         ADD_FILTER(ImageMagickFilterPPM)
00834         //ADD_FILTER(ImageMagickFilterPS)
00835         //ADD_FILTER(ImageMagickFilterPS2)
00836         //ADD_FILTER(ImageMagickFilterPS3)
00837         ADD_FILTER(ImageMagickFilterPSD)
00838         //ADD_FILTER(ImageMagickFilterPTIF)
00839         //ADD_FILTER(ImageMagickFilterPWP)
00840         //ADD_FILTER(ImageMagickFilterRLA)
00841         //ADD_FILTER(ImageMagickFilterRLE)
00842         //ADD_FILTER(ImageMagickFilterSCT)
00843         //ADD_FILTER(ImageMagickFilterSFW)
00844         //ADD_FILTER(ImageMagickFilterSUN)
00845         // // ADD_FILTER(ImageMagickFilterSVG) - removed per NeilH 19/07/2006 so it doesn't clash with vector SVG import
00846         //ADD_FILTER(ImageMagickFilterTGA)
00847         ADD_FILTER(ImageMagickFilterTIFF)
00848         //ADD_FILTER(ImageMagickFilterTIM)
00849         //ADD_FILTER(ImageMagickFilterTTF)
00850         //ADD_FILTER(ImageMagickFilterVICAR)
00851         //ADD_FILTER(ImageMagickFilterVIFF)
00852         //ADD_FILTER(ImageMagickFilterWBMP)
00853         //ADD_FILTER(ImageMagickFilterWPG)
00854         //ADD_FILTER(ImageMagickFilterXBM)
00855         //ADD_FILTER(ImageMagickFilterXCF)
00856         ADD_FILTER(ImageMagickFilterXPM)
00857         //ADD_FILTER(ImageMagickFilterXWD)
00858     }
00859 
00860     ADD_FILTER(TI_GIFFilter)
00861 PORTNOTETRACE("filter","Removed TIFFFilter");
00862 #ifndef EXCLUDE_FROM_XARALX
00863     ADD_FILTER(TIFFFilter)                  
00864 #endif
00865 
00866 #if !defined(EXCLUDE_FROM_XARALX) && !defined(PROD_XS)
00867     // disabled for XS builds
00868     OILFilter::InitPluginFilters(FilterList);
00869 #endif
00870 
00871 PORTNOTE("filter","Removed Flash filter for 0.7")
00872 #if defined(_DEBUG)
00873     ADD_FILTER(FlashFilter)
00874 #endif
00875 
00876 #ifndef STANDALONE
00877     // Other filters in alphabetical order.
00878 PORTNOTE("filter","Removed filters usage")
00879 #ifndef EXCLUDE_FROM_XARALX
00880     ADD_FILTER(AcornDrawFilter)
00881 #endif
00882     // Adobe AI / EPS filters.
00883     ADD_FILTER(AIEPSFilter)
00884     ADD_FILTER(AI5EPSFilter)
00885     ADD_FILTER(AI8EPSFilter)
00886 
00887     ADD_FILTER(PhotoShopEPSFilter)
00888 
00889     ADD_FILTER(ArtWorksEPSFilter)
00890 PORTNOTE("filter","Removed filters usage")
00891 #ifndef EXCLUDE_FROM_XARALX
00892 
00893 //  ADD_FILTER(BMPFilter)
00894 
00895     // These filters are not shown in the drop-down menu.
00896 //  ADD_FILTER(AdobeColourSwatchFilter)
00897 //  ADD_FILTER(AdobeColourTableFilter)
00898 //  ADD_FILTER(JCWColourFilter)
00899 
00900 // Remove this next line to add the CDR / CMX filters...
00901 #ifndef NOCDRCMX
00902 
00903     // Corel native filters. (CMX and CDR.)
00904     ADD_FILTER(CDRFilter)
00905     ADD_FILTER(CMXImportFilter)
00906 PORTNOTE("filter","Removed CMXFilterX usage")
00907     ADD_FILTER(CMXFilter16)
00908     ADD_FILTER(CMXFilter32) 
00909 
00910 #endif //NOCDRCMX
00911 
00912 
00913     // Corel EPS filters.
00914 PORTNOTE("filter","Removed Corel EPS filters usage")
00915     ADD_FILTER(Corel3EPSFilter)
00916     ADD_FILTER(Corel4EPSFilter)
00917 
00918     ADD_FILTER(CorelPaletteFilter)
00919 #endif
00920     ADD_FILTER(FreeHandEPSFilter)
00921 
00922 PORTNOTE("filter","Removed filters usage")
00923 #ifndef EXCLUDE_FROM_XARALX
00924     // HTML based filters.
00925 PORTNOTE("filter","Removed HTMLFilter usage")
00926     ADD_FILTER(HTMLFilter)  // the HTML filter
00927     ADD_FILTER(ImagemapFilter)
00928 #endif //EXCLUDE_FROM_XARALX
00929 
00930 
00931 #if BUILD_OTHER_TEXT_FILTERS
00932 
00933     // The text filters don't appear in the drop-down menu.
00934     ADD_FILTER(ANSITextFilter)
00935     ADD_FILTER(UnicodeTextFilter)
00936     ADD_FILTER(RTFTextFilter)
00937 
00938 #endif
00939 
00940 #endif
00941 
00942 #ifdef _DEBUG
00943     ADD_FILTER(FlareTemplateFilter)     // The text version
00944 #endif
00945 
00946     // Initialise the OIL filters (but they are still objects of class "Filter")
00947     // This can include filters specific to one platform.
00948     OILFilter::InitFilters(FilterList);
00949 
00950 #if !defined(EXCLUDE_FROM_RALPH)
00951     // Register our preference for minimum line widths, and whether or not we import
00952     // unnamed colours into the document colour list.
00953     Camelot.DeclareSection(_T("Filters"), 10); 
00954     Camelot.DeclarePref(_T("Filters"), _T("MinLineWidth"),      &MinLineWidth, 0, 10000); 
00955     Camelot.DeclarePref(_T("Filters"), _T("ImportWithLayers"),  &ImportWithLayers); 
00956     Camelot.DeclarePref(_T("Filters"), _T("OpenWithLayers"),    &OpenWithLayers); 
00957     Camelot.DeclarePref(_T("Filters"), _T("ImportBitmapsOntoLayers"),   &ImportBitmapsOntoLayers); 
00958     Camelot.DeclarePref(_T("Filters"), _T("DontWarnBitmapNonMixTransp"),    &bDontWarnBitmapNonMixTransp); 
00959     Camelot.DeclarePref(_T("Filters"), _T("AddUnnamedColours"), &AddUnnamedColours); 
00960 
00961 #endif
00962     XSEPSExportOptions::Init();
00963     BaseBitmapFilter::InitBaseClass();
00964     // All ok
00965     return TRUE;
00966 }
00967 
00968 
00969 /********************************************************************************************
00970 
00971 >   FilterID FilterManager::GetNewFilterID()
00972 
00973     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00974     Created:    10/12/96
00975     Returns:    A FilterID unique to this FilterManager for each call to the function
00976     Purpose:    Support function providing an unique ID for each newly registered Filter
00977 
00978 ********************************************************************************************/
00979 ID Filter::GetNewFilterID()
00980 {
00981     ERROR3IF(!m_NextFilterID, "Creating duff FilterID");
00982 
00983     return m_NextFilterID++;
00984 }
00985 
00986 
00987 /********************************************************************************************
00988 
00989 >   FilterID FilterManager::RegisterFilter( const Filter* const pFilter, 
00990                                             const DESTRUCTION_METHOD DestructMethod)
00991 
00992     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00993     Created:    15/12/94
00994     Inputs:     pFilter:    pointer to the filter to register
00995                 DestructMethod :    whether or not the given filter should be destructed when
00996                                     the collection of registered filters is destructed.
00997 
00998     Returns:    FilterID that uniquely identifies the given filter within the scope of this
00999                 FilterManager and allows for fast retrieval of the filter.
01000     Purpose:    Permits the filter to be used by the FilterManager.
01001                 For an import filter to be present on the Import dialog the filter should
01002                 associate itself with the requisite FileFormats via AssociateFilterWithFormat()
01003 
01004 ********************************************************************************************/
01005 ID Filter::RegisterFilter(  Filter* const pFilter)
01006 {
01007     ERROR2IF(pFilter == NULL, 0, "NULL Args");
01008 
01009     ID newID = GetNewFilterID();
01010     GetFilters().AddTail(pFilter);
01011 
01012     return newID;
01013 }
01014 
01015 
01016 
01017 /********************************************************************************************
01018 
01019 >   void Filter::DeinitFilters()
01020 
01021     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01022     Created:    22/02/94
01023     Purpose:    Destroy all the Filter objects.
01024     SeeAlso:    Filter
01025 
01026 ********************************************************************************************/
01027 
01028 BOOL Filter::DeinitFilters()
01029 {
01030     ListItem* pListItem = FilterList.GetHead();
01031     while (pListItem != NULL)
01032     {
01033         ((Filter*)pListItem)->Deinit();
01034 
01035         pListItem = FilterList.GetNext(pListItem);
01036     }
01037 
01038     // Get rid of our filters
01039     FilterList.DeleteAll();
01040 
01041     // All ok
01042     return TRUE;
01043 }
01044 
01045 
01046 /********************************************************************************************
01047 
01048 >   BOOL Filter::JoinFamily(CCRuntimeClass *pRuntimeClass)
01049 
01050     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01051     Created:    26/07/94
01052     Inputs:     pRuntimeClass - the type of filters in this family.
01053     Returns:    TRUE if the filter can be added to the family;
01054                 FALSE if not.
01055     Purpose:    Allow a filter to choose whether or not it wants to become part of a
01056                 filter 'family', e.g. a filter family such as "EPS files", or
01057                 "Bitmap files".
01058                 The default implementation checks to see if the filter is of the same
01059                 kind of filter, using IsKindOf(), and if so, it consents to be in the
01060                 filter family.  Filters should only over-ride this if they need
01061                 different behaviour for some bizarre reason.
01062 
01063 ********************************************************************************************/
01064 
01065 BOOL Filter::JoinFamily(CCRuntimeClass *pRuntimeClass)
01066 {
01067     return IsKindOf(pRuntimeClass);
01068 }
01069 
01070 /********************************************************************************************
01071 
01072 >   Filter *Filter::GetFirst()
01073 
01074     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01075     Created:    22/02/94
01076     Returns:    Pointer to the first filter, or NULL if none.
01077     Purpose:    Iterating through the list of filters known to Camelot.  This function
01078                 returns the first filter.
01079     SeeAlso:    Filter::GetNext()
01080     Scope:      Static
01081 
01082 ********************************************************************************************/
01083 
01084 Filter *Filter::GetFirst()
01085 {
01086     return (Filter *) FilterList.GetHead();
01087 }
01088 
01089 /********************************************************************************************
01090 
01091 >   Filter *Filter::GetNext(Filter *pFilter)
01092 
01093     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01094     Created:    22/02/94
01095     Inputs:     pFilter - pointer to the filter to be used to get the following filter.
01096     Returns:    Pointer to the next filter, or NULL if none.
01097     Purpose:    Iterating through the list of filters known to Camelot.  This function
01098                 returns the next filter.
01099     SeeAlso:    Filter::GetFirst
01100 
01101 ********************************************************************************************/
01102 
01103 Filter *Filter::GetNext(Filter *pFilter)
01104 {
01105     return (Filter *) FilterList.GetNext(pFilter);
01106 }
01107 
01108 /********************************************************************************************
01109 
01110 >   FilterFlags Filter::GetFlags()
01111 
01112     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01113     Created:    22/02/94
01114     Returns:    The FilterFlags structure
01115     Purpose:    Get the flags for a specified filter.
01116     SeeAlso:    FilterFlags
01117 
01118 ********************************************************************************************/
01119 
01120 FilterFlags Filter::GetFlags()
01121 {
01122     return Flags;
01123 }
01124 
01125 /********************************************************************************************
01126 
01127 >   virtual BOOL Filter::IsDefaultDocRequired(const TCHAR* pcszPathName)
01128 
01129     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01130     Created:    9/10/95
01131     Inputs:     pcszPathName    pointer to the pathname to check
01132     Returns:    TRUE if the filter requires a default document, FALSE if not.
01133     Purpose:    Works out if opening a file of this type requires a default document to be
01134                 loaded. If the file format supplies the document then return FALSE otherwise
01135                 return TRUE. An example would be opening a bitmap file. This has no document
01136                 defined in the file format and so we need to laod the default document before
01137                 importing the bitmap into this file.
01138                 In this baseclass version return FALSE and hence assume that the filters that
01139                 need to will override this function to return TRUE.
01140     SeeAlso:    Filter; Filter::IsDefaultDocRequired; CCamDoc::OnOpenDocument;
01141     SeeAlso:    FilterFamily::DoImport; Filter::DoImport;
01142 
01143 ********************************************************************************************/
01144 
01145 BOOL Filter::IsDefaultDocRequired(const TCHAR* pcszPathName)
01146 {
01147     // No need to check the pathname, just return FALSE as most filters will not require the
01148     // default document.
01149     return FALSE;
01150 }   
01151 
01152 /********************************************************************************************
01153 
01154 >   BOOL Filter::PreHowCompatible()
01155 
01156     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01157     Created:    28/11/94
01158     Returns:    True if it it worked ok.
01159     Purpose:    Allows a filter or set of filters to take some action or set up variables
01160                 before being called by HowCompatible. A group of filters which share common
01161                 code may require some variable set up before being asked to check the type.  
01162                 Base class does nothing and so works for all filters which do not require it.
01163     SeeAlso:    HowCompatible
01164 
01165 ********************************************************************************************/
01166 
01167 BOOL Filter::PreHowCompatible()
01168 {
01169     return TRUE;
01170 }
01171 
01172 /********************************************************************************************
01173 
01174 >   INT32 Filter::HowCompatible(PathName& Filename, ADDR HeaderStart, UINT32 HeaderSize, 
01175                               INT32 FileSize)
01176 
01177     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01178     Created:    31/08/94
01179     Inputs:     Filename - name of the file.
01180                 HeaderStart - Address of the first few bytes of the file.
01181                 HeaderSize - the number of bytes in the header pointed to by FileStart.
01182                 FileSize - the size of the whole file, in bytes.
01183     Returns:     0 => Not compatible with this filter - the filter will NOT be asked to
01184                       load such a file.
01185                 10 => Filter thinks that it is 100% compatible with this file.
01186                 Or any number in between depending on how much the filter likes the file.
01187     Purpose:    Determine if this filter can load the specified file.
01188                 The filter is provided with the first n bytes of the file, where n is
01189                 HeaderSize. It should look at this data and/or the pathname to determine
01190                 if it can load this file.
01191                 NB. Base class function is pure virtual - override it!
01192 
01193 ********************************************************************************************/
01194 
01195 /********************************************************************************************
01196 
01197 >   ADDR Filter::LoadInitialSegment(CCLexFile* pFile, UINT32* pSize, INT32* pFileSize)
01198 
01199     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01200     Created:    28/03/94
01201     Inputs:     pFile - the file to load from.
01202                 Size - the number of bytes to load from the file.
01203     Outputs:    Size - the number of bytes actually loaded (not actually implemented yet;
01204                         waiting for the CCFile class to be updated).
01205     Returns:    Address the the loaded block
01206     Purpose:    Loads in the first n bytes of a file, in order to investigate whether a
01207                 filter (or number of filters in the case of the FilterFamily class), is
01208                 compatible with the file - i.e. how well this file recognises the file
01209                 header.
01210                 The last byte in the block is set to 0, to prevent ASCII lexers from going
01211                 trundling off the end.
01212     Errors:     Unable to open file; Out of memory
01213     SeeAlso:    Filter::HowCompatible; Filter::PreHowCompatible
01214 
01215 ********************************************************************************************/
01216 
01217 ADDR Filter::LoadInitialSegment(CCLexFile* pFile, UINT32* pSize, size_t *pFileSize)
01218 {
01219     ERROR3IF(pFile == NULL, "Null CCLexFile* in Filter::LoadInitialSegment");
01220 
01221     BOOL ThrowState = pFile->SetThrowExceptions(TRUE);
01222     BOOL ErrorState = pFile->SetReportErrors(FALSE);
01223     
01224     // Tell caller how big the file is in bytes
01225     *pFileSize = pFile->Size();
01226 
01227     // Now that we know the file size, check to see if it has a chance of being loaded.
01228     // 4 is a nice small size that would fail the tests below.
01229     if (*pFileSize < 4)
01230     {
01231         // Could set a new special 'I don't think this file has any useful info in'. 
01232         TRACEUSER( "Neville", _T("LoadInitialSegment(): Very small file found\n"));
01233         ERROR1(NULL, _R(IDE_FILETOOSMALL));
01234     }
01235 
01236     // Check if the file size is less than the required initial segement size.
01237     // If so set the size to be the file size.
01238     // Casting UINT32 to INT32 should be ok as we know we are between 4 and the specified size.
01239     if ((UINT32) *pFileSize < *pSize)
01240         *pSize = (UINT32) *pFileSize;
01241 
01242     ADDR FilterBuf = (ADDR) CCMalloc(*pSize);
01243     if (FilterBuf == NULL)
01244         return NULL;
01245 
01246     // Save the current read pointer.
01247     FilePos nOldPos = pFile->tellIn();
01248 
01249     try
01250     {
01251         // A flag see if things are working
01252         BOOL IsResultOK = TRUE;
01253 
01254         
01255         // First we will check to see if it starts with the fabby binary EPS marker
01256         char Buf[4];
01257         pFile->SetDontFail(TRUE);
01258         pFile->read(Buf, 4);
01259         pFile->SetDontFail(FALSE);
01260 
01261         if( Progress::IsRalphAbort() )
01262             return NULL; 
01263     
01264         if ((Buf[0]=='\xC5') && (Buf[1]=='\xD0') && (Buf[2]=='\xD3') && (Buf[3]=='\xC6'))
01265         {
01266             // Yes, this is a binary EPS file that has a TIFF attached, so find the EPS
01267             FilePos StartOfEPS = 0;
01268 
01269             pFile->SetDontFail(TRUE);
01270             pFile->read(&StartOfEPS, 4);
01271             StartOfEPS = LEtoNative(StartOfEPS);
01272             pFile->SetDontFail(FALSE);
01273             if(Progress::IsRalphAbort())
01274                 return NULL; 
01275 
01276             TRACEUSER( "Rik", _T("EPS Starts at %ld\n"), StartOfEPS);
01277 
01278             // see if the result makes sense
01279             if (StartOfEPS==0)
01280             {
01281                 // Must be rubbish
01282                 TRACEUSER( "Rik", _T("This file claims to start at 0 - Its rubbish\n"));
01283                 IsResultOK = FALSE;
01284             }
01285         
01286             // Seek to the start of the EPS ready for the importer to read it.
01287             pFile->seekIn(StartOfEPS, ios::beg);
01288 
01289             // If the end of the file comes before the 1k we require then we must only read
01290             // the remaining file size otherwise the read below will error.
01291             if ((UINT32)(*pFileSize - StartOfEPS) < *pSize)
01292             {
01293                 *pSize = (UINT32) (*pFileSize - StartOfEPS);
01294                 TRACEUSER( "Neville", _T("Reduced initial segement size to %d\n"), *pSize);
01295             }
01296         }
01297         else
01298         {
01299             // This was not a binary EPS file, so go back to the start of the file
01300             pFile->seekIn(nOldPos, ios::beg);
01301         }
01302 
01303         // BODGE: Size should be updated to the number of bytes actually read.
01304         pFile->SetDontFail(TRUE);
01305         if (IsResultOK) pFile->read(FilterBuf, *pSize);
01306         pFile->SetDontFail(FALSE);
01307 
01308         if( Progress::IsRalphAbort() )
01309             return NULL; 
01310 
01311         // Don't need this file anymore - restote its original read pointer.
01312         pFile->seekIn(nOldPos, ios::beg);
01313 
01314         // Set back the old error informing and throwing states
01315         pFile->SetThrowExceptions(ThrowState);
01316         pFile->SetReportErrors(ErrorState);
01317 
01318         // If it worked
01319         if (IsResultOK)
01320         {
01321             // Zero the last byte of the buffer to make it simple for ASCII analysis.
01322             FilterBuf[(*pSize) - 1] = 0;
01323 
01324             // Return address of file data
01325             return FilterBuf;
01326         }
01327 
01328         // If we get here, there was a problem, so return null
01329         if (FilterBuf != NULL) CCFree(FilterBuf);
01330 
01331         // return
01332         ERROR1(NULL, _R(IDS_FILECORRUPT));
01333     }
01334     catch( CFileException )
01335     {
01336         // Restore the original read pointer.
01337         pFile->seekIn(nOldPos, ios::beg);
01338 
01339         // Set back the old error informing and throwing states
01340         pFile->SetThrowExceptions(ThrowState);
01341         pFile->SetReportErrors(ErrorState);
01342         
01343         // We had an error so the buffer is no good any more so remove it and
01344         // return NULL to the caller.
01345         if (FilterBuf != NULL) CCFree(FilterBuf);
01346         
01347         // We had a problem so return null
01348         return NULL;
01349     }
01350 
01351     // Should not get here
01352     return NULL;
01353 }
01354 
01355 
01356 ADDR Filter::LoadInitialSegment(PathName& Path, UINT32 *Size, size_t *FileSize)
01357 {
01358     CCDiskFile FilterFile;
01359     if (!FilterFile.open(Path, ios::in | ios::binary))
01360     {
01361         TRACEUSER( "Tim", _T("LoadInitialSegment(): Could not open file\n"));
01362         ERROR1(NULL, _R(IDT_IMPORT_NOTFOUND));
01363     }
01364 
01365     return LoadInitialSegment(&FilterFile, Size, FileSize);
01366 }
01367 
01368 
01369 
01370 
01371 /********************************************************************************************
01372 
01373 >   Layer *Filter::GetActiveLayer(Document *pDoc)
01374 
01375     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01376     Created:    28/03/94
01377     Inputs:     pDoc - the document to search.
01378     Returns:    Pointer to the layer found, or NULL if none,
01379     Purpose:    Find the active layer of the first spread of the specified document.
01380     SeeAlso:    Filter::GetFirstSpread
01381 
01382 ********************************************************************************************/
01383 
01384 Layer *Filter::GetActiveLayer(Document *pDoc)
01385 {
01386 PORTNOTE("spread", "Multi-spread warning!")
01387     Spread *pSpread = GetFirstSpread(pDoc);
01388     if (pSpread != NULL)
01389         return pSpread->FindActiveLayer();
01390 
01391     return NULL;
01392 }
01393 
01394 
01395 
01396 /********************************************************************************************
01397 
01398 >   BOOL Filter::MakeSureLayerExists(Document* pDoc)
01399 
01400     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
01401     Created:    4/4/95
01402     Inputs:     pDoc - the document that the inserting is happening in
01403     Returns:    TRUE if there is a layer
01404     Purpose:    This functions checks that there is a layer to put nodes onto during an
01405                 import, and will create a new layer if there are none. This means that
01406                 filters can call this function just before they try and insert a new node
01407                 into the tree and be sure that there will be a layer for it to go onto.
01408                 The function will return TRUE if there is a layer in the document (even
01409                 if this function had to create the layer). It will return FALSE only if
01410                 there are no layers and it was unable to create any new ones.
01411 
01412 ********************************************************************************************/
01413 
01414 BOOL Filter::MakeSureLayerExists(Document* pDoc)
01415 {
01416     // Find the spread that all the action is happening on
01417 PORTNOTE("spread", "Multi-spread warning!")
01418     Spread* pSpread = GetFirstSpread(pDoc);
01419     if (pSpread==NULL)
01420         return FALSE;
01421 
01422     // Try and find a layer in this spread
01423     Layer* pLayer = pSpread->FindFirstLayer();
01424     
01425     // If there were no layers, then we should try and make one
01426     if (pLayer==NULL)
01427     {
01428         // Time to build a new layer...
01429         Layer *pNewLayer = new Layer(pSpread, LASTCHILD, String_256(_R(IDS_K_FILTERS_LAYERNAME)));
01430         
01431         // If we failed, return FALSE to the caller
01432         if (pNewLayer==NULL)
01433             return FALSE;
01434 
01435         // Make Layer1 (top layer) the active layer
01436         pNewLayer->SetActive(TRUE);
01437 
01438         // Move the Insertion position onto the new layer
01439         pDoc->ResetInsertionPosition();
01440     }
01441 
01442     // all worked
01443     return TRUE;
01444 }
01445 
01446 
01447 
01448 /********************************************************************************************
01449 
01450 >   Spread *Filter::GetFirstSpread(Document *pDoc)
01451 
01452     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01453     Created:    28/03/94
01454     Inputs:     pDoc - the document to search.
01455     Returns:    Pointer to the spread found, or NULL if no spread was found.
01456     Purpose:    Find the first spread of the specified document.
01457     SeeAlso:    Filter::GetActiveLayer
01458 
01459 ********************************************************************************************/
01460 
01461 Spread *Filter::GetFirstSpread(Document *pDoc)
01462 {
01463     // Search for the first chapter node
01464     Node *pNode = pDoc->GetFirstNode()->FindNext()->FindFirstChild();
01465     while ((pNode != NULL) && (!pNode->IsKindOf(CC_RUNTIME_CLASS(Chapter))))
01466         pNode = pNode->FindNext();
01467         
01468     ENSURE(pNode->IsKindOf(CC_RUNTIME_CLASS(Chapter)), 
01469            "Filter::GetFirstSpread(): Could not find Chapter");
01470     Chapter *pChapter = (Chapter *) pNode;
01471     
01472     // pSpread is a child of pChapter
01473 PORTNOTE("spread", "Multi-spread warning!")
01474     Spread *pSpread = (Spread *) pChapter->FindFirstChild();
01475     ENSURE(pSpread->IsKindOf(CC_RUNTIME_CLASS(Spread)),
01476            "Filter::GetFirstSpread(): Could not find Spread");
01477 
01478     if (pSpread->IsKindOf(CC_RUNTIME_CLASS(Spread)))
01479         return pSpread;
01480     else
01481         return NULL;
01482 }
01483 
01484 
01485 /********************************************************************************************
01486 
01487 >   BOOL Filter::ImportBinary(ADDR pData, INT32 Length)
01488 
01489     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01490     Created:    23/08/94
01491     Inputs:     Length - the number of bytes to read.
01492     Outputs:    pData - the buffer to place the bytes in.
01493     Returns:    The number of bytes read, or -1 for an error.
01494                 (NB. Base class version always returns -1)
01495     Purpose:    Read in binary data from the file and place it in the buffer supplied by
01496                 the caller.  This is over-ridden by filters to do whatever translation is
01497                 necessary, e.g. EPS filters convert ASCII Hexadecimal data to binary.
01498 
01499                 NB. This base class version has no functionality - it always returns
01500                 FALSE without setting the error ID and ENSUREs in debug builds.
01501                 Don't use it!
01502 
01503     Errors:     End of file; Disk error
01504 
01505 ********************************************************************************************/
01506 
01507 INT32 Filter::ImportBinary(ADDR pData, INT32 Length)
01508 {
01509     ENSURE(FALSE, "Base class ImportBinary() function called!");
01510     return -1;
01511 }
01512 
01513 
01514 /********************************************************************************************
01515 
01516 >   virtual UINT32 Filter::GetImportMsgID()
01517 
01518     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01519     Created:    22/12/95
01520     Returns:    The id of the message to put on the progress display whilst importing.
01521     Purpose:    Used to get the message id to be used during export.
01522                 Virtual, so that multi-stage importers can change the message.
01523     SeeAlso:    DoImport;
01524 
01525 ********************************************************************************************/
01526 
01527 UINT32 Filter::GetImportMsgID()
01528 {
01529     return ImportMsgID;
01530 }
01531 
01532 /********************************************************************************************
01533 
01534 >   virtual UINT32 Filter::GetExportMsgID()
01535 
01536     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01537     Created:    18/09/95
01538     Returns:    The id of the message to put on the progress display whilst exporting.
01539     Purpose:    Used to get the message id to be used during export.
01540                 Virtual, so that two stage exporters can change the message.
01541     SeeAlso:    DoExport;
01542 
01543 ********************************************************************************************/
01544 
01545 UINT32 Filter::GetExportMsgID()
01546 {
01547     return (m_nForcedStatusExportMessage) ? m_nForcedStatusExportMessage : ExportMsgID;
01548 }
01549 
01550 
01551 
01552 /********************************************************************************************
01553 >   static void Filter::ForceStatusExportMessage(UINT32 nMessage)
01554 
01555     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01556     Created:    19/9/96
01557     Inputs:     nMessage        ----    the message to use instead of the usual when
01558                                         exporting a file.
01559     Purpose:    Overrides the status-line message shown when a file is exported.  This is
01560                 used by the clipboard code to change "Saving document..." to
01561                 "Copying to clipboard..."
01562     SeeAlso:    Filter::UnforceStatusExportMessage; ExternalClipboard::GetDataSource
01563 ********************************************************************************************/
01564 
01565 void Filter::ForceStatusExportMessage(UINT32 nMessage)
01566 {
01567     // Use this message please (if derived classes allow it).
01568     m_nForcedStatusExportMessage = nMessage;
01569 }
01570 
01571 
01572 
01573 /********************************************************************************************
01574 >   static void Filter::UnforceStatusExportMessage()
01575 
01576     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01577     Created:    19/9/96
01578     Purpose:    Resets the message override on export back to "no override".
01579     SeeAlso:    Filter::ForceStatusExportMessage; ExternalClipboard::GetDataSource
01580 ********************************************************************************************/
01581 
01582 void Filter::UnforceStatusExportMessage()
01583 {
01584     // Set this back to "no override".
01585     m_nForcedStatusExportMessage = 0;
01586 }
01587 
01588 
01589 
01590 /********************************************************************************************
01591 
01592 >   BOOL GetProgressString(CCLexFile* pTheFile, String_64 *pMessage, String_64* StrToAddToProgress=NULL)
01593 
01594     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01595     Created:    9/7/95
01596     Inputs:     pTheFile    file being used for importing
01597                 pMessage    pointer to the string to append extra bits to
01598                 StrToAddToProgress - A string to add to the progress string. This is used mainly by the 
01599                                     html import filter when importing bitmap to display "file 1 of n".
01600     Outputs:    -
01601     Returns:    True if worked ok, False otherwise.
01602     Purpose:    Works out what progress bar string to use during importing or exporting of
01603                 the file specified.
01604                 This consists of the passed in basic message plus, if it will fit, a truncated
01605                 form, if necessary, of the filename.
01606                 The file must be a diskfile so that it can access a filename, if not then
01607                 nothing will be added. If the pTheFile is null then nothing will be added. 
01608     SeeAlso:    Filter::GetImportProgressString;  Filter::GetExportProgressString;
01609 
01610 ********************************************************************************************/
01611 
01612 BOOL GetProgressString(CCLexFile* pTheFile, String_64 *pMessage, String_64* StrToAddToProgress=NULL)
01613 {
01614     // Get a shortened name for the file
01615     String_256 Filename;
01616     INT32 MaxSize = pMessage->MaxLength() - pMessage->Length(); 
01617     // Now take off the size of the " '" and "'" that will be added around it
01618     MaxSize -= 3;
01619     
01620     // CCFile::GetName will return what will fit into the string povided. What we
01621     // really want is just the filename, only present on disk files.
01622     if (pTheFile != NULL && pTheFile->IS_KIND_OF(CCDiskFile))
01623     {
01624         CCDiskFile *pTheDiskFile = (CCDiskFile *)pTheFile;
01625         // This will only work on CCDiskFiles
01626         PathName path = pTheDiskFile->GetPathName();
01627 
01628         // Use just the filename
01629         Filename = path.GetFileName();
01630 
01631         // If it is still too long, turn it into the form "...ffff.ext", i.e. have an
01632         // ellipsis followed by as much of the filename as we can fit into the string.
01633         // (We use the last segment of the filename, i.e. we throw away characters from
01634         // the beginning).
01635         INT32 FilenameLen = Filename.Length();
01636         if (MaxSize < FilenameLen)
01637         {
01638             // Shuffle pathname down to fit into buffer
01639             Filename.Remove(0, FilenameLen - MaxSize);
01640 
01641             // Put the ellipsis at the front
01642             TCHAR *Buf = (TCHAR *) Filename;
01643             Buf[0] = '.';
01644             Buf[1] = '.';
01645             Buf[2] = '.';
01646         }
01647 
01648         // Do an extra check to ensure that waht we are about to add in will fit
01649         if (Filename.Length() <= MaxSize)
01650         {
01651             // If we have a valid file name and it will fit into the progress string
01652             // then tag this onto the end of the progress string with single quotes.
01653 
01654             PCTSTR      res = camStrstr( (const TCHAR *)Filename, _T(".tmp") );
01655             
01656             if (res == NULL)
01657             {
01658                 *pMessage += String_32(_R(IDS_K_FILTERS_FILESTARTQUOTE));
01659                 *pMessage += Filename;  
01660                 *pMessage += String_32(_R(IDS_K_FILTERS_FILEENDQUOTE));
01661             }
01662 
01663             // add (for instance) "file 1 of 5"....
01664             if (StrToAddToProgress && !StrToAddToProgress->IsEmpty())
01665                 *pMessage += *StrToAddToProgress;
01666         }
01667     }
01668     
01669 //  if (pExportFile->GetName(&Filename) && (Filename.Length() < MaxSize))
01670 //  {
01671 //      // If we have a valid file name and it will fit into the progress string
01672 //      // then tag this onto the end of the progress string with single quotes.
01673 //      ProgressString += " '";
01674 //      ProgressString += Filename;
01675 //      ProgressString += "'";
01676 //  }
01677     
01678     return TRUE;
01679 }
01680 
01681 
01682 /********************************************************************************************
01683 
01684 >   virtual BOOL Filter::AddStringToProgressString(String_64 *Str)
01685 
01686     Author:     Olivier_Gascoin (Xara Group Ltd) <camelotdev@xara.com>
01687     Created:    21/04/97
01688     Inputs:     Str - This is the string to add in the ProgressString
01689     Outputs:    -
01690     Returns:    TRUE
01691     Purpose:    
01692     SeeAlso:    
01693 
01694 ********************************************************************************************/
01695 
01696 BOOL Filter::AddStringToProgressString(String_64 *Str)
01697 {
01698     m_StrToAddToProgress = *Str;
01699 
01700     return TRUE;
01701 }
01702 
01703 
01704 /********************************************************************************************
01705 
01706 >   virtual StringBase Filter::GetImportProgressString(CCLexFile* ImportFile, UINT32 ImportingMsgID)
01707 
01708     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01709     Created:    9/7/95
01710     Inputs:     ImportFile      file being used for importing
01711                 ImportingMsgID  id of message to use as basis on progress string
01712     Outputs:    -
01713     Returns:    String to use on the progress bar during import.
01714     Purpose:    Works out what progress bar string to use during importing of the file.
01715                 This consists of a basic message plus, if it will fit, a truncated form of
01716                 the filename being imported.
01717     SeeAlso:    Filter::GetExportProgressString;
01718 
01719 ********************************************************************************************/
01720 
01721 String_64 Filter::GetImportProgressString(CCLexFile* pImportFile, UINT32 ImportingMsgID)
01722 {
01723     String_64 ProgressString(ImportingMsgID);
01724 
01725     // Ammend the string with the filename, if we can. 
01726     GetProgressString(pImportFile, &ProgressString, &m_StrToAddToProgress);
01727 
01728     return ProgressString;
01729 }
01730 
01731 /********************************************************************************************
01732 
01733 >   virtual StringBase Filter::GetExportProgressString(CCLexFile* ExportFile, UINT32 ExportingMsgID)
01734 
01735     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01736     Created:    9/7/95
01737     Inputs:     ExportFile      file being used for importing
01738                 ImportingMsgID  id of message to use as basis on progress string
01739     Outputs:    -
01740     Returns:    String to use on the progress bar during import.
01741     Purpose:    Works out what progress bar string to use during exporting of the file.
01742                 This consists of a basic message plus, if it will fit, a truncated form of
01743                 the filename being exported.
01744     SeeAlso:    Filter::GetImportProgressString;
01745 
01746 ********************************************************************************************/
01747 
01748 String_64 Filter::GetExportProgressString(CCLexFile* pExportFile, UINT32 ExportingMsgID)
01749 {
01750 #ifdef DO_EXPORT
01751     String_64 ProgressString(ExportingMsgID);
01752 
01753     // Ammend the string with the filename, if we can. 
01754     GetProgressString(pExportFile, &ProgressString);
01755 
01756     return ProgressString;
01757 #else
01758     return String_64( _T("") );
01759 #endif
01760 }
01761 
01762 /********************************************************************************************
01763 
01764 >   virtual BOOL Filter::ExportVisibleLayersOnly()
01765 
01766     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01767     Created:    14/02/95
01768     Inputs:     -
01769     Outputs:    -
01770     Returns:    True if this filter wants to exclude invisible layers and so export only
01771                 visible items Or False if want to export everything.
01772     Purpose:    Determines if the filter wants to export only visible layers.
01773                 NB. This base class version does the default action of making the filter
01774                 export everything including hidden layers.
01775     SeeAlso:    Filter::ExportRender;
01776 
01777 ********************************************************************************************/
01778 
01779 BOOL Filter::ExportVisibleLayersOnly()
01780 {
01781     // base class version includes all layers and so everything will get exported
01782     return FALSE;
01783 }   
01784 
01785 /********************************************************************************************
01786 
01787 >   virtual BOOL Filter::ExportSelectionOnly()
01788 
01789     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01790     Created:    18/09/95
01791     Returns:    True if this filter wants check if an object is selected or not and so export
01792                 only the selected items Or False if want to export everything.
01793     Purpose:    Determines if the filter wants to export only selected items.
01794                 In the filters baseclass version the default action will be to
01795                 export all objects by default
01796                 Only used by bitmap export and in particular masked gif rendering at present.
01797     SeeAlso:    Filter::ExportRender;
01798 
01799 ********************************************************************************************/
01800 
01801 BOOL Filter::ExportSelectionOnly(BOOL MaskedRender)
01802 {
01803     // base class version says export everything regardless of whether selected or not.
01804     return FALSE;
01805 }
01806 
01807 
01808 /********************************************************************************************
01809 
01810 >   virtual BOOL Filter::OpenExportFile(CCDiskFile * pFile, PathName *pPath)
01811 
01812     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01813     Created:    22/12/95
01814     Inputs:     pDiskFile   The constructed disk file to use
01815                 pPath       The pathname of the file to be opened
01816     Returns:    True if the file has been opened correctly, False otherwise.
01817     Purpose:    Opens up the file ready for exporting into. Assumes the file has already
01818                 been constructed with the correct buffers etc..
01819     SeeAlso:    OpMenuExport::DoWithParam; Filters::DoExport;
01820     Errors:     The relevent error is set if the file did not open properly
01821 
01822 ********************************************************************************************/
01823 
01824 BOOL Filter::OpenExportFile(CCDiskFile * pDiskFile, PathName *pPath)
01825 {
01826 #ifdef DO_EXPORT
01827     ERROR2IF(pDiskFile == NULL, FALSE,"Filter::OpenExportFile null file supplied");
01828     ERROR2IF(pPath == NULL, FALSE,"Filter::OpenExportFile null pathname supplied");
01829 
01830     // Open up the file. This will create a zero length file just to make sure that it
01831     // is possible, i.e. we have write access. This should have actually already been
01832     // checked by the file export dialog code and trapped before this.
01833     // Added 27/9/95 ios::trunc as exporting a bitmap or eps file to the same file twice
01834     // appended the data to the end of the file on Windows 95.
01835     BOOL ok = pDiskFile->open(*pPath, ios::in | ios::out | ios::binary | ios::trunc);
01836     
01837     if (!ok)
01838     {
01839         // Failed to open the file so set the error that we want to report
01840         Error::SetError(_R(IDT_EXPORT_NOTFOUND), 0);
01841     }
01842     return ok;
01843 #else
01844     return FALSE;
01845 #endif
01846 }
01847 
01848 /********************************************************************************************
01849 
01850 >   virtual BOOL Filter::DeleteExportFile(CCDiskFile * pFile, PathName *pPath)
01851 
01852     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01853     Created:    22/12/95
01854     Inputs:     pDiskFile   The constructed disk file to use
01855     Returns:    True if the file has been closed and deleted correctly, False otherwise.
01856     Purpose:    Used for when either an export has been aborted by the user half way through
01857                 or when an error has occured. It closes up the export file, if open, and then
01858                 deletes it.
01859     SeeAlso:    OpMenuExport::DoWithParam; Filters::DoExport;
01860     SeeAlso:    ClipboardMapping::ExportToTempFile; OpMenuSave::SaveSpecificFile;
01861 
01862 ********************************************************************************************/
01863 
01864 BOOL Filter::DeleteExportFile(CCDiskFile * pDiskFile)
01865 {
01866 #ifdef DO_EXPORT
01867     ERROR2IF(pDiskFile == NULL, FALSE,"Filter::CloseExportFile null file supplied");
01868 
01869     // Remove the zero length file that we created as part of the process.
01870     
01871     // First, ensure file is closed
01872     if (pDiskFile->isOpen())
01873         pDiskFile->close();
01874     
01875     // Get its pathname 
01876     PathName Path = pDiskFile->GetPathName();
01877 
01878     // And try and remove it, only if it exists
01879     if (Path.IsValid())
01880     {
01881         BOOL Exists = TRUE;
01882         BOOL status = TRUE;
01883         Exists = SGLibOil::FileExists(&Path);
01884         if (Exists)
01885             status = SGLibOil::FileDelete(&Path);
01886         TRACEUSER( "Neville", _T("Filter::DeleteExportFile removed exists status =%d, file status =%d/n"),Exists,status);
01887     }
01888 #endif
01889     return TRUE;
01890 }
01891 
01892 /********************************************************************************************
01893 
01894 >   virtual BOOL Filter::ExportRender(RenderRegion *pRegion)
01895 
01896     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01897     Created:    28/03/94
01898     Inputs:     pRegion - the render region to export to.
01899     Returns:    TRUE if the export process completed successfully, FALSE if an error occured.
01900     Purpose:    Export a file to a given render region.  It is the responsibility of the
01901                 derived filter to create a render region of the correct type, and then pass
01902                 it to this function.
01903     Errors:     Render region is not connected to a spread.
01904     SeeAlso:    EPSRenderRegion::ExportRender, FlashRenderRegion::ExportRender
01905 
01906 ********************************************************************************************/
01907 
01908 BOOL Filter::ExportRender ( RenderRegion *pRegion, BOOL MaskedRender)
01909 {
01910 #ifdef DO_EXPORT
01911     // Disable bitmap caching but remember the old state so we can set it back
01912     ScopedFlagSetter fsBitmapCacheing(NodeRenderableBounded::bEnableCacheing, FALSE);
01913 
01914     ERROR2IF(pRegion==NULL,FALSE,"Filter::ExportRender null render region supplied");
01915 
01916     // We need special handling for Camelot EPS 
01917     // (NB. but not native files - do not change this to IS_KIND_OF!)
01918     BOOL IsCamelotEPS = IS_A(pRegion, CamelotEPSRenderRegion);
01919 
01920     // Get the DC for this export operation
01921     // This can be NULL, in the case of bitmap export, or a CMetaFileDC in the case
01922     // of MetaFile export. In the later case we MUST NOT set up the ExportDC pointer
01923     // pDC otherwise the CATCH handlers will fail as there is no ExportFile. Also the
01924     // progress bar message will fail.
01925     // The CDC can be Null if we are talking about bitmap export
01926     CNativeDC* pCDC = pRegion->GetRenderDC();
01927     ExportDC* pDC = NULL;
01928     NumNodes = 0;
01929 
01930     // At present, it appears that only EPS derived filters have a file attached and so
01931     // are the only ones which use an ExportDC. All bitmap filters use NULL.
01932     if( pCDC != NULL && this->IS_KIND_OF(EPSFilter))
01933         pDC = (ExportDC*)CCDC::ConvertFromNativeDC(pCDC);
01934     
01935     // Find out how big the document and document components are...
01936     // (We only do this for EPS files)
01937     if(
01938         this->IS_KIND_OF(EPSFilter) &&
01939         !IsCamelotEPS)
01940     {
01941         // First, we ask the document itself
01942         Document *pDocument = GetDocument();
01943         NumNodes += pDocument->GetSizeOfExport(this);
01944 
01945         // Next, the document components...
01946         DocComponent *pComponent = pDocument->EnumerateDocComponents(NULL);
01947 
01948         while (pComponent != NULL)
01949         {
01950             // Ask this document component how much data it will export.
01951             NumNodes += pComponent->GetSizeOfExport(this);
01952 
01953             // Look for next doc component
01954             pComponent = pDocument->EnumerateDocComponents(pComponent);
01955         }
01956     }
01957 
01958     // Remember how big this initial header is, so we don't overflow when writing
01959     // out and screw up the progress indication (which could happen if, e.g. the
01960     // bitmap export code was incorrect).
01961     CurrentProgressLimit = NumNodes;
01962 
01963     // Find the first node that we should export from this spread
01964     Node *pNode = pRegion->GetRenderSpread();
01965 
01966     ENSURE(pNode != NULL, "Render Region has no spread in Filter::ExportRender!");
01967     ERRORIF(pNode == NULL, _R(IDT_EXPORT_INTERNAL_ERR), FALSE);
01968 
01969     // Go and find the bounding rect for this spread and set the render regions
01970     // clipping rect to it
01971     if (pNode->IsSpread())
01972     {
01973         // find out the old clip rect
01974         DocRect OldClipRect = pRegion->GetClipRect();
01975 
01976         // only do something if it is empty
01977         if (OldClipRect.IsEmpty())
01978         {
01979             // Get a pointer to the spread and find out its bounding rect
01980             Spread* pSpread = (Spread*) pNode;
01981             DocRect SpreadRect = pSpread->GetBoundingRect();
01982             pSpread->DocCoordToSpreadCoord(&SpreadRect);
01983 
01984             // and set the render regions clipping rect to this
01985             pRegion->SetClipRect(SpreadRect);
01986         }
01987     }
01988 
01989     // Work out if this filter wants to include all layers or just the visible ones
01990     // Default action will be to include all so that say an eps or native filters save
01991     // everything. 
01992     BOOL bVisibleLayersOnly = ExportVisibleLayersOnly();
01993     BOOL bSelectedOnly = ExportSelectionOnly(MaskedRender);
01994 
01995     if (IsCamelotEPS)
01996     {
01997         try
01998         {
01999             // Special 3-stage rendering needed for Camelot EPS to be renderable.
02000             View *pView = DocView::GetSelected();
02001             Matrix RenderMatrix = pRegion->GetMatrix();
02002             RenderViewResult Result = pView->RenderSimpleView(pRegion, RenderMatrix,
02003                                                               pRegion->GetRenderSpread(), 
02004                                                               FALSE);
02005             if (Result == RENDERVIEW_USERABORT)
02006                 // Export is over - user has aborted it (but this is not an error)
02007                 return TRUE;
02008 
02009             if (Result == RENDERVIEW_FAILURE)
02010                 // Export was not successful
02011                 return FALSE;
02012 
02013             // This should never happen, as Camelot EPS cannot do 'eveything'
02014             ERROR3IF(Result == RENDERVIEW_NOTNEEDED, 
02015                      "RenderSimpleView did not render anything into EPS!");
02016 
02017             // Finished render region - close down region (i.e. output trailer).
02018             ((EPSRenderRegion *) pRegion)->CloseDown();
02019         }
02020 
02021         catch(CFileException)
02022         {
02023             // Didn't work - report failure to caller.
02024             if (pDC)
02025                 pDC->ExportFile->SetThrowExceptions(FALSE);
02026             return FALSE;
02027         }
02028         // All ok
02029         return TRUE;
02030     }
02031     else
02032     {
02033         FilterRenderCallback MyCallback(this, TRUE, bVisibleLayersOnly, bSelectedOnly);
02034         pRegion->RenderTree(pNode, FALSE, FALSE, &MyCallback);
02035         pRegion->ResetRender();
02036 
02037         // Now actually export the nodes themselves
02038         // Use a virtual function so that filters can overide this and say render in strips as
02039         // the bitmap filters are required to do
02040         ProgressOffset = 0;
02041         BOOL Result = ExportRenderNodes(pRegion, pDC, bVisibleLayersOnly, bSelectedOnly, FALSE/*TRUE*/);
02042 
02043         // return the result to the caller
02044         return Result;
02045     }
02046 #else
02047     return FALSE;
02048 #endif
02049 }
02050 
02051 
02052 
02053 
02054 /********************************************************************************************
02055 
02056 >   BOOL FilterRenderCallback::BeforeNode(RenderRegion* pRegion, Node* pNode)
02057 
02058     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
02059     Created:    30/11/2004
02060     Inputs:     pNode - pointer to node about to be rendered by RenderTree
02061                 pRender - pointer to RenderRegion running RenderTree loop
02062     Outputs:    -
02063     Returns:    TRUE if node can be rendered
02064                 FALSE if not
02065     Purpose:    Handle the callback from RenderTree that has been requested by Filter
02066 
02067 ********************************************************************************************/
02068 
02069 BOOL FilterRenderCallback::BeforeNode(RenderRegion* pRegion, Node* pNode)
02070 {
02071 // Don't need to do this because BeforeSubtree should have doen it for every node
02072 // that gets passed to BeforeNode...
02073 //  if (!pNode->NeedsToExport(pRegion, m_bVisibleLayersOnly, m_bSelectedOnly))
02074 //      return FALSE;
02075 
02076     if (m_bCount)
02077     {
02078         if (pNode->IsNodeRenderableClass())
02079             Filter::NumNodes += ((NodeRenderable*)pNode)->GetSizeOfExport(m_pFilter);
02080 
02081         return FALSE;   // Don't render anything!
02082     }
02083 
02084     // --------------------------------------------------------------------------
02085     // If rendering an RGBT bitmap, don't render anything in background layers
02086     if (pRegion->m_DoCompression)
02087     {
02088         Layer* pLayer = (Layer*)pNode->FindParent(CC_RUNTIME_CLASS(Layer));
02089         if (pLayer && pLayer->IsBackground())
02090             return FALSE;
02091     }
02092 
02093     // Update the progress display
02094     if (pNode->IsNodeRenderableClass())
02095         m_pFilter->UpdateFilterProgress(((NodeRenderable*)pNode)->GetSizeOfExport(m_pFilter));
02096     else
02097         m_pFilter->UpdateFilterProgress(0);             // For back compatibility with previous version of this code
02098 
02099     // Render (export) the node that we have, using special export rendering if it exists.
02100     BOOL bExportRendered = pNode->ExportRender(pRegion);
02101 
02102     return (!bExportRendered);                      // If not exported let RenderTree do it, return TRUE
02103 }
02104 
02105 
02106 /********************************************************************************************
02107 
02108 >   BOOL FilterRenderCallback::BeforeSubtree(RenderRegion* pRegion,
02109                                             Node* pNode,
02110                                             Node** ppNextNode,
02111                                             BOOL bClip,
02112                                             SubtreeRenderState* pState)
02113 
02114     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
02115     Created:    30/11/2004
02116     Inputs:     pNode - pointer to node about to be rendered by RenderTree
02117                 pRender - pointer to RenderRegion running RenderTree loop
02118     Outputs:    pNextNode - pointer to node where navigation should continue
02119                 State - Navigation state for RenderTree state machine
02120     Returns:    TRUE if we've returned a valid SubRenderState
02121                 FALSE if not
02122     Purpose:    Handle the callback from RenderTree that has been requested by Filter
02123 
02124 ********************************************************************************************/
02125 
02126 BOOL FilterRenderCallback::BeforeSubtree(RenderRegion* pRegion,
02127                                          Node* pNode,
02128                                          Node** ppNextNode,
02129                                          BOOL bClip,
02130                                          SubtreeRenderState* pState)
02131 {
02132     if (pNode==NULL)
02133         return TRUE;
02134 
02135     if (m_bCount)
02136     {
02137         // We're only counting so we will control tree navigation to ensure clever
02138         // nodes don't skip around by themselves
02139         if (pNode->NeedsToExport(pRegion, m_bVisibleLayersOnly, m_bSelectedOnly))
02140             *pState = SUBTREE_ROOTANDCHILDREN;
02141         else
02142             *pState = SUBTREE_NORENDER;
02143 
02144         return TRUE;
02145     }
02146 
02147     // --------------------------------------------------------------------------
02148     // We're not counting so let normal, smart navigation take place
02149     if (pNode->NeedsToExport(pRegion, m_bVisibleLayersOnly, m_bSelectedOnly))
02150     {
02151         // This node does need to be exported
02152         // Tell the node at the root of the subtree that we're about to export it and it's children
02153         pNode->PreExportRender(pRegion);
02154         return FALSE;                       // Tell RenderTree we want normal navigation to take place
02155     }
02156     else
02157     {
02158         *pState = SUBTREE_NORENDER;         // Tell RenderTree we want to forcibly skip this node
02159         return TRUE;
02160     }
02161 }
02162 
02163 
02164 
02165 
02166 /********************************************************************************************
02167 
02168 >   virtual BOOL Filter::ExportRenderNodes ( RenderRegion   *pRegion,
02169                                              ExportDC       *pDC,
02170                                              BOOL           VisibleLayersOnly       = FALSE,
02171                                              BOOL           CheckSelected           = FALSE,
02172                                              BOOL           ShowProgress            = TRUE )
02173 
02174     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> (from Neville's original code)
02175     Created:    12/4/00
02176     Inputs:     pRegion                 - the render region to export to.
02177                 pDc                     - device context to use, can be NULL.
02178                 VisibleLayersOnly       - use visible layers or not
02179                 ShowProgress            - TRUE then start up a progress bar or FALSE assume
02180                                           the caller has done it.
02181     Returns:    TRUE if the export process completed successfully, FALSE if an error occured.
02182     Purpose:    Sets up the file to do an export of the nodes in the tree, by initialising
02183                 the file, and any slow-job code. It then calls the WriteNodes method to do
02184                 the actual work, and EndExportRender to complete the task.
02185     SeeAlso:    Filter::ExportRender, Filter::WriteNodes, Filter::EndExportRender
02186 
02187 ********************************************************************************************/
02188 
02189 BOOL Filter::ExportRenderNodes ( RenderRegion   *pRegion,
02190                                  ExportDC       *pDC,
02191                                  BOOL           VisibleLayersOnly,
02192                                  BOOL           CheckSelected,
02193                                  BOOL           ShowProgress )
02194 {
02195 #ifdef DO_EXPORT
02196     ERROR2IF ( pRegion == NULL, FALSE, "Filter::ExportRender null render region supplied" );
02197 
02198     // Start a progress update going
02199     if ( ShowProgress )
02200     {
02201         String_64   ExportMessage ( GetExportMsgID () );
02202         if ( pDC && pDC->ExportFile )
02203         {
02204             ExportMessage = GetExportProgressString ( pDC->ExportFile, GetExportMsgID () );
02205         }
02206         BeginSlowJob ( NumNodes, FALSE, &ExportMessage );
02207     }
02208 
02209     // Work out how often we want to update the progress bar.
02210     UpdateEvery = ( NumNodes / 100 ) + 1;
02211     
02212     LastExportProgressUpdate = 0;
02213     NumNodes = 0;
02214 
02215     // Guard against disk/file errors, and get ready to render.
02216     //TRY
02217     {
02218         // Get the region ready to render.
02219         if ( !pRegion->StartRender() )
02220         {
02221             // An error occured.
02222             if ( ShowProgress )
02223                 EndSlowJob ();
02224             return FALSE;
02225         }
02226     }
02227 #if 0
02228     CATCH ( CFileException, e )
02229     {
02230         // Didn't work - report failure to caller.
02231         if ( pDC )
02232             pDC->ExportFile->SetThrowExceptions ( FALSE );
02233         if ( ShowProgress )
02234             EndSlowJob ();
02235         return FALSE;
02236     }
02237     END_CATCH
02238 #endif
02239     // Write the nodes out to the file, and end the export
02240     if ( WriteNodes ( pRegion, pDC, VisibleLayersOnly, CheckSelected, ShowProgress ) &&
02241          EndExportRender ( pRegion, ShowProgress ) )
02242     {
02243         // It worked.
02244         return TRUE;
02245     }
02246     else
02247     {
02248         // Houston, we have a problem.
02249         return FALSE;
02250     }
02251 
02252 #else
02253     return FALSE;
02254 #endif
02255 }
02256 
02257 
02258 /********************************************************************************************
02259 
02260 >   virtual BOOL Filter::WriteNodes ( RenderRegion  *pRegion,
02261                                       ExportDC      *pDC,
02262                                       BOOL          VisibleLayersOnly,
02263                                       BOOL          CheckSelected,
02264                                       BOOL          ShowProgress )
02265 
02266     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> (from Neville's original code)
02267     Created:    12/4/00
02268     Inputs:     pRegion                 - the render region to export to.
02269                 pDc                     - device context to use, can be NULL.
02270                 VisibleLayersOnly       - use visible layers or not
02271                 ShowProgress            - TRUE then start up a progress bar or FALSE assume
02272                                           the caller has done it.
02273     Returns:    TRUE if the export process completed successfully, FALSE if an error occured.
02274     Purpose:    Actually export the nodes to the given render region showing a progress bar
02275                 as we go. Assumes everything has been set up by ExportRender.   
02276                 Assumes that either a progress bar has been started and will be ended by the
02277                 caller or that it should start and end the progress bar itself.
02278     SeeAlso:    Filter::ExportRender, Filter::ExportRenderNodes
02279 
02280 ********************************************************************************************/
02281 
02282 BOOL Filter::WriteNodes ( RenderRegion  *pRegion,
02283                           ExportDC      *pDC,
02284                           BOOL          VisibleLayersOnly,
02285                           BOOL          SelectedOnly,
02286                           BOOL          ShowProgress )
02287 {
02288 #ifdef DO_EXPORT
02289 
02290     // Find the first node that we should export from this spread
02291     Node *pNode = pRegion->GetRenderSpread ();
02292 
02293     // Cycle through all exportable nodes, and render (export) them.
02294     // Export the file, but catch any file errors.
02295     //TRY
02296     {
02297 //      BOOL IsPageBackGroundAnd32BitAlpha = FALSE;
02298 //      BOOL LookForPageBackgrounds = TRUE;
02299 
02300         FilterRenderCallback MyCallback(this, FALSE, VisibleLayersOnly, SelectedOnly);  // Not counting this time!
02301         pRegion->RenderTree(pNode, FALSE, FALSE, &MyCallback);
02302         pRegion->ResetRender();
02303     }
02304 #if 0
02305     CATCH ( CFileException, e )
02306     {
02307         // Didn't work - report failure to caller.
02308         if ( pDC )
02309             pDC->ExportFile->SetThrowExceptions ( FALSE );
02310         pRegion->StopRender ();
02311         if ( ShowProgress )
02312             EndSlowJob ();
02313         return FALSE;
02314     }
02315     END_CATCH
02316 #endif
02317     // All OK
02318     return TRUE;
02319 #else
02320     return FALSE;
02321 #endif
02322 }
02323 
02324 
02325 /********************************************************************************************
02326 
02327 >   virtual void Filter::UpdateFilterProgress(UINT32 increment)
02328 
02329     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> (from Neville's original code)
02330     Created:    12/4/00
02331     Inputs:     pRegion                 - the render region to export to.
02332                 ShowProgress            - TRUE then start up a progress bar or FALSE assume
02333                                           the caller has done it.
02334     Returns:    TRUE if the export process completed successfully, FALSE if an error occured.
02335     Purpose:    Shuts down the export render process.
02336     SeeAlso:    Filter::ExportRender, Filter::ExportRenderNodes
02337 
02338 ********************************************************************************************/
02339 
02340 void Filter::UpdateFilterProgress(UINT32 increment)
02341 {
02342     // Limit the progress display to legal values
02343     if (increment>0)
02344         CurrentProgressLimit = NumNodes + increment;
02345 
02346     // Update node count accordingly
02347     NumNodes = CurrentProgressLimit;
02348 
02349     if (NumNodes > (LastExportProgressUpdate + UpdateEvery))
02350         LastExportProgressUpdate = NumNodes;
02351 }
02352 
02353 /********************************************************************************************
02354 
02355 >   virtual BOOL Filter::EndExportRender ( RenderRegion *pRegion,
02356                                            BOOL         ShowProgress )
02357 
02358     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> (from Neville's original code)
02359     Created:    12/4/00
02360     Inputs:     pRegion                 - the render region to export to.
02361                 ShowProgress            - TRUE then start up a progress bar or FALSE assume
02362                                           the caller has done it.
02363     Returns:    TRUE if the export process completed successfully, FALSE if an error occured.
02364     Purpose:    Shuts down the export render process.
02365     SeeAlso:    Filter::ExportRender, Filter::ExportRenderNodes
02366 
02367 ********************************************************************************************/
02368 
02369 BOOL Filter::EndExportRender ( RenderRegion *pRegion,
02370                                BOOL         ShowProgress )
02371 {
02372 #ifdef DO_EXPORT
02373 
02374     //TRY
02375     {
02376         // Finished rendering - deinit render region.
02377         pRegion->StopRender ();
02378 
02379         // Shut down the render region.
02380         pRegion->CloseDown ();
02381     }
02382 #if 0
02383     CATCH ( CFileException, e )
02384     {
02385         // Didn't work - report failure to caller.
02386         if ( ShowProgress )
02387             EndSlowJob ();
02388         return FALSE;
02389     }
02390     END_CATCH
02391 #endif
02392     // Close down progress display, if present
02393     if ( ShowProgress )
02394         EndSlowJob ();
02395 
02396     // All OK
02397     return TRUE;
02398 #else
02399     return FALSE;
02400 #endif
02401 }
02402 
02403 /********************************************************************************************
02404 
02405 >   UINT32 Filter::GetNumNodes()
02406 
02407     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02408     Created:    16/5/95
02409     Inputs:     -
02410     Outputs:    -
02411     Returns:    The numbers of nodes which are currently set up to be used for a progress bar.
02412     Purpose:    Allows access to the stored numbers of nodes which is currently set up to
02413                 be used for a progress bar.
02414     
02415 ********************************************************************************************/
02416 
02417 UINT32 Filter::GetNumNodes()
02418 {
02419     return NumNodes;
02420 }
02421 
02422 /********************************************************************************************
02423 
02424 >   UINT32 Filter::SetNumNodes(UINT32 NewNumNodes)
02425 
02426     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02427     Created:    16/5/95
02428     Inputs:     -
02429     Outputs:    -
02430     Returns:    The old number of nodes value
02431     Purpose:    Allows setting of the stored numbers of nodes which is currently set up to
02432                 be used for a progress bar.
02433     
02434 ********************************************************************************************/
02435 
02436 UINT32 Filter::SetNumNodes(UINT32 NewNumNodes)
02437 {
02438     UINT32 OldNumNodes = NumNodes;
02439     
02440     NumNodes = NewNumNodes;
02441     
02442     return OldNumNodes;
02443 }
02444 
02445 
02446 /********************************************************************************************
02447 
02448 >   BOOL Filter::UpdateExportedNodeCount(UINT32 NumNodesSaved)
02449 
02450     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02451     Created:    27/01/95
02452     Inputs:     NumNodes - number of nodes just saved.
02453     Returns:    TRUE if the progress display was updated ok;
02454                 FALSE if not (i.e. the user pressed Esc to cancel the operation).
02455     Purpose:    Update the progress display according to the number passed in.  The NumNodes
02456                 parameter indicates how many nodes have just been saved.
02457                 Most nodes won't call this when exporting as they are only '1' node.
02458                 Nodes such as blenders or bitmaps may call this to update the progress
02459                 more smoothly.
02460                 E.g. a bitmap might say that it is 20 nodes if it has 20 scanlines.  It 
02461                     could then call this function after each scanline is saved with the
02462                     value 1.  It should not call it with more than the number of nodes it 
02463                     claims to be, e.g. the example bitmap above should only ever call with 
02464                     NumNodes in the range 1 to 20.  And the cumulative total of NumNodesSaved
02465                     passed in by one node should never be more than the number of nodes it
02466                     claims to be either.
02467 
02468     SeeAlso:    Node::GetSizeOfExport
02469 
02470 ********************************************************************************************/
02471 
02472 BOOL Filter::UpdateExportedNodeCount(UINT32 NumNodesSaved)
02473 {
02474 #ifdef DO_EXPORT
02475     // Work out how many nodes have been saved in total.
02476     NumNodes += NumNodesSaved;
02477 
02478     // Make sure we remain within the legal range of values
02479     if (NumNodes > CurrentProgressLimit)
02480     {
02481         #if _DEBUG
02482         // Only report an error once for each sub-section otherwise it's too annoying.
02483         static UINT32 LastError = 0;
02484         if (LastError != CurrentProgressLimit)
02485         {
02486             if (Error::IsUserName("Tim"))
02487             {
02488                 ERROR3("Filter::UpdateExportedNodeCount() called with an out of range value!");
02489             }
02490             LastError = CurrentProgressLimit;
02491         }
02492         #endif
02493 
02494         // Ignore the error in retail builds - it's not serious (but limit the value)
02495         NumNodes = CurrentProgressLimit;
02496     }
02497 
02498     // Check to see if it's worth updating yet.
02499     if (NumNodes > (LastExportProgressUpdate + UpdateEvery))
02500     {
02501         LastExportProgressUpdate = NumNodes;
02502 
02503         if (!ContinueSlowJob(NumNodes))
02504         {
02505             return FALSE;
02506         }
02507     }
02508 
02509 #endif
02510     // Everything is ok if we get here
02511     return TRUE;
02512 }
02513 
02514 /********************************************************************************************
02515 
02516 >   BitmapFilterSupport Filter::GetBitmapSupportLevel()
02517 
02518     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02519     Created:    30/01/95
02520     Returns:            NoBitmapSupport - This filter does not support bitmap images.
02521                     SimpleBitmapSupport - This filter has simple support for bitmap images;
02522                                           they must be saved into the file whenever
02523                                           they are used.
02524                 IndirectedBitmapSupport - This filter supports bitmap indirection; i.e. a
02525                                           bitmap pool of some type is saved and then this
02526                                           can be referenced in the file.
02527     Purpose:    Determine how well this filter supports bitmaps when exporting.
02528 
02529 ********************************************************************************************/
02530 
02531 BitmapFilterSupport Filter::GetBitmapSupportLevel()
02532 {
02533     // Defaults to no bitmap support
02534     return NoBitmapSupport;
02535 }
02536 
02537 /********************************************************************************************
02538 
02539 >   BOOL Filter::ImportBitmap(CCLexFile*, KernelBitmap**)
02540 
02541     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02542     Created:    8/4/94
02543     Inputs:     -
02544     Returns:    TRUE if the bitmap was imported ok (or if it wasn't imported because the
02545                      file format does not support it;
02546                 FALSE if an error occured.
02547     Purpose:    -
02548     Errors:     Usual disk/file errors.
02549     SeeAlso:    CamelotEPSFilter::ExportBitmap
02550 
02551 ********************************************************************************************/
02552 
02553 BOOL Filter::ImportBitmap(CCLexFile*, KernelBitmap**)
02554 {
02555     // Base class - ignore bitmaps
02556     return TRUE;
02557 }
02558 
02559 /********************************************************************************************
02560 
02561 >   BOOL Filter::ExportBitmap(KernelBitmap& TheBitmap)
02562 
02563     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02564     Created:    01/09/94
02565     Inputs:     TheBitmap - the bitmap to export
02566     Returns:    TRUE if the bitmap was exported ok (or if it wasn't exported because the
02567                      file format does not support it;
02568                 FALSE if an error occured.
02569     Purpose:    Virtual function to export a bitmap to a file.  This base class version
02570                 always does nothing and returns TRUE, so formats which do not support
02571                 bitmaps need do nothing.  Formats that support bitmaps should over-ride
02572                 this function to do the necessary work required to embed the bitmap into
02573                 the file.
02574     Errors:     Usual disk/file errors.
02575     SeeAlso:    CamelotEPSFilter::ExportBitmap
02576 
02577 ********************************************************************************************/
02578 
02579 BOOL Filter::ExportBitmap(KernelBitmap&)
02580 {
02581     // Base class - ignore bitmaps
02582     return TRUE;
02583 }
02584 
02585 
02586 /********************************************************************************************
02587 
02588 >   BOOL Filter::SetLineColour(DocColour& Col)
02589 
02590     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02591     Created:    13/04/94
02592     Inputs:     Col - the new line colour to use.
02593     Returns:    TRUE if the attribute was changed ok; 
02594                 FALSE otherwise.
02595     Purpose:    Updates the current attribute for line colour to reflect the value passed 
02596                 in.
02597     Errors:     Out of memory.
02598     SeeAlso:    Filter; Filter::Init
02599 
02600 ********************************************************************************************/
02601 
02602 BOOL Filter::SetLineColour(DocColour& Col)
02603 {
02604     // Sanity check
02605     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
02606 
02607     // If we haven't changed this attribute yet, then make a new attribute object for
02608     // our own personal use...
02609     if (!CurrentAttrs[ATTR_STROKECOLOUR].Temp)
02610     {
02611         // Make the correct attribute value and install it as the current one.
02612         CurrentAttrs[ATTR_STROKECOLOUR].pAttr = new StrokeColourAttribute(Col);
02613         if (CurrentAttrs[ATTR_STROKECOLOUR].pAttr == NULL)
02614             return FALSE;
02615         CurrentAttrs[ATTR_STROKECOLOUR].Temp = TRUE;
02616     }
02617     else
02618     {
02619         // We already have an attribute - just change it.
02620         StrokeColourAttribute *pAttr = 
02621             (StrokeColourAttribute *) CurrentAttrs[ATTR_STROKECOLOUR].pAttr;
02622         pAttr->Colour = Col;
02623     }
02624 
02625     // All worked ok.
02626     return TRUE;
02627 }
02628 
02629 /********************************************************************************************
02630 
02631 >   BOOL Filter::SetLineWidth(MILLIPOINT Width)
02632 
02633     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02634     Created:    13/04/94
02635     Inputs:     Width - the new line width to use.
02636     Returns:    TRUE if the attribute was changed ok; 
02637                 FALSE otherwise.
02638     Purpose:    Updates the current attribute for line width to reflect the value passed 
02639                 in.
02640     Errors:     Out of memory.
02641     SeeAlso:    Filter; Filter::Init
02642 
02643 ********************************************************************************************/
02644 
02645 BOOL Filter::SetLineWidth(MILLIPOINT Width)
02646 {
02647     // Sanity check
02648     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
02649 
02650     // Avoid zero width lines - change them to the value specified in the user preference.
02651     if (Width == 0)
02652         Width = MinLineWidth;
02653 
02654     // If we haven't changed this attribute yet, then make a new attribute object for
02655     // our own personal use...
02656     if (!CurrentAttrs[ATTR_LINEWIDTH].Temp)
02657     {
02658         // Make the correct attribute value and install it as the current one.
02659         CurrentAttrs[ATTR_LINEWIDTH].pAttr = new LineWidthAttribute(Width);
02660         if (CurrentAttrs[ATTR_LINEWIDTH].pAttr == NULL)
02661             return FALSE;
02662         CurrentAttrs[ATTR_LINEWIDTH].Temp = TRUE;
02663     }
02664     else
02665     {
02666         // We already have an attribute - just change it.
02667         LineWidthAttribute *pAttr = 
02668             (LineWidthAttribute *) CurrentAttrs[ATTR_LINEWIDTH].pAttr;
02669         pAttr->LineWidth = Width;
02670     }
02671 
02672     // All worked ok.
02673     return TRUE;
02674 }
02675 
02676 /********************************************************************************************
02677 
02678 >   BOOL Filter::SetLineCap(LineCapType LineCap)
02679 
02680     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02681     Created:    13/04/94
02682     Inputs:     LineCap - the new line cap style to use.
02683     Returns:    TRUE if the attribute was changed ok; 
02684                 FALSE otherwise.
02685     Purpose:    Updates the current attribute for line cap style to reflect the value passed 
02686                 in.
02687     Errors:     Out of memory.
02688     SeeAlso:    Filter; Filter::Init
02689 
02690 ********************************************************************************************/
02691 
02692 BOOL Filter::SetLineCap(LineCapType LineCap)
02693 {
02694     // Sanity check
02695     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
02696 
02697     // If we haven't changed this attribute yet, then make a new attribute object for
02698     // our own personal use...
02699     if (!CurrentAttrs[ATTR_STARTCAP].Temp)
02700     {
02701         // Make the correct attribute value and install it as the current one.
02702         CurrentAttrs[ATTR_STARTCAP].pAttr = new StartCapAttribute;
02703         if (CurrentAttrs[ATTR_STARTCAP].pAttr == NULL)
02704             return FALSE;
02705         CurrentAttrs[ATTR_STARTCAP].Temp = TRUE;
02706     }
02707 
02708     // We have an attribute - just change it.
02709     StartCapAttribute *pAttr = 
02710         (StartCapAttribute *) CurrentAttrs[ATTR_STARTCAP].pAttr;
02711     pAttr->StartCap = LineCap;
02712 
02713     // All worked ok.
02714     return TRUE;
02715 }
02716 
02717 /********************************************************************************************
02718 
02719 >   BOOL Filter::SetJoinType(JointType JoinType)
02720 
02721     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
02722     Created:    13/04/94
02723     Inputs:     JoinType - the new line join style to use.
02724     Returns:    TRUE if the attribute was changed ok; 
02725                 FALSE otherwise.
02726     Purpose:    Updates the current attribute for line join style to reflect the value passed 
02727                 in.
02728     Errors:     Out of memory.
02729     SeeAlso:    Filter; Filter::Init
02730 
02731 ********************************************************************************************/
02732 
02733 BOOL Filter::SetJoinType(JointType JoinType)
02734 {
02735     // Sanity check
02736     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
02737 
02738     // If we haven't changed this attribute yet, then make a new attribute object for
02739     // our own personal use...
02740     if (!CurrentAttrs[ATTR_JOINTYPE].Temp)
02741     {
02742         // Make the correct attribute value and install it as the current one.
02743         CurrentAttrs[ATTR_JOINTYPE].pAttr = new JoinTypeAttribute;
02744         if (CurrentAttrs[ATTR_JOINTYPE].pAttr == NULL)
02745             return FALSE;
02746         CurrentAttrs[ATTR_JOINTYPE].Temp = TRUE;
02747     }
02748 
02749     // We have an attribute - just change it.
02750     JoinTypeAttribute *pAttr = 
02751         (JoinTypeAttribute *) CurrentAttrs[ATTR_JOINTYPE].pAttr;
02752     pAttr->JoinType = JoinType;
02753 
02754     // All worked ok.
02755     return TRUE;
02756 }
02757 
02758 /********************************************************************************************
02759 
02760 >   BOOL Filter::SetLineTransp(UINT32 TranspType, UINT32 Transp)
02761 
02762     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02763     Created:    15/04/95
02764     Inputs:     TranspType - the transparency type to use.
02765                 Transp - the transparency (0 to 255) of the line.
02766     Returns:    TRUE if the attribute was changed ok; 
02767                 FALSE otherwise.
02768     Purpose:    Updates the current attribute for line transparency to reflect the value 
02769                 passed in.
02770     Errors:     Out of memory.
02771     SeeAlso:    Filter; Filter::Init
02772 
02773 ********************************************************************************************/
02774 
02775 BOOL Filter::SetLineTransp(UINT32 TranspType, UINT32 Transp)
02776 {
02777     // Sanity check
02778     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
02779 
02780     // If we haven't changed this attribute yet, then make a new attribute object for
02781     // our own personal use...
02782     if (!CurrentAttrs[ATTR_STROKETRANSP].Temp)
02783     {
02784         // Make the correct attribute value and install it as the current one.
02785         CurrentAttrs[ATTR_STROKETRANSP].pAttr = new StrokeTranspAttribute;
02786         if (CurrentAttrs[ATTR_STROKETRANSP].pAttr == NULL)
02787             return FALSE;
02788         CurrentAttrs[ATTR_STROKETRANSP].Temp = TRUE;
02789     }
02790 
02791     // We have an attribute - just change it.
02792     StrokeTranspAttribute *pAttr = 
02793         (StrokeTranspAttribute *) CurrentAttrs[ATTR_STROKETRANSP].pAttr;
02794 
02795     pAttr->TranspType = TranspType;
02796     pAttr->Transp = Transp;
02797 
02798     // All worked ok.
02799     return TRUE;
02800 }
02801 
02802 /********************************************************************************************
02803 
02804 >   BOOL Filter::SetDashPattern(DashRec& Dash)
02805 
02806     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02807     Created:    15/04/95
02808     Inputs:     Dash - the Dash Pattern to use.
02809     Returns:    TRUE if the attribute was changed ok; 
02810                 FALSE otherwise.
02811     Purpose:    Updates the current attribute for dash pattern to reflect the value 
02812                 passed in.
02813     Errors:     Out of memory.
02814     SeeAlso:    Filter; Filter::Init
02815 
02816 ********************************************************************************************/
02817 
02818 BOOL Filter::SetDashPattern(DashRec& Dash)
02819 {
02820     // Sanity check
02821     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
02822 
02823     // If we haven't changed this attribute yet, then make a new attribute object for
02824     // our own personal use...
02825     if (!CurrentAttrs[ATTR_DASHPATTERN].Temp)
02826     {
02827         // Make the correct attribute value and install it as the current one.
02828         CurrentAttrs[ATTR_DASHPATTERN].pAttr = new DashPatternAttribute;
02829         if (CurrentAttrs[ATTR_DASHPATTERN].pAttr == NULL)
02830             return FALSE;
02831         CurrentAttrs[ATTR_DASHPATTERN].Temp = TRUE;
02832     }
02833 
02834     // We have an attribute - just change it.
02835     DashPatternAttribute *pAttr = 
02836         (DashPatternAttribute *) CurrentAttrs[ATTR_DASHPATTERN].pAttr;
02837 
02838     // Bodge 
02839     // When we save Native files we at present save out a dash pattern ID and then
02840     // save out the full dash pattern definition! This is ok apart from wasting space.
02841     // The problem happens when we load the information back in, we load the id and apply
02842     // the relevent dash pattern and then load the definition and apply it, zapping the
02843     // id.
02844     // If we are a native filter then assume that the id has already been set up
02845     // Now done in CheckIfDefaultPattern below.
02846     // But have to disable both checks as if we set the id then we would have an id on 
02847     // a scaled version of the pattern. This would also only fix files which have been
02848     // save once, as saving again will have completely lost all trace of the id! 
02849     /* if (this->IS_KIND_OF(CamelotNativeEPSFilter))
02850     {
02851         // Note the current id already put there by the native filter
02852         INT32 DashId = pAttr->DashPattern.GetDashID();
02853         // Copy the new dash pattern over
02854         pAttr->DashPattern = Dash;
02855         // Copy the original ID across but only if it has been set
02856         // As it will default to zero then we copy it across if we have changed it!
02857         if (DashId != 0)
02858             pAttr->DashPattern.DashID = DashId; 
02859     }
02860     else */
02861 
02862     pAttr->DashPattern = Dash;
02863     
02864     // make sure the dash pattern is OK
02865     pAttr->DashPattern.CheckAndFix();
02866 
02867     // Reset the ID if it is one of our default patterns
02868     // Cannot do this check as when a line is first saved the definition is scaled
02869     // for some strange and bizarre reason, possible to do with the fact that a general
02870     // EPS saving routine is being used.
02871     //pAttr->DashPattern.CheckIfDefaultPattern();
02872 
02873     // All worked ok.
02874     return TRUE;
02875 }
02876 
02877 /********************************************************************************************
02878 
02879 >   BOOL Filter::SetStartArrow(ArrowRec& Arrow)
02880 
02881     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02882     Created:    15/04/95
02883     Inputs:     Arrow - the Arrow to use.
02884     Returns:    TRUE if the attribute was changed ok; 
02885                 FALSE otherwise.
02886     Purpose:    Updates the current attribute for Start Arrow to reflect the value 
02887                 passed in.
02888     Errors:     Out of memory.
02889     SeeAlso:    Filter; Filter::Init
02890 
02891 ********************************************************************************************/
02892 
02893 BOOL Filter::SetStartArrow(ArrowRec& Arrow)
02894 {
02895     // Sanity check
02896     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
02897 
02898     // If we haven't changed this attribute yet, then make a new attribute object for
02899     // our own personal use...
02900     if (!CurrentAttrs[ATTR_STARTARROW].Temp)
02901     {
02902         // Make the correct attribute value and install it as the current one.
02903         CurrentAttrs[ATTR_STARTARROW].pAttr = new StartArrowAttribute;
02904         if (CurrentAttrs[ATTR_STARTARROW].pAttr == NULL)
02905             return FALSE;
02906         CurrentAttrs[ATTR_STARTARROW].Temp = TRUE;
02907     }
02908 
02909     // We have an attribute - just change it.
02910     StartArrowAttribute *pAttr = 
02911         (StartArrowAttribute *) CurrentAttrs[ATTR_STARTARROW].pAttr;
02912 
02913     pAttr->StartArrow = Arrow;
02914 
02915     // All worked ok.
02916     return TRUE;
02917 }
02918 
02919 /********************************************************************************************
02920 
02921 >   BOOL Filter::SetEndArrow(ArrowRec& Arrow)
02922 
02923     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02924     Created:    15/04/95
02925     Inputs:     Arrow - the Arrow to use.
02926     Returns:    TRUE if the attribute was changed ok; 
02927                 FALSE otherwise.
02928     Purpose:    Updates the current attribute for End Arrow to reflect the value 
02929                 passed in.
02930     Errors:     Out of memory.
02931     SeeAlso:    Filter; Filter::Init
02932 
02933 ********************************************************************************************/
02934 
02935 BOOL Filter::SetEndArrow(ArrowRec& Arrow)
02936 {
02937     // Sanity check
02938     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
02939 
02940     // If we haven't changed this attribute yet, then make a new attribute object for
02941     // our own personal use...
02942     if (!CurrentAttrs[ATTR_ENDARROW].Temp)
02943     {
02944         // Make the correct attribute value and install it as the current one.
02945         CurrentAttrs[ATTR_ENDARROW].pAttr = new EndArrowAttribute;
02946         if (CurrentAttrs[ATTR_ENDARROW].pAttr == NULL)
02947             return FALSE;
02948         CurrentAttrs[ATTR_ENDARROW].Temp = TRUE;
02949     }
02950 
02951     // We have an attribute - just change it.
02952     EndArrowAttribute *pAttr = 
02953         (EndArrowAttribute *) CurrentAttrs[ATTR_ENDARROW].pAttr;
02954 
02955     pAttr->EndArrow = Arrow;
02956 
02957     // All worked ok.
02958     return TRUE;
02959 }
02960 
02961 /********************************************************************************************
02962 
02963 >   BOOL Filter::SetMitreLimit(MILLIPOINT MitreLimit)
02964 
02965     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02966     Created:    15/04/95
02967     Inputs:     Arrow - the Arrow to use.
02968     Returns:    TRUE if the attribute was changed ok; 
02969                 FALSE otherwise.
02970     Purpose:    Updates the current attribute for the Mitre Limit to reflect the value 
02971                 passed in.
02972     Errors:     Out of memory.
02973     SeeAlso:    Filter; Filter::Init
02974 
02975 ********************************************************************************************/
02976 
02977 BOOL Filter::SetMitreLimit(MILLIPOINT MitreLimit)
02978 {
02979     // Sanity check
02980     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
02981 
02982     // If we haven't changed this attribute yet, then make a new attribute object for
02983     // our own personal use...
02984     if (!CurrentAttrs[ATTR_MITRELIMIT].Temp)
02985     {
02986         // Make the correct attribute value and install it as the current one.
02987         CurrentAttrs[ATTR_MITRELIMIT].pAttr = new MitreLimitAttribute;
02988         if (CurrentAttrs[ATTR_MITRELIMIT].pAttr == NULL)
02989             return FALSE;
02990         CurrentAttrs[ATTR_MITRELIMIT].Temp = TRUE;
02991     }
02992 
02993     // We have an attribute - just change it.
02994     MitreLimitAttribute *pAttr = 
02995         (MitreLimitAttribute *) CurrentAttrs[ATTR_MITRELIMIT].pAttr;
02996 
02997     pAttr->MitreLimit = MitreLimit;
02998 
02999     // All worked ok.
03000     return TRUE;
03001 }
03002 
03003 
03004 
03005 /********************************************************************************************
03006 
03007 >   BOOL Filter::SetPathFilled(BOOL Filled)
03008 
03009     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03010     Created:    04/01/95
03011     Inputs:     Filled - whether or not paths should be filled.
03012     Returns:    TRUE if ok;
03013                 FALSE otherwise (e.g. out of memory)
03014     Purpose:    Indicate whether paths should be filled or not.  This is independent of the
03015                 current fill attribute, so, for example, if this function is called to
03016                 set the paths to be unfilled, and then called again to set them to be
03017                 filled, then afterwards all paths filled will be filled with whatever
03018                 fill attribute was last set.
03019     Errors:     Out of memory => ERROR1
03020     SeeAlso:    Filter::SetFillColour
03021 
03022 ********************************************************************************************/
03023 
03024 BOOL Filter::SetPathFilled(BOOL Filled)
03025 {
03026     if(Filled == PathFilled)
03027         return TRUE;
03028     
03029     if (Filled)
03030     {
03031         // See if we need to reinstate the fill attribute
03032         if (FillAttr.pAttr != NULL)
03033         {
03034             // Yes we do...
03035             if (CurrentAttrs[ATTR_FILLGEOMETRY].Temp)
03036             {
03037                 // Get rid of the current one (if it is a temporary attribute)
03038                 delete CurrentAttrs[ATTR_FILLGEOMETRY].pAttr;
03039             }
03040 
03041             // Install the new one, and vape the pointer so we don't do this again.
03042             CurrentAttrs[ATTR_FILLGEOMETRY] = FillAttr;
03043             FillAttr.pAttr = NULL;
03044         }
03045     }
03046     else
03047     {
03048         // Lose the current saved FillAttr if we need to.
03049         if ((FillAttr.pAttr != NULL) && (FillAttr.Temp))
03050         {
03051             delete FillAttr.pAttr;
03052         }
03053 
03054         // Disabling the fill attribute - remember the current one.
03055         FillAttr = CurrentAttrs[ATTR_FILLGEOMETRY];
03056 
03057         // Install a new flat colour fill...
03058         CurrentAttrs[ATTR_FILLGEOMETRY].pAttr = new FlatFillAttribute;
03059         if (CurrentAttrs[ATTR_FILLGEOMETRY].pAttr == NULL)
03060             return FALSE;
03061         CurrentAttrs[ATTR_FILLGEOMETRY].Temp = TRUE;
03062 
03063         // .. and make it a transparent fill
03064         DocColour TransCol(COLOUR_TRANS);
03065         FillGeometryAttribute *pAttr = (FillGeometryAttribute *) 
03066                                                     CurrentAttrs[ATTR_FILLGEOMETRY].pAttr;
03067         pAttr->SetStartColour(&TransCol);
03068     }
03069 
03070     PathFilled = Filled;
03071 
03072     // Must be ok if we got here
03073     return TRUE;
03074 }
03075 
03076 
03077 /********************************************************************************************
03078 
03079 >   BOOL Filter::SetFillColour(DocColour& Col)
03080 
03081     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03082     Created:    13/04/94
03083     Inputs:     Col - the new fill colour to use.
03084     Returns:    TRUE if the attribute was changed ok; 
03085                 FALSE otherwise.
03086     Purpose:    Updates the current attribute for fill colour to reflect the value passed 
03087                 in.
03088     Errors:     Out of memory.
03089     SeeAlso:    Filter; Filter::Init
03090 
03091 ********************************************************************************************/
03092 
03093 BOOL Filter::SetFillColour(DocColour& Col)
03094 {
03095     // Sanity check
03096     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
03097 
03098     // Find out which fill attribute to change
03099     AttributeEntry *pEntry;
03100     if (FillAttr.pAttr == NULL)
03101         // No 'saved' fill attribute, so just update the normal one.
03102         pEntry = &CurrentAttrs[ATTR_FILLGEOMETRY];
03103     else
03104         // Update the saved fill attribute.
03105         pEntry = &FillAttr;
03106 
03107     // If we haven't changed this attribute yet, then make a new attribute object for
03108     // our own personal use...
03109     if (!pEntry->Temp)
03110     {
03111         // Make the correct attribute value and install it as the current one.
03112         pEntry->pAttr = new FlatFillAttribute(Col);
03113         if (pEntry->pAttr == NULL)
03114             return FALSE;
03115         pEntry->Temp = TRUE;
03116     }
03117     else
03118     {
03119         // Ensure we have the correct attribute
03120         if (!IS_A(pEntry->pAttr, FlatFillAttribute))
03121         {
03122             // Wrong type - delete it and get the right type of attribute value.
03123             delete pEntry->pAttr;
03124             pEntry->pAttr = new FlatFillAttribute;
03125             if (pEntry->pAttr == NULL)
03126                 return FALSE;
03127         }
03128     }
03129 
03130     // We've got an attribute - change it.
03131     FlatFillAttribute *pAttr = (FlatFillAttribute *) pEntry->pAttr;
03132 
03133     pAttr->SetStartColour(&Col);
03134 
03135     // All worked ok.
03136     return TRUE;
03137 }
03138 
03139 /********************************************************************************************
03140 
03141 >   BOOL Filter::SetLinearFill(DocColour StartColour, DocColour EndColour,
03142                                DocCoord StartPoint, DocCoord EndPoint,
03143                                DocCoord *EndPoint2 = NULL)
03144 
03145     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03146     Created:    13/04/94
03147     Inputs:     StartColour, EndColour, StartPoint, EndPoint - see GradFillAttribute.
03148     Returns:    TRUE if the attribute was changed ok; 
03149                 FALSE otherwise.
03150     Purpose:    Updates the current attribute for gradfill colour to reflect the value passed 
03151                 in.
03152     Errors:     Out of memory.
03153     SeeAlso:    Filter; Filter::Init; GradFillAttribute
03154 
03155 ********************************************************************************************/
03156 
03157 BOOL Filter::SetLinearFill(DocColour &StartColour, DocColour &EndColour,
03158                            DocCoord StartPoint, DocCoord EndPoint,
03159                            DocCoord *EndPoint2)
03160 {
03161     // Sanity check
03162     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
03163 
03164     // Find out which fill attribute to change
03165     AttributeEntry *pEntry;
03166     if (FillAttr.pAttr == NULL)
03167         // No 'saved' fill attribute, so just update the normal one.
03168         pEntry = &CurrentAttrs[ATTR_FILLGEOMETRY];
03169     else
03170         // Update the saved fill attribute.
03171         pEntry = &FillAttr;
03172 
03173     // If we haven't changed this attribute yet, then make a new attribute object for
03174     // our own personal use...
03175     if (!pEntry->Temp)
03176     {
03177         // Make the correct attribute value and install it as the current one.
03178         pEntry->pAttr = new LinearFillAttribute;
03179         if (pEntry->pAttr == NULL)
03180             return FALSE;
03181         pEntry->Temp = TRUE;
03182     }
03183     else
03184     {
03185         // Ensure we have the correct attribute
03186         if (!IS_A(pEntry->pAttr, LinearFillAttribute))
03187         {
03188             // Wrong type - delete it and get the right type of attribute value.
03189             delete pEntry->pAttr;
03190             pEntry->pAttr = new LinearFillAttribute;
03191             if (pEntry->pAttr == NULL)
03192                 return FALSE;
03193         }
03194     }
03195 
03196     // We've got an attribute - change it.
03197     LinearFillAttribute *pAttr = (LinearFillAttribute *) pEntry->pAttr;
03198 
03199     // Copy field values.
03200     pAttr->SetStartColour(&StartColour);
03201     pAttr->SetEndColour(&EndColour);
03202     pAttr->SetStartPoint(&StartPoint);
03203     pAttr->SetEndPoint(&EndPoint);
03204     pAttr->SetEndPoint2(EndPoint2);
03205 
03206     // All worked ok.
03207     return TRUE;
03208 }
03209 
03210 /********************************************************************************************
03211 
03212 >   BOOL Filter::SetRadialFill(DocColour StartColour, DocColour EndColour,
03213                                DocCoord StartPoint, DocCoord EndPoint)
03214 
03215     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03216     Created:    13/04/94
03217     Inputs:     StartColour, EndColour - colours to fade between.
03218                 StartPoint, EndPoint1 - the points defining the radial fill.
03219     Returns:    TRUE if the attribute was changed ok; 
03220                 FALSE otherwise.
03221     Purpose:    Updates the current attribute for gradfill colour to reflect the value passed 
03222                 in.
03223     Errors:     Out of memory.
03224     SeeAlso:    Filter; Filter::Init; GradFillAttribute
03225 
03226 ********************************************************************************************/
03227 
03228 BOOL Filter::SetRadialFill(DocColour &StartColour, DocColour &EndColour,
03229                            DocCoord StartPoint, DocCoord EndPoint)
03230 {
03231     // Call the more general function...
03232     BOOL Success = SetRadialFill(StartColour, EndColour, StartPoint, EndPoint, EndPoint);
03233 
03234     // Set the new attribute to be a circular one, if it worked
03235     if (Success)
03236     {
03237         RadialFillAttribute *pAttr = 
03238             (RadialFillAttribute *) CurrentAttrs[ATTR_FILLGEOMETRY].pAttr;
03239         pAttr->MakeCircular();
03240     }
03241 
03242     return Success;
03243 }
03244 
03245 /********************************************************************************************
03246 
03247 >   BOOL Filter::SetRadialFill(DocColour StartColour, DocColour EndColour,
03248                                DocCoord StartPoint, 
03249                                DocCoord EndPoint1, DocCoord EndPoint2)
03250 
03251     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03252     Created:    13/04/94
03253     Inputs:     StartColour, EndColour - colours to fade between.
03254                 StartPoint, EndPoint1, EndPoint2 - the points defining the elliptical
03255                                                    radial fill.
03256     Returns:    TRUE if the attribute was changed ok; 
03257                 FALSE otherwise.
03258     Purpose:    Updates the current attribute for gradfill colour to reflect the value passed 
03259                 in.
03260     Errors:     Out of memory.
03261     SeeAlso:    Filter; Filter::Init; GradFillAttribute
03262 
03263 ********************************************************************************************/
03264 
03265 BOOL Filter::SetRadialFill(DocColour &StartColour, DocColour &EndColour,
03266                            DocCoord StartPoint, 
03267                            DocCoord EndPoint1, DocCoord EndPoint2)
03268 {
03269     // Sanity check
03270     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
03271 
03272     // Find out which fill attribute to change
03273     AttributeEntry *pEntry;
03274     if (FillAttr.pAttr == NULL)
03275         // No 'saved' fill attribute, so just update the normal one.
03276         pEntry = &CurrentAttrs[ATTR_FILLGEOMETRY];
03277     else
03278         // Update the saved fill attribute.
03279         pEntry = &FillAttr;
03280 
03281     // If we haven't changed this attribute yet, then make a new attribute object for
03282     // our own personal use...
03283     if (!pEntry->Temp)
03284     {
03285         // Make the correct attribute value and install it as the current one.
03286         pEntry->pAttr = new RadialFillAttribute;
03287         if (pEntry->pAttr == NULL)
03288             return FALSE;
03289         pEntry->Temp = TRUE;
03290     }
03291     else
03292     {
03293         // Ensure we have the correct attribute
03294         if (!IS_A(pEntry->pAttr, RadialFillAttribute))
03295         {
03296             // Wrong type - delete it and get the right type of attribute value.
03297             delete pEntry->pAttr;
03298             pEntry->pAttr = new RadialFillAttribute;
03299             if (pEntry->pAttr == NULL)
03300                 return FALSE;
03301         }
03302     }
03303 
03304     // We've got an attribute - change it.
03305     RadialFillAttribute *pAttr = (RadialFillAttribute *) pEntry->pAttr;
03306 
03307     // Copy field values.
03308     pAttr->SetStartColour(&StartColour);
03309     pAttr->SetEndColour(&EndColour);
03310     pAttr->SetStartPoint(&StartPoint);
03311     pAttr->SetEndPoint(&EndPoint1);
03312     pAttr->SetEndPoint2(&EndPoint2);
03313 
03314     // Make sure it's elliptical
03315     pAttr->MakeElliptical();
03316 
03317     // All worked ok.
03318     return TRUE;
03319 }
03320 
03321 /********************************************************************************************
03322 
03323 >   BOOL Filter::SetSquareFill(DocColour StartColour, DocColour EndColour,
03324                                DocCoord StartPoint, 
03325                                DocCoord EndPoint1, DocCoord EndPoint2)
03326 
03327     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03328     Created:    27/08/94
03329     Inputs:     StartColour, EndColour - colours to fade between.
03330                 StartPoint, EndPoint1, EndPoint2 - the points defining the elliptical
03331                                                    radial fill.
03332     Returns:    TRUE if the attribute was changed ok; 
03333                 FALSE otherwise.
03334     Purpose:    Updates the current attribute for gradfill colour to reflect the value passed 
03335                 in.
03336 
03337                 FN copied and modified by Ben.
03338     Errors:     Out of memory.
03339     SeeAlso:    Filter; Filter::Init; GradFillAttribute
03340 
03341 ********************************************************************************************/
03342 
03343 BOOL Filter::SetSquareFill(DocColour &StartColour, DocColour &EndColour,
03344                            DocCoord StartPoint, 
03345                            DocCoord EndPoint1, DocCoord EndPoint2)
03346 {
03347     // Sanity check
03348     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
03349 
03350     // Find out which fill attribute to change
03351     AttributeEntry *pEntry;
03352     if (FillAttr.pAttr == NULL)
03353         // No 'saved' fill attribute, so just update the normal one.
03354         pEntry = &CurrentAttrs[ATTR_FILLGEOMETRY];
03355     else
03356         // Update the saved fill attribute.
03357         pEntry = &FillAttr;
03358 
03359     // If we haven't changed this attribute yet, then make a new attribute object for
03360     // our own personal use...
03361     if (!pEntry->Temp)
03362     {
03363         // Make the correct attribute value and install it as the current one.
03364         pEntry->pAttr = new SquareFillAttribute;
03365         if (pEntry->pAttr == NULL)
03366             return FALSE;
03367         pEntry->Temp = TRUE;
03368     }
03369     else
03370     {
03371         // Ensure we have the correct attribute
03372         if (!IS_A(pEntry->pAttr, SquareFillAttribute))
03373         {
03374             // Wrong type - delete it and get the right type of attribute value.
03375             delete pEntry->pAttr;
03376             pEntry->pAttr = new SquareFillAttribute;
03377             if (pEntry->pAttr == NULL)
03378                 return FALSE;
03379         }
03380     }
03381 
03382     // We've got an attribute - change it.
03383     SquareFillAttribute *pAttr = (SquareFillAttribute *) pEntry->pAttr;
03384 
03385     // Copy field values.
03386     pAttr->SetStartColour(&StartColour);
03387     pAttr->SetEndColour(&EndColour);
03388     pAttr->SetStartPoint(&StartPoint);
03389     pAttr->SetEndPoint(&EndPoint1);
03390     pAttr->SetEndPoint2(&EndPoint2);
03391 
03392     // All worked ok.
03393     return TRUE;
03394 }
03395 
03396 /********************************************************************************************
03397 
03398 >   BOOL Filter::SetConicalFill(DocColour StartColour, DocColour EndColour,
03399                                DocCoord StartPoint, DocCoord EndPoint)
03400 
03401     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03402     Created:    13/04/94
03403     Inputs:     StartColour, EndColour, StartPoint, EndPoint - see GradFillAttribute.
03404     Returns:    TRUE if the attribute was changed ok; 
03405                 FALSE otherwise.
03406     Purpose:    Updates the current attribute for gradfill colour to reflect the value passed 
03407                 in.
03408     Errors:     Out of memory.
03409     SeeAlso:    Filter; Filter::Init; GradFillAttribute
03410 
03411 ********************************************************************************************/
03412 
03413 BOOL Filter::SetConicalFill(DocColour &StartColour, DocColour &EndColour,
03414                            DocCoord StartPoint, DocCoord EndPoint)
03415 {
03416     // Sanity check
03417     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
03418 
03419     // Find out which fill attribute to change
03420     AttributeEntry *pEntry;
03421     if (FillAttr.pAttr == NULL)
03422         // No 'saved' fill attribute, so just update the normal one.
03423         pEntry = &CurrentAttrs[ATTR_FILLGEOMETRY];
03424     else
03425         // Update the saved fill attribute.
03426         pEntry = &FillAttr;
03427 
03428     // If we haven't changed this attribute yet, then make a new attribute object for
03429     // our own personal use...
03430     if (!pEntry->Temp)
03431     {
03432         // Make the correct attribute value and install it as the current one.
03433         pEntry->pAttr = new ConicalFillAttribute;
03434         if (pEntry->pAttr == NULL)
03435             return FALSE;
03436         pEntry->Temp = TRUE;
03437     }
03438     else
03439     {
03440         // Ensure we have the correct attribute
03441         if (!IS_A(pEntry->pAttr, ConicalFillAttribute))
03442         {
03443             // Wrong type - delete it and get the right type of attribute value.
03444             delete pEntry->pAttr;
03445             pEntry->pAttr = new ConicalFillAttribute;
03446             if (pEntry->pAttr == NULL)
03447                 return FALSE;
03448         }
03449     }
03450 
03451     // We've got an attribute - change it.
03452     ConicalFillAttribute *pAttr = (ConicalFillAttribute *) pEntry->pAttr;
03453 
03454     // Copy field values.
03455     pAttr->SetStartColour(&StartColour);
03456     pAttr->SetEndColour(&EndColour);
03457     pAttr->SetStartPoint(&StartPoint);
03458     pAttr->SetEndPoint(&EndPoint);
03459 
03460     // All worked ok.
03461     return TRUE;
03462 }
03463 
03464 /********************************************************************************************
03465 
03466 >   BOOL Filter::SetBitmapFill(KernelBitmap *pBitmap,
03467                            DocCoord StartPoint, DocCoord EndPoint, DocCoord EndPoint2,
03468                            DocColour *StartColour = 0, DocColour *EndColour = 0)
03469 
03470     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03471     Created:    23/08/94
03472     Inputs:     pBitmap - pointer to the bitmap object to fill with.
03473                 StartPoint, EndPoint, EndPoint2 - see BitmapFillAttribute.
03474     Returns:    TRUE if the attribute was changed ok; 
03475                 FALSE otherwise.
03476     Purpose:    Updates the current attribute for fill colour to reflect the value passed 
03477                 in.
03478     Errors:     Out of memory.
03479     SeeAlso:    Filter; Filter::Init; BitmapFillAttribute
03480 
03481 ********************************************************************************************/
03482 
03483 BOOL Filter::SetBitmapFill(KernelBitmap *pBitmap,
03484                            DocCoord StartPoint, DocCoord EndPoint, DocCoord EndPoint2,
03485                            DocColour *StartColour, DocColour *EndColour)
03486 {
03487     // Sanity check
03488     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
03489     ERROR3IF((StartColour != 0 && EndColour == 0) || (StartColour == 0 && EndColour != 0),
03490             "SetBitmapFill, StartColour and EndColour have a different status");
03491 
03492     // Find out which fill attribute to change
03493     AttributeEntry *pEntry;
03494     if (FillAttr.pAttr == NULL)
03495         // No 'saved' fill attribute, so just update the normal one.
03496         pEntry = &CurrentAttrs[ATTR_FILLGEOMETRY];
03497     else
03498         // Update the saved fill attribute.
03499         pEntry = &FillAttr;
03500 
03501     // If we haven't changed this attribute yet, then make a new attribute object for
03502     // our own personal use...
03503     if (!pEntry->Temp)
03504     {
03505         // Make the correct attribute value and install it as the current one.
03506         pEntry->pAttr = new BitmapFillAttribute;
03507         if (pEntry->pAttr == NULL)
03508             return FALSE;
03509         pEntry->Temp = TRUE;
03510     }
03511     else
03512     {
03513         // Ensure we have the correct attribute
03514         if (!IS_A(pEntry->pAttr, BitmapFillAttribute))
03515         {
03516             // Wrong type - delete it and get the right type of attribute value.
03517             delete pEntry->pAttr;
03518             pEntry->pAttr = new BitmapFillAttribute;
03519             if (pEntry->pAttr == NULL)
03520                 return FALSE;
03521         }
03522     }
03523 
03524     // We've got an attribute - change it.
03525     BitmapFillAttribute *pAttr = (BitmapFillAttribute *) pEntry->pAttr;
03526 
03527     // Copy field values.
03528     pAttr->SetStartColour(StartColour);
03529     pAttr->SetEndColour(EndColour);
03530 
03531     pAttr->SetStartPoint(&StartPoint);
03532     pAttr->SetEndPoint(&EndPoint);
03533     pAttr->SetEndPoint2(&EndPoint2);
03534 
03535     GetDocument()->SetCurrent();
03536 //  pAttr->AttachBitmap(pBitmap);
03537     pAttr->GetBitmapRef()->Attach(pBitmap, GetDocument());
03538 
03539     if (pAttr->GetBitmap() != pBitmap)
03540     {
03541         // It didn't use the bitmap we gave it, so we can delete it
03542         delete pBitmap;
03543     }
03544 
03545     // All worked ok.
03546     return TRUE;
03547 }
03548 
03549 
03550 /********************************************************************************************
03551 
03552 >   BOOL Filter::SetFractalFill(DocColour &StartColour, DocColour &EndColour,
03553                             DocCoord StartPoint, DocCoord EndPoint1, DocCoord EndPoint2,
03554                             INT32 Seed, double Graininess, double Gravity, double Squash, 
03555                             UINT32 DPI, BOOL Tileable)
03556 
03557     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03558     Created:    08/11/94
03559     Inputs:     StartColour, EndColour - the colours of the fill
03560                 StartPoint, EndPoint1, EndPoint2 - co-ordinates of the fill mesh
03561                 Seed, Graininess, Gravity, Squash - strange fractal parameters
03562                 DPI - the resolution of the fractal bitmap (dots per inch).
03563                 Tileable - whether the fractal bitmap is tileable or not (ask Alex).
03564     Returns:    TRUE if the attribute was changed ok; 
03565                 FALSE otherwise => ERROR1
03566     Purpose:    Updates the current attribute for colour fill geometry to be a fractal fill
03567                 using the values passed in.
03568     Errors:     Out of memory => ERROR1
03569     SeeAlso:    Filter; Filter::Init; FractalFillAttribute
03570 
03571 ********************************************************************************************/
03572 
03573 BOOL Filter::SetFractalFill(DocColour &StartColour, DocColour &EndColour,
03574                             DocCoord StartPoint, DocCoord EndPoint1, DocCoord EndPoint2,
03575                             INT32 Seed, double Graininess, double Gravity, double Squash, 
03576                             UINT32 DPI, BOOL Tileable)
03577 {
03578     // Sanity check
03579     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
03580 
03581     // Find out which fill attribute to change
03582     AttributeEntry *pEntry;
03583     if (FillAttr.pAttr == NULL)
03584         // No 'saved' fill attribute, so just update the normal one.
03585         pEntry = &CurrentAttrs[ATTR_FILLGEOMETRY];
03586     else
03587         // Update the saved fill attribute.
03588         pEntry = &FillAttr;
03589 
03590     // If we haven't changed this attribute yet, then make a new attribute object for
03591     // our own personal use...
03592     if (!pEntry->Temp)
03593     {
03594         // Make the correct attribute value and install it as the current one.
03595         pEntry->pAttr = new FractalFillAttribute;
03596         if (pEntry->pAttr == NULL)
03597             return FALSE;
03598         pEntry->Temp = TRUE;
03599     }
03600     else
03601     {
03602         // Ensure we have the correct attribute
03603         if (!IS_A(pEntry->pAttr, FractalFillAttribute))
03604         {
03605             // Wrong type - delete it and get the right type of attribute value.
03606             delete pEntry->pAttr;
03607             pEntry->pAttr = new FractalFillAttribute;
03608             if (pEntry->pAttr == NULL)
03609                 return FALSE;
03610         }
03611     }
03612 
03613     // We've got an attribute - change it.
03614     FractalFillAttribute *pAttr = (FractalFillAttribute *) pEntry->pAttr;
03615 
03616     // Copy field values.
03617     pAttr->SetStartColour(&StartColour);
03618     pAttr->SetEndColour(&EndColour);
03619     pAttr->SetStartPoint(&StartPoint);
03620     pAttr->SetEndPoint(&EndPoint1);
03621     pAttr->SetEndPoint2(&EndPoint2);
03622     pAttr->SetSeed(Seed);
03623     pAttr->SetGraininess(Graininess);
03624     pAttr->SetGravity(Gravity);
03625     pAttr->SetSquash(Squash);
03626     pAttr->SetTileable(Tileable);
03627 
03628     // Actually create the fractal bitmap
03629     pAttr->SetFractalDPI(DPI);
03630     pAttr->RecalcFractal();
03631 
03632     // All worked ok.
03633     return TRUE;
03634 }
03635 
03636 
03637 
03639 // TRANSPARENT FILLS //
03641 
03642 /********************************************************************************************
03643 
03644 >   BOOL Filter::SetNoTranspFill()
03645 
03646     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03647     Created:    10/10/94
03648     Returns:    TRUE if the fill attribute is set ok;
03649                 FALSE if not (e.g. out of memory)
03650     Purpose:    Set the current transparency fill for this import operation to be none,
03651                 i.e. there is no transparency.
03652     Errors:     Out of memory
03653     SeeAlso:    Filter; Filter::Init; Filter::SetFlatTranspFill; TranspFillAttribute
03654     Note:       This also (via SetFlatTranspFill) set the new painting mode attribute as well
03655 
03656 ********************************************************************************************/
03657 
03658 BOOL Filter::SetNoTranspFill()
03659 {
03660     // At present, we use a flat transparent fill with 0% transparency and T type 1 for
03661     // 'no transparency'.
03662     return SetFlatTranspFill(1, 0);
03663 }
03664 
03665 /********************************************************************************************
03666 
03667 >   BOOL Filter::SetFlatTranspFill(UINT32 TranspType, UINT32 Transp)
03668 
03669     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03670     Created:    10/10/94
03671     Inputs:     TranspType - the type of transparency (1-3)
03672                 Transp - the 8 bit transparency value (0-255)
03673     Returns:    TRUE if the fill attribute is set ok;
03674                 FALSE if not (e.g. out of memory)
03675     Purpose:    Set the current transparency fill for this import operation to be a flat
03676                 transparency value.
03677     Errors:     Out of memory
03678     SeeAlso:    Filter; Filter::Init; TranspFillAttribute
03679 
03680 ********************************************************************************************/
03681 
03682 BOOL Filter::SetFlatTranspFill(UINT32 TranspType, UINT32 Transp)
03683 {
03684     // Sanity check
03685     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
03686 
03687     // If we haven't changed this attribute yet, then make a new attribute object for
03688     // our own personal use...
03689     if (!CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].Temp)
03690     {
03691         // Make the correct attribute value and install it as the current one.
03692         CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr = new FlatTranspFillAttribute;
03693         if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr == NULL)
03694             return FALSE;
03695         CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].Temp = TRUE;
03696     }
03697     else
03698     {
03699         // Ensure we have the correct attribute
03700         if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr->GetRuntimeClass() != 
03701             CC_RUNTIME_CLASS(FlatTranspFillAttribute))
03702         {
03703             // Wrong type - delete it and get the right type of attribute value.
03704             delete CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr;
03705             CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr = new FlatTranspFillAttribute;
03706             if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr == NULL)
03707                 return FALSE;
03708         }
03709     }
03710 
03711     // We've got an attribute - change it.
03712     FlatTranspFillAttribute *pAttr = 
03713         (FlatTranspFillAttribute *) CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr;
03714 
03715     // Copy field values.
03716     pAttr->SetTranspType(TranspType);
03717     pAttr->SetStartTransp(&Transp);
03718 
03719     // All worked ok.
03720     return TRUE;
03721 }
03722 
03723 /********************************************************************************************
03724 
03725 >   BOOL Filter::SetLinearTranspFill(UINT32 TranspType, UINT32 StartTransp, UINT32 EndTransp,
03726                                      DocCoord StartPoint, DocCoord EndPoint,
03727                                      DocCoord *EndPoint2 = NULL)
03728 
03729     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03730     Created:    13/04/94
03731     Inputs:     TranspType - the type of transparency (1-3)
03732                 StartTransp - the 8 bit start transparency value (0-255)
03733                 EndTransp - the 8 bit end transparency value (0-255)
03734                 StartPoint, EndPoint - the start and end-points of the linear fill.
03735     Returns:    TRUE if the attribute was changed ok; 
03736                 FALSE otherwise.
03737     Purpose:    Updates the current attribute for transparency fill to be a linear
03738                 transparent fill as specified by the values passed in.
03739     Errors:     Out of memory.
03740     SeeAlso:    Filter; Filter::Init; TranspFillAttribute
03741 
03742 ********************************************************************************************/
03743 
03744 BOOL Filter::SetLinearTranspFill(UINT32 TranspType, UINT32 StartTransp, UINT32 EndTransp,
03745                                  DocCoord StartPoint, DocCoord EndPoint,
03746                                  DocCoord *EndPoint2)
03747 {
03748     // Sanity check
03749     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
03750 
03751     // If we haven't changed this attribute yet, then make a new attribute object for
03752     // our own personal use...
03753     if (!CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].Temp)
03754     {
03755         // Make the correct attribute value and install it as the current one.
03756         CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr = new LinearTranspFillAttribute;
03757         if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr == NULL)
03758             return FALSE;
03759         CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].Temp = TRUE;
03760     }
03761     else
03762     {
03763         // Ensure we have the correct attribute
03764         if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr->GetRuntimeClass() != 
03765             CC_RUNTIME_CLASS(LinearTranspFillAttribute))
03766         {
03767             // Wrong type - delete it and get the right type of attribute value.
03768             delete CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr;
03769             CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr = new LinearTranspFillAttribute;
03770             if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr == NULL)
03771                 return FALSE;
03772         }
03773     }
03774 
03775     // We've got an attribute - change it.
03776     LinearTranspFillAttribute *pAttr = 
03777         (LinearTranspFillAttribute *) CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr;
03778 
03779     // Copy field values.
03780     pAttr->SetTranspType(TranspType);           // waz 3362
03781     pAttr->SetStartTransp(&StartTransp);
03782     pAttr->SetEndTransp(&EndTransp);
03783     pAttr->SetStartPoint(&StartPoint);
03784     pAttr->SetEndPoint(&EndPoint);
03785     pAttr->SetEndPoint2(EndPoint2);
03786 
03787     // All worked ok.
03788     return TRUE;
03789 }
03790 
03791 /********************************************************************************************
03792 
03793 >   BOOL Filter::SetRadialTranspFill(UINT32 TranspType, UINT32 StartTransp, UINT32 EndTransp,
03794                                      DocCoord StartPoint, DocCoord EndPoint)
03795 
03796     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03797     Created:    13/04/94
03798     Inputs:     TranspType - the type of transparency (1-3)
03799                 StartTransp - the 8 bit start transparency value (0-255)
03800                 EndTransp - the 8 bit end transparency value (0-255)
03801                 StartPoint - the centre of the radial fill.
03802                 EndPoint - a point on the edge of the circle defining the radial fill.
03803     Returns:    TRUE if the attribute was changed ok; 
03804                 FALSE otherwise.
03805     Purpose:    Updates the current attribute for transparency fill to be a circular
03806                 transparent fill as specified by the values passed in.
03807     Errors:     Out of memory.
03808     SeeAlso:    Filter; Filter::Init; GradFillAttribute
03809 
03810 ********************************************************************************************/
03811 
03812 BOOL Filter::SetRadialTranspFill(UINT32 TranspType, UINT32 StartTransp, UINT32 EndTransp,
03813                            DocCoord StartPoint, DocCoord EndPoint)
03814 {
03815     // Call the more general function...
03816     BOOL Success = SetRadialTranspFill(TranspType, StartTransp, EndTransp, 
03817                                        StartPoint, EndPoint, EndPoint);
03818 
03819     // Set the new attribute to be a circular one, if it worked
03820     if (Success)
03821     {
03822         RadialTranspFillAttribute *pAttr = 
03823             (RadialTranspFillAttribute *) CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr;
03824         pAttr->MakeCircular();
03825     }
03826 
03827     return Success;
03828 }
03829 
03830 /********************************************************************************************
03831 
03832 >   BOOL Filter::SetRadialTranspFill(UINT32 TranspType, UINT32 StartTransp, UINT32 EndTransp,
03833                                      DocCoord StartPoint, 
03834                                      DocCoord EndPoint1, DocCoord EndPoint2)
03835 
03836     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03837     Created:    13/04/94
03838     Inputs:     TranspType - the type of transparency (1-3)
03839                 StartTransp - the 8 bit start transparency value (0-255)
03840                 EndTransp - the 8 bit end transparency value (0-255)
03841                 StartPoint, EndPoint, EndPoint2 - the points defining the elliptical fill.
03842     Returns:    TRUE if the attribute was changed ok; 
03843                 FALSE otherwise.
03844     Purpose:    Updates the current attribute for transparency fill to be an elliptical
03845                 transparent fill as specified by the values passed in.
03846     Errors:     Out of memory.
03847     SeeAlso:    Filter; Filter::Init; GradFillAttribute
03848 
03849 ********************************************************************************************/
03850 
03851 BOOL Filter::SetRadialTranspFill(UINT32 TranspType, UINT32 StartTransp, UINT32 EndTransp,
03852                                  DocCoord StartPoint, 
03853                                  DocCoord EndPoint1, DocCoord EndPoint2)
03854 {
03855     // Sanity check
03856     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
03857 
03858     // If we haven't changed this attribute yet, then make a new attribute object for
03859     // our own personal use...
03860     if (!CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].Temp)
03861     {
03862         // Make the correct attribute value and install it as the current one.
03863         CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr = new RadialTranspFillAttribute;
03864         if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr == NULL)
03865             return FALSE;
03866         CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].Temp = TRUE;
03867     }
03868     else
03869     {
03870         // Ensure we have the correct attribute
03871         if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr->GetRuntimeClass() != 
03872             CC_RUNTIME_CLASS(RadialTranspFillAttribute))
03873         {
03874             // Wrong type - delete it and get the right type of attribute value.
03875             delete CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr;
03876             CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr = new RadialTranspFillAttribute;
03877             if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr == NULL)
03878                 return FALSE;
03879         }
03880     }
03881 
03882     // We've got an attribute - change it.
03883     RadialTranspFillAttribute *pAttr = 
03884         (RadialTranspFillAttribute *) CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr;
03885 
03886     // Copy field values.
03887     pAttr->SetTranspType(TranspType);           // waz 3469
03888     pAttr->SetStartTransp(&StartTransp);
03889     pAttr->SetEndTransp(&EndTransp);
03890     pAttr->SetStartPoint(&StartPoint);
03891     pAttr->SetEndPoint(&EndPoint1);
03892     pAttr->SetEndPoint2(&EndPoint2);
03893 
03894     // Make sure it's elliptical
03895     pAttr->MakeElliptical();
03896 
03897     // All worked ok.
03898     return TRUE;
03899 }
03900 
03901 /********************************************************************************************
03902 
03903 >   BOOL Filter::SetConicalTranspFill(UINT32 TranspType, UINT32 StartTransp, UINT32 EndTransp,
03904                                       DocCoord StartPoint, DocCoord EndPoint)
03905 
03906     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03907     Created:    13/04/94
03908     Inputs:     TranspType - the type of transparency (1-3)
03909                 StartTransp - the 8 bit start transparency value (0-255)
03910                 EndTransp - the 8 bit end transparency value (0-255)
03911                 StartPoint, EndPoint - the points defining the conical fill.
03912     Returns:    TRUE if the attribute was changed ok; 
03913                 FALSE otherwise.
03914     Purpose:    Updates the current attribute for gradfill colour to reflect the value passed 
03915                 in.
03916     Errors:     Out of memory.
03917     SeeAlso:    Filter; Filter::Init; GradFillAttribute
03918 
03919 ********************************************************************************************/
03920 
03921 BOOL Filter::SetConicalTranspFill(UINT32 TranspType, UINT32 StartTransp, UINT32 EndTransp,
03922                                   DocCoord StartPoint, DocCoord EndPoint)
03923 {
03924     // Sanity check
03925     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
03926 
03927     // If we haven't changed this attribute yet, then make a new attribute object for
03928     // our own personal use...
03929     if (!CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].Temp)
03930     {
03931         // Make the correct attribute value and install it as the current one.
03932         CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr = new ConicalTranspFillAttribute;
03933         if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr == NULL)
03934             return FALSE;
03935         CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].Temp = TRUE;
03936     }
03937     else
03938     {
03939         // Ensure we have the correct attribute
03940         if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr->GetRuntimeClass() != 
03941             CC_RUNTIME_CLASS(ConicalTranspFillAttribute))
03942         {
03943             // Wrong type - delete it and get the right type of attribute value.
03944             delete CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr;
03945             CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr = new ConicalTranspFillAttribute;
03946             if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr == NULL)
03947                 return FALSE;
03948         }
03949     }
03950 
03951     // We've got an attribute - change it.
03952     ConicalTranspFillAttribute *pAttr = 
03953         (ConicalTranspFillAttribute *) CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr;
03954 
03955     // Copy field values.
03956     pAttr->SetTranspType(TranspType);           // waz 3538
03957     pAttr->SetStartTransp(&StartTransp);
03958     pAttr->SetEndTransp(&EndTransp);
03959     pAttr->SetStartPoint(&StartPoint);
03960     pAttr->SetEndPoint(&EndPoint);
03961 
03962     // All worked ok.
03963     return TRUE;
03964 }
03965 
03966 /********************************************************************************************
03967 
03968 >   BOOL Filter::SetBitmapTranspFill(UINT32 TranspType, KernelBitmap *pBitmap,
03969                                      DocCoord StartPoint, 
03970                                      DocCoord EndPoint, DocCoord EndPoint2,
03971                                      UINT32 StartTransp = 0, UINT32 EndTransp = 255)
03972 
03973     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
03974     Created:    23/08/94
03975     Inputs:     TranspType - the type of transparency (1-3)
03976                 pBitmap - pointer to the bitmap object to fill with.
03977                 StartPoint, EndPoint, EndPoint2 - see BitmapTranspFillAttribute.
03978     Returns:    TRUE if the attribute was changed ok; 
03979                 FALSE otherwise.
03980     Purpose:    Updates the current attribute for fill colour to reflect the value passed 
03981                 in.
03982     Errors:     Out of memory.
03983     SeeAlso:    Filter; Filter::Init; BitmapFillAttribute
03984 
03985 ********************************************************************************************/
03986 
03987 BOOL Filter::SetBitmapTranspFill(UINT32 TranspType, KernelBitmap *pBitmap,
03988                                  DocCoord StartPoint, DocCoord EndPoint, DocCoord EndPoint2,
03989                                  UINT32 StartTransp, UINT32 EndTransp)
03990 {
03991     // Sanity check
03992     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
03993 
03994     // If we haven't changed this attribute yet, then make a new attribute object for
03995     // our own personal use...
03996     if (!CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].Temp)
03997     {
03998         // Make the correct attribute value and install it as the current one.
03999         CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr = new BitmapTranspFillAttribute;
04000         if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr == NULL)
04001             return FALSE;
04002         CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].Temp = TRUE;
04003     }
04004     else
04005     {
04006         // Ensure we have the correct attribute
04007         if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr->GetRuntimeClass() != 
04008             CC_RUNTIME_CLASS(BitmapTranspFillAttribute))
04009         {
04010             // Wrong type - delete it and get the right type of attribute value.
04011             delete CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr;
04012             CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr = new BitmapTranspFillAttribute;
04013             if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr == NULL)
04014                 return FALSE;
04015         }
04016     }
04017 
04018     // We've got an attribute - change it.
04019     BitmapTranspFillAttribute *pAttr = 
04020         (BitmapTranspFillAttribute *) CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr;
04021 
04022     // Copy field values.
04023     pAttr->SetTranspType(TranspType);           // waz 3606
04024     pAttr->SetStartTransp(&StartTransp);
04025     pAttr->SetEndTransp(&EndTransp);
04026 
04027     pAttr->SetStartPoint(&StartPoint);
04028     pAttr->SetEndPoint(&EndPoint);
04029     pAttr->SetEndPoint2(&EndPoint2);
04030 
04031     GetDocument()->SetCurrent();
04032 //  pAttr->AttachBitmap(pBitmap);
04033     pAttr->GetBitmapRef()->Attach(pBitmap, GetDocument());
04034 
04035     if (pAttr->GetBitmap() != pBitmap)
04036     {
04037         // It didn't use the bitmap we gave it, so we can delete it
04038         delete pBitmap;
04039     }
04040 
04041     // All worked ok.
04042     return TRUE;
04043 }
04044 
04045 /********************************************************************************************
04046 
04047 >   BOOL Filter::SetFractalTranspFill(UINT32 TranspType,
04048                             DocCoord StartPoint, DocCoord EndPoint1, DocCoord EndPoint2,
04049                             INT32 Seed, double Graininess, double Gravity, double Squash, 
04050                             UINT32 DPI, BOOL Tileable,
04051                             UINT32 StartTransp = 0, UINT32 EndTransp = 255)
04052 
04053     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
04054     Created:    08/11/94
04055     Inputs:     TranspType - the type of transparency (1-3)
04056                 StartPoint, EndPoint1, EndPoint2 - co-ordinates of the fill mesh
04057                 Seed, Graininess, Gravity, Squash - strange fractal parameters
04058                 DPI - the resolution of the fractal bitmap (dots per inch).
04059                 Tileable - whether the fractal bitmap is tileable or not (ask Alex).
04060     Returns:    TRUE if the attribute was changed ok; 
04061                 FALSE otherwise => ERROR1
04062     Purpose:    Updates the current attribute for colour fill geometry to be a fractal fill
04063                 using the values passed in.
04064     Errors:     Out of memory => ERROR1
04065     SeeAlso:    Filter; Filter::Init; FractalFillAttribute
04066 
04067 ********************************************************************************************/
04068 
04069 BOOL Filter::SetFractalTranspFill(UINT32 TranspType,
04070                                   DocCoord StartPoint, DocCoord EndPoint1, DocCoord EndPoint2,
04071                                   INT32 Seed, double Graininess, double Gravity, double Squash, 
04072                                   UINT32 DPI, BOOL Tileable,
04073                                   UINT32 StartTransp, UINT32 EndTransp)
04074 {
04075     // Sanity check
04076     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
04077 
04078     // If we haven't changed this attribute yet, then make a new attribute object for
04079     // our own personal use...
04080     if (!CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].Temp)
04081     {
04082         // Make the correct attribute value and install it as the current one.
04083         CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr = new FractalTranspFillAttribute;
04084         if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr == NULL)
04085             return FALSE;
04086         CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].Temp = TRUE;
04087     }
04088     else
04089     {
04090         // Ensure we have the correct attribute
04091         if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr->GetRuntimeClass() != 
04092             CC_RUNTIME_CLASS(FractalTranspFillAttribute))
04093         {
04094             // Wrong type - delete it and get the right type of attribute value.
04095             delete CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr;
04096             CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr = new FractalTranspFillAttribute;
04097             if (CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr == NULL)
04098                 return FALSE;
04099         }
04100     }
04101 
04102     // We've got an attribute - change it.
04103     FractalTranspFillAttribute *pAttr = 
04104         (FractalTranspFillAttribute *) CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr;
04105 
04106     // Copy field values.
04107     pAttr->SetTranspType(TranspType);           // waz 3690
04108     pAttr->SetStartTransp(&StartTransp);
04109     pAttr->SetEndTransp(&EndTransp);
04110 
04111     pAttr->SetStartPoint(&StartPoint);
04112     pAttr->SetEndPoint(&EndPoint1);
04113     pAttr->SetEndPoint2(&EndPoint2);
04114 
04115     pAttr->SetSeed(Seed);
04116     pAttr->SetGraininess(Graininess);
04117     pAttr->SetGravity(Gravity);
04118     pAttr->SetSquash(Squash);
04119     pAttr->SetTileable(Tileable);
04120 
04121     // Actually create the fractal bitmap
04122     pAttr->SetFractalDPI(DPI);
04123     pAttr->RecalcFractal();
04124 
04125     // All worked ok.
04126     return TRUE;
04127 }
04128 
04129 
04130 
04131 BOOL Filter::SetFadeFillEffect()
04132 {
04133     // Sanity check
04134     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
04135 
04136     // If we haven't changed this attribute yet, then make a new attribute object for
04137     // our own personal use...
04138     if (!CurrentAttrs[ATTR_FILLEFFECT].Temp)
04139     {
04140         // Make the correct attribute value and install it as the current one.
04141         CurrentAttrs[ATTR_FILLEFFECT].pAttr = new FillEffectFadeAttribute;
04142         if (CurrentAttrs[ATTR_FILLEFFECT].pAttr == NULL)
04143             return FALSE;
04144         CurrentAttrs[ATTR_FILLEFFECT].Temp = TRUE;
04145     }
04146     else
04147     {
04148         // Ensure we have the correct attribute
04149         if (!IS_A(CurrentAttrs[ATTR_FILLEFFECT].pAttr, FillEffectFadeAttribute))
04150         {
04151             // Wrong type - delete it and get the right type of attribute value.
04152             delete CurrentAttrs[ATTR_FILLEFFECT].pAttr;
04153             CurrentAttrs[ATTR_FILLEFFECT].pAttr = new FillEffectFadeAttribute;
04154             if (CurrentAttrs[ATTR_FILLEFFECT].pAttr == NULL)
04155                 return FALSE;
04156         }
04157     }
04158 
04159     // All worked ok.
04160     return TRUE;
04161 }
04162 
04163 BOOL Filter::SetRainbowFillEffect()
04164 {
04165     // Sanity check
04166     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
04167 
04168     // If we haven't changed this attribute yet, then make a new attribute object for
04169     // our own personal use...
04170     if (!CurrentAttrs[ATTR_FILLEFFECT].Temp)
04171     {
04172         // Make the correct attribute value and install it as the current one.
04173         CurrentAttrs[ATTR_FILLEFFECT].pAttr = new FillEffectRainbowAttribute;
04174         if (CurrentAttrs[ATTR_FILLEFFECT].pAttr == NULL)
04175             return FALSE;
04176         CurrentAttrs[ATTR_FILLEFFECT].Temp = TRUE;
04177     }
04178     else
04179     {
04180         // Ensure we have the correct attribute
04181         if (!IS_A(CurrentAttrs[ATTR_FILLEFFECT].pAttr, FillEffectRainbowAttribute))
04182         {
04183             // Wrong type - delete it and get the right type of attribute value.
04184             delete CurrentAttrs[ATTR_FILLEFFECT].pAttr;
04185             CurrentAttrs[ATTR_FILLEFFECT].pAttr = new FillEffectRainbowAttribute;
04186             if (CurrentAttrs[ATTR_FILLEFFECT].pAttr == NULL)
04187                 return FALSE;
04188         }
04189     }
04190 
04191     // All worked ok.
04192     return TRUE;
04193 }
04194 
04195 BOOL Filter::SetAltRainbowFillEffect()
04196 {
04197     // Sanity check
04198     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
04199 
04200     // If we haven't changed this attribute yet, then make a new attribute object for
04201     // our own personal use...
04202     if (!CurrentAttrs[ATTR_FILLEFFECT].Temp)
04203     {
04204         // Make the correct attribute value and install it as the current one.
04205         CurrentAttrs[ATTR_FILLEFFECT].pAttr = new FillEffectAltRainbowAttribute;
04206         if (CurrentAttrs[ATTR_FILLEFFECT].pAttr == NULL)
04207             return FALSE;
04208         CurrentAttrs[ATTR_FILLEFFECT].Temp = TRUE;
04209     }
04210     else
04211     {
04212         // Ensure we have the correct attribute
04213         if (!IS_A(CurrentAttrs[ATTR_FILLEFFECT].pAttr, FillEffectAltRainbowAttribute))
04214         {
04215             // Wrong type - delete it and get the right type of attribute value.
04216             delete CurrentAttrs[ATTR_FILLEFFECT].pAttr;
04217             CurrentAttrs[ATTR_FILLEFFECT].pAttr = new FillEffectAltRainbowAttribute;
04218             if (CurrentAttrs[ATTR_FILLEFFECT].pAttr == NULL)
04219                 return FALSE;
04220         }
04221     }
04222 
04223     // All worked ok.
04224     return TRUE;
04225 }
04226 
04227 
04228 BOOL Filter::SetLinearFillMapping(INT32 Repeat)
04229 {
04230     // Sanity check
04231     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
04232     ERROR3IF((Repeat < 0) || (Repeat > 3),"Bad mapping repeat in SetLinearFillMapping()");
04233 
04234     // If we haven't changed this attribute yet, then make a new attribute object for
04235     // our own personal use...
04236     if (!CurrentAttrs[ATTR_FILLMAPPING].Temp)
04237     {
04238         // Make the correct attribute value and install it as the current one.
04239         CurrentAttrs[ATTR_FILLMAPPING].pAttr = new FillMappingLinearAttribute;
04240         if (CurrentAttrs[ATTR_FILLMAPPING].pAttr == NULL)
04241             return FALSE;
04242         CurrentAttrs[ATTR_FILLMAPPING].Temp = TRUE;
04243     }
04244     else
04245     {
04246         // Ensure we have the correct attribute
04247         if (!IS_A(CurrentAttrs[ATTR_FILLMAPPING].pAttr, FillMappingLinearAttribute))
04248         {
04249             // Wrong type - delete it and get the right type of attribute value.
04250             delete CurrentAttrs[ATTR_FILLMAPPING].pAttr;
04251             CurrentAttrs[ATTR_FILLMAPPING].pAttr = new FillMappingLinearAttribute;
04252             if (CurrentAttrs[ATTR_FILLMAPPING].pAttr == NULL)
04253                 return FALSE;
04254         }
04255     }
04256 
04257     // Set the repeat state
04258     FillMappingLinearAttribute *pAttr = 
04259             (FillMappingLinearAttribute *) CurrentAttrs[ATTR_FILLMAPPING].pAttr;
04260     pAttr->Repeat = Repeat;
04261 
04262 // *******************************************************************
04263 // Added by Will 12/2/95
04264 // Bitmap and Fractal tesselation does not appear to be being saved.
04265 // This code ensures that the repeat and tesselation values matach up.
04266     
04267     FillGeometryAttribute* pCurrentFill =
04268             (FillGeometryAttribute *) CurrentAttrs[ATTR_FILLGEOMETRY].pAttr;
04269 
04270     if (pCurrentFill != NULL)
04271         pCurrentFill->SetTesselation(Repeat);
04272 
04273 // *******************************************************************
04274 
04275     // All worked ok.
04276     return TRUE;
04277 }
04278 
04279 
04280 BOOL Filter::SetLinearTranspFillMapping(INT32 Repeat)
04281 {
04282     // Sanity check
04283     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
04284     ERROR3IF((Repeat < 0) || (Repeat > 3),"Bad mapping repeat in SetLinearTranspFillMapping()");
04285 
04286     // If we haven't changed this attribute yet, then make a new attribute object for
04287     // our own personal use...
04288     if (!CurrentAttrs[ATTR_TRANSPFILLMAPPING].Temp)
04289     {
04290         // Make the correct attribute value and install it as the current one.
04291         CurrentAttrs[ATTR_TRANSPFILLMAPPING].pAttr = new TranspFillMappingLinearAttribute;
04292         if (CurrentAttrs[ATTR_TRANSPFILLMAPPING].pAttr == NULL)
04293             return FALSE;
04294         CurrentAttrs[ATTR_TRANSPFILLMAPPING].Temp = TRUE;
04295     }
04296     else
04297     {
04298         // Ensure we have the correct attribute
04299         if (!IS_A(CurrentAttrs[ATTR_TRANSPFILLMAPPING].pAttr, TranspFillMappingLinearAttribute))
04300         {
04301             // Wrong type - delete it and get the right type of attribute value.
04302             delete CurrentAttrs[ATTR_TRANSPFILLMAPPING].pAttr;
04303             CurrentAttrs[ATTR_TRANSPFILLMAPPING].pAttr = new TranspFillMappingLinearAttribute;
04304             if (CurrentAttrs[ATTR_TRANSPFILLMAPPING].pAttr == NULL)
04305                 return FALSE;
04306         }
04307     }
04308 
04309     // Set the repeat state
04310     TranspFillMappingLinearAttribute *pAttr = 
04311             (TranspFillMappingLinearAttribute *) CurrentAttrs[ATTR_TRANSPFILLMAPPING].pAttr;
04312     pAttr->Repeat = Repeat;
04313 
04314 // *******************************************************************
04315 // Added by Will 12/2/95
04316 // Bitmap and Fractal tesselation does not appear to be being saved.
04317 // This code ensures that the repeat and tesselation values matach up.
04318     
04319     TranspFillAttribute* pCurrentFill =
04320             (TranspFillAttribute *) CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr;
04321 
04322     if (pCurrentFill != NULL)
04323         pCurrentFill->SetTesselation(Repeat);
04324 
04325 // *******************************************************************
04326 
04327     // All worked ok.
04328     return TRUE;
04329 }
04330 
04331 
04332 /********************************************************************************************
04333 
04334 >   BOOL Filter::SetWindingRule(WindingType WindingRule)
04335 
04336     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
04337     Created:    13/04/94
04338     Inputs:     WindingRule - the new winding rule to use.
04339     Returns:    TRUE if the attribute was changed ok; 
04340                 FALSE otherwise.
04341     Purpose:    Updates the current attribute for winding rule to reflect the value passed 
04342                 in.
04343     Errors:     Out of memory.
04344     SeeAlso:    Filter; Filter::Init; WindingType
04345 
04346 ********************************************************************************************/
04347 
04348 BOOL Filter::SetWindingRule(WindingType WindingRule)
04349 {
04350     // Sanity check
04351     ENSURE(CurrentAttrs != NULL, "No current attributes in filter!");
04352 
04353     // If we haven't changed this attribute yet, then make a new attribute object for
04354     // our own personal use...
04355     if (!CurrentAttrs[ATTR_WINDINGRULE].Temp)
04356     {
04357         // Make the correct attribute value and install it as the current one.
04358         CurrentAttrs[ATTR_WINDINGRULE].pAttr = new WindingRuleAttribute(WindingRule);
04359         if (CurrentAttrs[ATTR_WINDINGRULE].pAttr == NULL)
04360             return FALSE;
04361         CurrentAttrs[ATTR_WINDINGRULE].Temp = TRUE;
04362     }
04363     else
04364     {
04365         // We already have an attribute - just change it.
04366         WindingRuleAttribute *pAttr = 
04367             (WindingRuleAttribute *) CurrentAttrs[ATTR_WINDINGRULE].pAttr;
04368         pAttr->WindingRule = WindingRule;
04369     }
04370 
04371     // All worked ok.
04372     return TRUE;
04373 }
04374 
04375 /********************************************************************************************
04376 
04377 >   virtual BOOL Filter::GetDragAndDropTranslation(ImportPosition *pPos, DocRect BoundsRect, 
04378                                                    Coord* Offset)
04379 
04380     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
04381     Created:    04/10/94
04382     Inputs:     pSpread - the spread to check against.
04383                 BoundsRect - the bounding rectangle to check (in spread coordinates).
04384     Outputs:    Offset -
04385     Returns:    TRUE if the bounding rectangle is smaller than the spread => Offset now
04386                      contains the translation necessary to position the objects correctly.
04387                 FALSE if bounding rectangle is bigger than the spread, or pPos was NULL.
04388                       In either case, a FALSE return results in Offset containing (0,0).
04389     Purpose:    Given an drag'n'drop point (in pPos), calculate the translation necessary
04390                 to position the imported objects at this position on the spread.  It ensures
04391                 that bounding rectangles smaller than the spread are wholly contained within
04392                 the spread.  i.e. if you drag a file right to the edge of a spread, the 
04393                 translation will move it closer to the centre of the spread so that it is
04394                 wholly contained within the spread.
04395 
04396                 Used by the import filters for drag'n'drop to ensure that after the
04397                 imported objects are translated to the drop point, they are all still
04398                 on the spread.
04399                 Made virtual 20/5/97.
04400     SeeAlso:    Filter::DoImport
04401 
04402 ********************************************************************************************/
04403 
04404 BOOL Filter::GetDragAndDropTranslation(ImportPosition *pPos, DocRect BoundsRect, 
04405                                        Coord* Offset)
04406 {
04407 #if !defined(EXCLUDE_FROM_RALPH)
04408     // First check to se if we actually have a drag and drop point.
04409     if (pPos == NULL)
04410     {
04411         // No - set offset to 0 and return FALSE to indicate we can't cope with this.
04412         Offset->x = 0;
04413         Offset->y = 0;
04414         return FALSE;
04415     }
04416 
04417     // Get the spread's bounding rectangle and convert it to spread coords.
04418     DocRect SpreadRect = pPos->pSpread->GetPasteboardRect();
04419     pPos->pSpread->DocCoordToSpreadCoord(&SpreadRect);
04420 
04421 #if defined( DODGY_BITMAP_POS_CODE )
04422     // Now check that the bounding rectangle is small enough to fit on the spread...
04423     if ((BoundsRect.Width() > SpreadRect.Width()) ||
04424         (BoundsRect.Height() > SpreadRect.Height()))
04425     {
04426         // No - set offset to 0 and return FALSE to indicate we can't cope with this.
04427         Offset->x = 0;
04428         Offset->y = 0;
04429         return FALSE;
04430     }
04431 #endif
04432 
04433     // Bounding box should be centred on drop point
04434     DocCoord Centre;
04435     Centre.x = (BoundsRect.lo.x + BoundsRect.hi.x) / 2;
04436     Centre.y = (BoundsRect.lo.y + BoundsRect.hi.y) / 2;
04437 
04438     Offset->x = pPos->Position.x - Centre.x;
04439     Offset->y = pPos->Position.y - Centre.y;
04440 
04441     // Transform the bounding rect to see if it's off the spread.
04442     BoundsRect.Translate(Offset->x, Offset->y);
04443 
04444     // If it's off the spread - limit it to the edge of the spread:
04445 
04446     // (a) Horizontal adjustment
04447     if (BoundsRect.lo.x < SpreadRect.lo.x)
04448         Offset->x += (SpreadRect.lo.x - BoundsRect.lo.x);
04449     else if (BoundsRect.hi.x > SpreadRect.hi.x)
04450         Offset->x -= (BoundsRect.hi.x - SpreadRect.hi.x);
04451 
04452     // (b) Vertical adjustment (most useful to clip hi co-ords)
04453     if (BoundsRect.hi.y > SpreadRect.hi.y)
04454         Offset->y -= (BoundsRect.hi.y - SpreadRect.hi.y);
04455     else if (BoundsRect.lo.y < SpreadRect.lo.y)
04456         Offset->y += (SpreadRect.lo.y - BoundsRect.lo.y);
04457 
04458     // Whatever happened, we can fit it on the spread.
04459     return TRUE;
04460 #else
04461     Offset->x = 0;
04462     Offset->y = 0;
04463     return FALSE;
04464 #endif
04465 }
04466 
04467 /********************************************************************************************
04468 
04469 >   virtual BOOL Filter::WillAcceptExistingFile(PathName pthToReplace)
04470 
04471     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
04472     Created:    9/5/97
04473     Returns:    TRUE if this filter is willing to accept this existing file
04474                 FALSE otherwise
04475     Purpose:    Checks to see if this filter will accept an existing file to export
04476                 to.
04477 
04478                 This base version will simply ask the user if she wants to overwrite
04479                 the file.
04480 
04481                 But ImagemapFilter::WillAcceptExistingFile will override this
04482                 so the user can insert an imagemap into an existing HTML file.
04483 
04484 ********************************************************************************************/
04485 
04486 BOOL Filter::WillAcceptExistingFile(PathName pthToReplace)
04487 {
04488 PORTNOTETRACE("filter","Filter::WillAcceptExistingFile - do nothing");
04489 #ifndef EXCLUDE_FROM_XARALX
04490     //We're going to put up a message box to ask the user if she wants to
04491     //replace the existing file.
04492 
04493     //So first get the truncated path name
04494     String_256 strToReplace =  pthToReplace.GetTruncatedPath(50);
04495 
04496     //Now create a string to put our error message in
04497     String_256 strError;
04498 
04499     //And make the error message up using the file name
04500     strError.MakeMsg(_R(IDM_EXPORT_OVERWRITE), &strToReplace);
04501                                                 
04502     //Now, set that error message as the next one to display
04503     Error::SetError( 0, strError, 0 );
04504 
04505     //And set up the message help context
04506     SetNextMsgHelpContext(_R(IDM_EXPORT_OVERWRITE));
04507 
04508     //Now set up the buttons
04509     ErrorInfo Info;
04510     Info.Button[0] = _R(IDB_OVERWRITE);
04511     Info.Button[1] = _R(IDS_CANCEL);
04512     
04513     //Make "cancel" the default
04514     Info.OK = Info.Cancel = 2;
04515 
04516     //And put the error box up
04517     switch (AskQuestion( &Info ))
04518     {
04519         case _R(IDS_CANCEL):
04520             return FALSE;
04521 
04522         case _R(IDB_OVERWRITE):
04523         default:
04524             return TRUE;
04525     }
04526 #endif
04527     return false;
04528 }
04529 
04530 /********************************************************************************************
04531 
04532 >   virtual void Filter::SetSaveAttributes ( BOOL DoSave )
04533 
04534     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
04535     Created:    14/3/00
04536     Inputs:     DoSave  - Should the attributes be saved along with the file data?
04537     Returns:    -
04538     Purpose:    Informs the filter whether or not it should record the attribute settings
04539                 along with the file data. This allows templates to have default colours other
04540                 than the standard Camelot values, whilst not encumbering save files with this
04541                 extra information.
04542 ********************************************************************************************/
04543 
04544 void Filter::SetSaveAttributes ( BOOL DoSave )
04545 {
04546     SaveAttributes = DoSave;
04547 }
04548 
04549 /********************************************************************************************
04550 
04551 >   CompatibleFilter::CompatibleFilter(Filter *NewFilter, INT32 NewCompatibility)
04552 
04553     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
04554     Created:    28/03/94
04555     Inputs:     NewFilter - the filter to add to the list.
04556                 NewCompatibility - the compatibility rating for this filter.
04557     Purpose:    Initialises a list item for a CompatibleFilterList.
04558     SeeAlso:    CompatibleFilter
04559 
04560 ********************************************************************************************/
04561 
04562 CompatibleFilter::CompatibleFilter(Filter *NewFilter, INT32 NewCompatibility)
04563 {
04564     pFilter = NewFilter; 
04565     Compatibility = NewCompatibility;
04566 }
04567 
04568 
04569 
04570 CC_IMPLEMENT_MEMDUMP(CompatibleFilter, ListItem)
04571 CC_IMPLEMENT_MEMDUMP(CompatibleFilterList, List)
04572 
04573 
04574 
04575 /********************************************************************************************
04576 
04577 >   BOOL CompatibleFilterList::AddFilter(Filter *pFilter, INT32 Compatibility)
04578 
04579     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
04580     Created:    28/03/94
04581     Inputs:     pFilter - the filter to add to the list.
04582                 Compatibility - the compatibility rating of the filter.
04583     Returns:    TRUE if the filter was added to the list ok; FALSE if not.
04584     Purpose:    Add a new item to the compatible filter list, which points to the given
04585                 filter, and stores the given compatibility rating in the list entry.
04586                 The list is kept in sorted order, i.e. the list item is added to the list
04587                 according to its compatibility rating; the higher the rating, the closer
04588                 it is to the head of the list.
04589     Errors:     Out of memory.
04590     SeeAlso:    ComaptibleFilterList; CompatibleFilter
04591 
04592 ********************************************************************************************/
04593 
04594 BOOL CompatibleFilterList::AddFilter(Filter *pFilter, INT32 Compatibility)
04595 {
04596     // Make a new list item for this filter.
04597     CompatibleFilter *pNewItem = new CompatibleFilter(pFilter, Compatibility);
04598     if (pNewItem == NULL)
04599         return FALSE;
04600 
04601     // Search for the correct place in the list
04602     CompatibleFilter *pItem = (CompatibleFilter *) GetHead();
04603 
04604     while ((pItem != NULL) && (pItem->Compatibility > Compatibility))
04605         pItem = (CompatibleFilter *) GetNext(pItem);
04606 
04607     // If come to the end of the list, add it to the end, otherwise add before the
04608     // current item
04609     if (pItem == NULL)
04610         AddTail(pNewItem);
04611     else
04612         InsertBefore(pItem, pNewItem);
04613 
04614     // All ok
04615     return TRUE;
04616 }
04617 
04618 /********************************************************************************************
04619 
04620 >   FilterFamily::FilterFamily()
04621 
04622     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
04623     Created:    28/03/94
04624     Purpose:    Initialise the FilterFamily object.  This can import but not export.
04625     SeeAlso:    FilterFamily; Filter
04626 
04627 ********************************************************************************************/
04628 
04629 FilterFamily::FilterFamily()
04630 {
04631     // We can import, but not export.
04632     Flags.CanImport = TRUE;
04633     Flags.CanExport = FALSE;
04634     Flags.CanExportMultipleImages = FALSE;
04635     
04636     pCachedBestFilter = NULL;
04637 }
04638 
04639 /********************************************************************************************
04640 
04641 >   FilterFamily::~FilterFamily()
04642 
04643     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
04644     Created:    28/03/94
04645     Purpose:    Destructor for FilterFamily object.  Does nothing at present.
04646     SeeAlso:    FilterFamily
04647 
04648 ********************************************************************************************/
04649 
04650 FilterFamily::~FilterFamily()
04651 {
04652 }
04653 
04654 
04655 
04656 /********************************************************************************************
04657 
04658 >   INT32 FilterFamily::HowCompatible(PathName& Filename, 
04659                                     ADDR HeaderStart, UINT32 HeaderSize, UINT32 FileSize);
04660 
04661     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
04662     Created:    28/03/94
04663     Inputs:     As base class version.
04664     Returns:    Always returns 0 => don't understand file.
04665     Purpose:    Returns 0, to indicate that this filter does not recognise the file.
04666                 This is because this is not a 'proper' import filter - it's just pretending
04667                 to be a number of the other filters joined into one.
04668     SeeAlso:    FilterFamily; Filter::HowCompatible
04669 
04670 ********************************************************************************************/
04671 
04672 INT32 FilterFamily::HowCompatible(PathName& Filename, 
04673                                 ADDR HeaderStart, UINT32 HeaderSize, UINT32 FileSize)
04674 
04675 {
04676     return 0;
04677 }
04678 
04679 
04680 /********************************************************************************************
04681 
04682 >   Filter* FilterFamily::GetBestFilter(CCLexFile* pFile, BOOL ShowWarnings = FALSE)
04683 
04684     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04685     Created:    9/10/95
04686     Inputs:     pFile           the file to be checked
04687                 ShowWarnings    TRUE shows a message box if the best filter is found is
04688                                 not perfect for this file. (added 1/2/01 ChrisG)
04689     Returns:    pointer to the best filter found or NULL if none found.
04690     Purpose:    Works out the best filter to use for the specified file by asking all the
04691                 filters in turn whether it recognises the file. 
04692     Errors:     Out of memory, File not recognised.
04693     SeeAlso:    FilterFamily::DoImport; FilterFamily::IsDefaultDocRequired;
04694     SeeAlso:    Filter::IsDefaultDocRequired;
04695         
04696 ********************************************************************************************/
04697 
04698 // Graeme (28/6/00) - Because AI9 files have a load of junk at their start, the original
04699 // 1kb file header just isn't big enough. I've extended it to 8kb (which should fit nicely
04700 // into the cache), to cover for this.
04701 #define FILTER_HDRSIZE (8192)
04702 
04703 Filter* FilterFamily::GetBestFilter(CCLexFile* pFile, BOOL ShowWarnings /*= FALSE*/)
04704 {
04705     ERROR2IF(pFile == NULL, NULL, "FilterFamily::GetBestFilter NULL CCFile* supplied");
04706     
04707     // Load the first 1k of the file.
04708     UINT32 SegmentSize = FILTER_HDRSIZE;
04709     size_t FileSize;
04710     ADDR FilterBuf = LoadInitialSegment(pFile, &SegmentSize, &FileSize);
04711 
04712     // Error occured when accessing file
04713     if (FilterBuf == NULL)
04714         return NULL;
04715 
04716 #if FALSE
04717     {
04718         DWORD* pDWord = (DWORD*) FilterBuf;
04719         BYTE* pByte = (BYTE*) FilterBuf;
04720 
04721         TRACE( _T("Initial segment\n"));
04722 
04723         for (UINT32 i = 0; i < 16; i++)
04724         {
04725             char c0 = isprint(pByte[0])?pByte[0]:'.';
04726             char c1 = isprint(pByte[1])?pByte[1]:'.';
04727             char c2 = isprint(pByte[2])?pByte[2]:'.';
04728             char c3 = isprint(pByte[3])?pByte[3]:'.';
04729             
04730             TRACE( _T("%04x : %08x  "), (i*4), pDWord[0]);
04731             TRACE( _T("%02x %02x %02x %02x  "), pByte[0], pByte[1], pByte[2], pByte[3]);
04732             TRACE( _T("%c%c%c%c\n"), c0, c1, c2, c3);
04733             pDWord += 1;
04734             pByte += 4;
04735         }
04736     }
04737 #endif
04738 
04739     // Try to create a file-path from the file.  Some files don't have a notion of a
04740     // path, for these ones we will use a blank string.
04741     PathName Path = pFile->GetPathName();
04742 
04743     // Create a list of all the filters that understand this file to one degree or
04744     // another, sorted on how much they like the file.
04745     CompatibleFilterList Filters;
04746 
04747     Filter* pFilter = Filter::GetFirst();
04748     while (pFilter != NULL)
04749     {
04750         // Inform any filters that we are about to do a HowCompatible call.
04751         // This would allow a set of filters which have common functionality hidden in a
04752         // filter that cannot import and cannot export handle this call and hence set
04753         // itself up. This would allow it to maybe cache a result which should only be
04754         // checked by the first filter in the group. 
04755         if (pFilter->JoinFamily(pFilterType) && (!pFilter->GetFlags().CanImport))
04756             /*BOOL ok =*/ pFilter->PreHowCompatible();
04757 
04758         if (pFilter->GetFlags().CanImport && pFilter->JoinFamily(pFilterType))
04759         {
04760             // This is an import filter which belongs to our family - ask it if it 
04761             // understands this file.
04762             INT32 Compatibility = pFilter->HowCompatible(Path, FilterBuf, SegmentSize, 
04763                                                        (UINT32) FileSize);
04764 
04765 //          RELTRACE( _T("Filter %s - Compatibility %d\n"), (LPCTSTR)pFilter->FilterName, (INT32)Compatibility);
04766             if (Compatibility > 0)
04767             {
04768                 // Add this filter to the list
04769                 if (Filters.AddFilter(pFilter, Compatibility) == FALSE)
04770                 {
04771                     // Error has occured - clean up our objects and return error
04772                     CCFree(FilterBuf);
04773                     Filters.DeleteAll();
04774                     return NULL;
04775                 }
04776             }
04777         }
04778 
04779         // Get the next filter.
04780         pFilter = Filter::GetNext(pFilter);
04781     }
04782 
04783     
04784     // added by Ben to avoid the MacPaint filter grabbing everything
04785     CompatibleFilter* pCFilter = (CompatibleFilter *)Filters.GetHead();
04786     
04787     // run through all the filters to see if their extensions match
04788     CompatibleFilter* pBestFilter = NULL;
04789     CompatibleFilter* pSecondBestFilter = NULL;
04790 
04791 /*  BOOL fPathValid = Path.IsValid();
04792     TRACEUSER( "JustinF", _T("File path is %s\n"),
04793         (LPCTSTR) (fPathValid ? Path.GetPath() : "INVALID"));
04794 */
04795 
04796     INT32 bestCompatibility = 0;
04797     while(pCFilter != NULL)
04798     {
04799 PORTNOTE("filter","Removed OILFilter usage")
04800 #ifndef EXCLUDE_FROM_XARALX
04801         // (ChrisG 22/01/01) File extension matching is now done for all of the filters,
04802         //  regardless of their current comaptibility score. If one is found that doesn't
04803         //  have the correct extension, then we subtract one from that filter's score.
04804         //
04805         // This allows dodgy EPS files to have a better chance of getting the right 
04806         //  filter without having to give any indication of what format they're in other than
04807         //  the file extension.
04808         //
04809         //  NOTE: This check is only done if the path is valid.
04810         if (fPathValid && !pCFilter->pFilter->pOILFilter->DoesExtensionOfFileMatch(pFile))
04811         {
04812             pCFilter->Compatibility --;
04813         }
04814 #endif
04815         // If this filter has a higher compatibility than the current best, make this the new
04816         // "best filter" and relegate the other to second best.
04817         if (pCFilter->Compatibility >= bestCompatibility)
04818         {
04819             pSecondBestFilter = pBestFilter;
04820             pBestFilter = pCFilter;
04821             bestCompatibility = pCFilter->Compatibility;
04822         }
04823         // if this isn't the best, but IS better than the previous best, then update SecondBest.
04824         else if (pSecondBestFilter != NULL)
04825         {
04826             if (pCFilter->Compatibility >= pSecondBestFilter->Compatibility)
04827             {
04828                 pSecondBestFilter = pCFilter;
04829             }
04830         }
04831 
04832         pCFilter = (CompatibleFilter*) Filters.GetNext(pCFilter);
04833     }
04834 
04835     // BODGE:
04836     // For now, just choose the filter at the head of the list.
04837     // We should check for the compatibility being less than 10 and provide a scrolly list 
04838     // for the user to choose from if more than one filter is interested.
04839     //
04840     // Improved 16/10/2000 by ChrisG - added a scan for the best possible compatibility, so 
04841     // that the filter's position in the list is not quite as important as it was. Although a 
04842     // dialog with a list box filled with the results and compatibilities would be better.
04843     //
04844     // Note: SecondBestFilter is a bit of an irrelevance now, but may be useful for debugging 
04845     // purposes
04846 
04847     if (pBestFilter == NULL)
04848     {
04849         // If we have a second best filter then choose it
04850         if (pSecondBestFilter != NULL)
04851             pBestFilter = pSecondBestFilter;
04852         else
04853         {
04854             pBestFilter = (CompatibleFilter*) Filters.GetHead();
04855             TRACE( _T("Couldn't find best filter in FilterFamily::GetBestFilter\n"));
04856         }
04857     }
04858 
04859     if (pBestFilter == NULL)
04860     {
04861 #ifdef STANDALONE
04862         // if this is the standalone version, see if it's an EPS file we just tried
04863         if(camStrncmp((char*) FilterBuf, "%!PS-Adobe", 10) == 0)
04864         {
04865             Error::SetError(_R(IDT_NOTTHISEPS));
04866             CCFree(FilterBuf);
04867             Filters.DeleteAll();
04868             return NULL;
04869         }
04870 #endif
04871         // None of the filters liked this file - tell the user
04872         CCFree(FilterBuf);
04873         Filters.DeleteAll();
04874         Error::SetError(_R(IDT_FILE_NOTRECOGNISED));
04875         return NULL;
04876     }
04877 
04878     // (ChrisG 1/2/01) if this filter is not perfectly compatible, tell the user, 
04879     //  if we're showing warnings
04880     if (pBestFilter->Compatibility < 9)
04881     {
04882         if (ShowWarnings)
04883             InformWarning (_R(IDT_IMPORTFILTER_NOTPERFECT));
04884     }
04885 
04886     // Free up the objects that we used
04887     Filter* pBest = pBestFilter->pFilter;
04888     CCFree(FilterBuf);
04889     Filters.DeleteAll();
04890     return pBest;   
04891 }   
04892 
04893 
04894 
04895 /********************************************************************************************
04896 
04897 >   BOOL FilterFamily::IsDefaultDocRequired(const TCHAR* pcszPathName)
04898 
04899     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04900     Created:    9/10/95
04901     Inputs:     pcszPathName    pointer to the pathname to check
04902     Returns:    TRUE if the filter requires a default document, FALSE if not.
04903     Purpose:    Works out if opening a file of this type requires a default document to be
04904                 loaded. If the file format supplies the document then return FALSE otherwise
04905                 return TRUE. An example would be opening a bitmap file. This has no document
04906                 defined in the file format and so we need to laod the default document before
04907                 importing the bitmap into this file.
04908     SeeAlso:    Filter; Filter::IsDefaultDocRequired; CCamDoc::OnOpenDocument;
04909     SeeAlso:    FilterFamily::DoImport; Filter::DoImport; FilterFamily::GetBestFilter
04910 
04911 ********************************************************************************************/
04912 
04913 BOOL FilterFamily::IsDefaultDocRequired(const TCHAR* pcszPathName)
04914 {
04915     // If the pathname passed in is NULL then there is nothing we can do so say no
04916     // default document is required.
04917     if (pcszPathName == NULL) return FALSE;
04918 
04919     // Ensure the cached best filter is set to null
04920     pCachedBestFilter = NULL;
04921 
04922     // Work out the best filter to use on this file.
04923     Filter* pBestFilter = NULL;
04924 
04925     // First off, we have to try and open the file
04926     CCDiskFile file(1024, FALSE, TRUE);
04927 
04928     // Build a string out of the path name
04929     String_256 FileName(pcszPathName);
04930 
04931     // get it into the proper PathName class
04932     PathName Path(FileName);
04933 
04934     // If we cannot open the file then return false
04935     if (!file.open(Path, ios::in | ios::binary)) return FALSE;      
04936 
04937     // Find the best file for this to use
04938     pBestFilter = GetBestFilter(&file);
04939     
04940     // On this pass, no errors are allowed, at present.
04941     Error::ClearError();
04942 
04943     // Close the file again
04944     if (file.isOpen()) file.close();
04945     
04946     // If the filter is NULL then not found, must have set an error. 
04947     if (pBestFilter == NULL) return FALSE;
04948 
04949     // Result: do we require the default document?
04950     BOOL Result;
04951 
04952     // Ask the best filter to see if we need to load a default document for it to use.
04953     // At this point the pathname is irrelevent.
04954     Result = pBestFilter->IsDefaultDocRequired(pcszPathName);
04955 
04956     // Make a note of the filter that we decided on as the best filter.
04957     pCachedBestFilter = pBestFilter;
04958 
04959     return Result;
04960 }   
04961 
04962 
04963 /********************************************************************************************
04964 
04965 >   BOOL FilterFamily::DoImport(SelOperation *pOp, CCLexFile* pFile, 
04966                                 Document *pDestDoc, BOOL AutoChosen, ImportPosition *Pos,
04967                                 KernelBitmap** ppImportedBitmap, DocCoord* pPosTranslate,
04968                                 String_56& URL)
04969 
04970     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
04971     Created:    21/03/94
04972     Inputs:     pOp - the live operation associated with this file import process.
04973                 pFile - The file to import from
04974                 pDestDoc - the document to import the file into.
04975                 Pos -
04976                 ppImportedBitmap - this is used mainly in the bitfltr.cpp for the HTML
04977                 import filter. HTMLFilter::DoImport() needs a pointer to a kernel bitmap
04978                 to set the background bitmap up into Camelot.
04979                 pPosTranslate - This is used too by the HTMLFilter in order to do a formatting.
04980                 URL - the URL of the original imported file
04981     Returns:    TRUE if the document was loaded ok, FALSE if not.
04982     Purpose:    Loads in the initial 1k of the file, and passes this around all the filters
04983                 to see which ones understand it.  It then chooses the filter that claims
04984                 the highest 'compatibility', and calls its DoImport() function to load it.
04985     Errors:     Out of memory, File not recognised.
04986     SeeAlso:    Filter; Filter::DoImport; FilterFamily::GetBestFilter;
04987     SeeAlso:    FilterFamily::IsDefaultDocRequired; Filter::IsDefaultDocRequired;
04988 
04989 ********************************************************************************************/
04990 
04991 BOOL FilterFamily::DoImport(SelOperation *pOp, CCLexFile* pFile, 
04992                             Document *pDestDoc, BOOL AutoChosen, ImportPosition *Pos,
04993                             KernelBitmap** ppImportedBitmap, DocCoord* pPosTranslate, String_256* URL)
04994 {
04995     // Work out the best filter to use on this file.
04996     // (ChrisG 1/2/01) We do want to be warned if this filter isn't perfect
04997     Filter *pBestFilter = GetBestFilter(pFile, TRUE);
04998 
04999     // If the filter is NULL then not found, must have set an error. 
05000     if (pBestFilter == NULL)
05001     {
05002         // Ensure the cached best filter is set to null
05003         pCachedBestFilter = NULL;
05004         return FALSE;
05005     }
05006     
05007     // Result: did we import the file ok?
05008     BOOL Result = FALSE;
05009 
05010     // Use this filter to import the file, and tell the filter that it was chosen
05011     // automatically.
05012     Result = pBestFilter->DoImport(pOp, pFile, pDestDoc, TRUE, Pos, NULL, NULL, URL);
05013 
05014     // Make sure the art file error is more specific
05015     if (!Result && pBestFilter->FilterID == FILTERID_NATIVE_EPS)
05016     {
05017         // Check that it is not our special do nothing message
05018         // or that the error has been reported before and cleared 
05019         if (Error::GetErrorNumber() != _R(IDN_USER_CANCELLED) &&
05020             Error::GetErrorNumber() != _R(IDT_IMPORT_USERABORT))
05021         {
05022             Error::ClearError();
05023             Error::SetError(_R(IDS_ERRORINARTFILE));
05024         }
05025     }
05026 
05027     // Ensure the cached best filter is set back to null again
05028     pCachedBestFilter = NULL;
05029 
05030     // Return the result of importing the file.
05031     return Result;
05032 }
05033 
05034 
05035 
05036 /********************************************************************************************
05037 
05038 >   BOOL FilterFamily::ImportBitmap(CCLexFile* pFile, KernelBitmap** ppBitmap)
05039 
05040     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05041     Created:    8/04/94
05042     Inputs:     pFile - The file to import from
05043     Outputs:    *ppBitmap is updated to point at the imported bitmap.
05044     Returns:    TRUE if the bitmap was loaded ok, FALSE if not.
05045     Purpose:    Loads in the initial 1k of the file, and passes this around all the filters
05046                 to see which ones understand it.  It then chooses the filter that claims
05047                 the highest 'compatibility', and calls its ImportBitmap() function to load it.
05048     Errors:     Out of memory, File not recognised.
05049     SeeAlso:    Filter; Filter::ImportBitmap
05050 
05051 ********************************************************************************************/
05052 
05053 BOOL FilterFamily::ImportBitmap(CCLexFile* pFile, KernelBitmap** ppBitmap)
05054 {
05055     // If it is not a disk file, then bail right out now.
05056 //  if (!pFile->IS_KIND_OF(CCDiskFile)) return FALSE;
05057 
05058     // Find out the pathname of the file in question
05059     PathName Path = pFile->GetPathName();
05060 
05061     // Load the first 1k of the file.
05062     UINT32 SegmentSize = FILTER_HDRSIZE;
05063     size_t FileSize;
05064     ADDR FilterBuf = LoadInitialSegment(pFile, &SegmentSize, &FileSize);
05065     if (FilterBuf == NULL)
05066         // Error occured when accessing file
05067         return FALSE;
05068 
05069     // Create a list of all the filters that understand this file to one degree or
05070     // another, sorted on how much they like the file.
05071     CompatibleFilterList Filters;
05072 
05073     Filter* pFilter = Filter::GetFirst();
05074     while (pFilter != NULL)
05075     {
05076         // Inform any filters that we are about to do a HowCompatible call.
05077         // This would allow a set of filters which have common functionality hidden in a
05078         // filter that cannot import and cannot export handle this call and hence set
05079         // itself up. This would allow it to maybe cache a result which should only be
05080         // checked by the first filter in the group. 
05081         if (pFilter->JoinFamily(pFilterType) && (!pFilter->GetFlags().CanImport))
05082             /*BOOL ok =*/ pFilter->PreHowCompatible();
05083 
05084         if (pFilter->GetFlags().CanImport && pFilter->JoinFamily(pFilterType))
05085         {
05086             // This is an import filter which belongs to our family - ask it if it 
05087             // understands this file.
05088             INT32 Compatibility = pFilter->HowCompatible(Path, FilterBuf, SegmentSize, 
05089                                                        (UINT32) FileSize);
05090 
05091             if (Compatibility > 0)
05092             {
05093                 // Add this filter to the list
05094                 if (Filters.AddFilter(pFilter, Compatibility) == FALSE)
05095                 {
05096                     // Error has occured - clean up our objects and return error
05097                     CCFree(FilterBuf);
05098                     Filters.DeleteAll();
05099                     return FALSE;
05100                 }
05101             }
05102         }
05103 
05104         // Get the next filter.
05105         pFilter = Filter::GetNext(pFilter);
05106     }
05107 
05108     // BODGE:
05109     // For now, just choose the filter at the head of the list.
05110     // We should check for the compatibility being less than 10 and provide a scrolly list 
05111     // for the user to choose from if more than one filter is interested.
05112     CompatibleFilter* pBestFilter = (CompatibleFilter*) Filters.GetHead();
05113 
05114     // Result: did we import the file ok?
05115     BOOL Result;
05116 
05117     if (pBestFilter == NULL)
05118     {
05119         // None of the filters liked this file - tell the user
05120         Result = FALSE;
05121         Error::SetError(_R(IDT_FILE_NOTRECOGNISED));
05122     }
05123     else
05124     {
05125         // Use this filter to import the file, and tell the filter that it was chosen
05126         // automatically.
05127         Result = pBestFilter->pFilter->ImportBitmap(pFile, ppBitmap);
05128     }
05129 
05130     // Clean up
05131     CCFree(FilterBuf);
05132     Filters.DeleteAll();
05133 
05134     // Return the result of importing the file.
05135     return Result;
05136 }
05137 
05138 /********************************************************************************************
05139 
05140 >   BOOL FilterFamily::DoExport(Operation*, CCLexFile*, PathName *, Document*, BOOL)
05141 
05142     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
05143     Created:    28/03/94
05144     Inputs:     As base class version.
05145     Returns:    Always returns FALSE.
05146     Purpose:    Dummy function - this filter does not allow export.
05147     Errors:     ENSURE failure when called.
05148 
05149 ********************************************************************************************/
05150 
05151 BOOL FilterFamily::DoExport(Operation*, CCLexFile*, PathName*, Document*, BOOL)
05152 {
05153     // This filter doesn't export.
05154     ENSURE(FALSE, "FilterFamily::DoExport() called - this should not happen!");
05155     return FALSE;
05156 }
05157 
05158 
05159 /********************************************************************************************
05160 
05161 >   BOOL FilterFamily::JoinFamily(CCRuntimeClass *)
05162 
05163     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
05164     Created:    26/07/94
05165     Purpose:    Over-rides this function, because we don't ever want a filter family to
05166                 join another filter family, as this would be nonsensical.
05167     SeeAlso:    FilterFamily
05168 
05169 ********************************************************************************************/
05170 
05171 BOOL FilterFamily::JoinFamily(CCRuntimeClass *)
05172 {
05173     return FALSE;
05174 }
05175 
05176 
05177 /********************************************************************************************
05178 
05179 >   GenericFilter::GenericFilter()
05180 
05181     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
05182     Created:    28/07/94
05183     Purpose:    Sets up the generic filter object to interface to all the installed
05184                 filters.
05185 
05186 ********************************************************************************************/
05187 
05188 GenericFilter::GenericFilter()
05189 {
05190     // This is the generic filter, so we want *all* filters in it.
05191     pFilterType = CC_RUNTIME_CLASS(Filter);
05192 }
05193 
05194 /********************************************************************************************
05195 
05196 >   BOOL GenericFilter::Init()
05197 
05198     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
05199     Created:    28/03/94
05200     Returns:    TRUE if initalised ok; FALSE if error occurred.
05201     Purpose:    Set up a generic filter object.  This creates the associated OILFilter
05202                 object, and sets up the filter ID number and strings.
05203     Errors:     Out of memory.
05204     SeeAlso:    FilterFamily; OILFilter
05205 
05206 ********************************************************************************************/
05207 
05208 BOOL GenericFilter::Init()
05209 {
05210     // Get the OILFilter object
05211     pOILFilter = new OILFilterFamily(this, _R(IDT_FILTERNAME_GENERIC));
05212     if (pOILFilter == NULL)
05213         return FALSE;
05214 
05215     // Load the description strings
05216     FilterName.Load(_R(IDT_GENERIC_FILTERNAME));
05217     FilterInfo.Load(_R(IDT_GENERIC_FILTERINFO));
05218     FilterID = FILTERID_GENERIC;
05219 
05220     // All ok
05221     return TRUE;
05222 }
05223 
05224 /********************************************************************************************
05225 
05226 >   VectorFilterFamily::VectorFilterFamily()
05227 
05228     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
05229     Created:    28/07/94
05230     Purpose:    Sets up the vector filter object to interface to all the installed
05231                 filters that decode vector file formats.
05232 
05233 ********************************************************************************************/
05234 
05235 VectorFilterFamily::VectorFilterFamily()
05236 {
05237     // This is the vector files filter, so we want *all* vector filters in it.
05238     pFilterType = CC_RUNTIME_CLASS(VectorFilter);
05239 }
05240 
05241 /********************************************************************************************
05242 
05243 >   BOOL VectorFilterFamily::Init()
05244 
05245     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
05246     Created:    28/03/94
05247     Returns:    TRUE if initalised ok; FALSE if error occurred.
05248     Purpose:    Set up a vector file filter object.  This creates the associated OILFilter
05249                 object, and sets up the filter ID number and strings.
05250     Errors:     Out of memory.
05251     SeeAlso:    FilterFamily; OILFilter
05252 
05253 ********************************************************************************************/
05254 
05255 BOOL VectorFilterFamily::Init()
05256 {
05257     // Get the OILFilter object
05258     pOILFilter = new OILFilterFamily(this, _R(IDT_FILTERNAME_VECTOR));
05259     if (pOILFilter == NULL)
05260         return FALSE;
05261 
05262     // Load the description strings
05263     FilterName.Load(_R(IDT_VECTOR_FILTERNAME));
05264     FilterInfo.Load(_R(IDT_VECTOR_FILTERINFO));
05265     FilterID = FILTERID_VECTOR;
05266 
05267     // All ok
05268     return TRUE;
05269 }
05270 
05271 /********************************************************************************************
05272 
05273 >   BitmapFilterFamily::BitmapFilterFamily()
05274 
05275     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
05276     Created:    28/07/94
05277     Purpose:    Sets up the bitmap filter object to interface to all the installed
05278                 filters that decode bitmap file formats.
05279 
05280 ********************************************************************************************/
05281 
05282 BitmapFilterFamily::BitmapFilterFamily()
05283 {
05284     // This is the bitmap files filter, so we want *all* bitmap filters in it.
05285     pFilterType = CC_RUNTIME_CLASS(BitmapFilter);
05286 }
05287 
05288 /********************************************************************************************
05289 
05290 >   BOOL BitmapFilterFamily::Init()
05291 
05292     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
05293     Created:    28/03/94
05294     Returns:    TRUE if initalised ok; FALSE if error occurred.
05295     Purpose:    Set up a bitmap filter object.  This creates the associated OILFilter
05296                 object, and sets up the filter ID number and strings.
05297     Errors:     Out of memory.
05298     SeeAlso:    FilterFamily; OILFilter
05299 
05300 ********************************************************************************************/
05301 
05302 BOOL BitmapFilterFamily::Init()
05303 {
05304     // Get the OILFilter object
05305     pOILFilter = new OILFilterFamily(this, _R(IDT_FILTERNAME_BITMAP));
05306     if (pOILFilter == NULL)
05307         return FALSE;
05308 
05309     // Load the description strings
05310     FilterName.Load(_R(IDT_BITMAP_FILTERNAME));
05311     FilterInfo.Load(_R(IDT_BITMAP_FILTERINFO));
05312     FilterID = FILTERID_BITMAP;
05313 
05314     // All ok
05315     return TRUE;
05316 }
05317 
05318 
05319 
05320 #if BUILD_TEXT_FILTERS
05321 /********************************************************************************************
05322 >   TextFilterFamily::TextFilterFamily()
05323 
05324     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
05325     Created:    24/11/95
05326     Purpose:    Sets up the text filter object to interface to all the installed
05327                 filters that decode text file formats.
05328 ********************************************************************************************/
05329 TextFilterFamily::TextFilterFamily()
05330 {
05331     pFilterType = CC_RUNTIME_CLASS(TextFilter);
05332 }
05333 
05334 
05335 /********************************************************************************************
05336 >   BOOL TextFilterFamily::Init()
05337 
05338     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
05339     Created:    24/11/95
05340     Returns:    TRUE if initalised ok; FALSE if error occurred.
05341     Purpose:    Set up a text filter object.  This creates the associated OILFilter
05342                 object, and sets up the filter ID number and strings.
05343     Errors:     Out of memory.
05344     SeeAlso:    FilterFamily; OILFilter
05345 ********************************************************************************************/
05346 BOOL TextFilterFamily::Init()
05347 {
05348     // Get the OILFilter object
05349     pOILFilter = new OILFilterFamily(this, _R(IDT_FILTERNAME_TEXT));
05350     if (pOILFilter == NULL)
05351         return FALSE;
05352 
05353     // Load the description strings
05354     FilterName.Load(_R(IDT_TEXT_FILTERNAME));
05355     FilterInfo.Load(_R(IDT_TEXT_FILTERINFO));
05356     FilterID = FILTERID_TEXT;
05357 
05358     // All ok
05359     return TRUE;
05360 }
05361 #endif  // #if BUILD_TEXT_FILTERS
05362 
05363 
05364 /********************************************************************************************
05365 
05366 >   GenericEPSFilter::GenericFilter()
05367 
05368     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
05369     Created:    28/07/94
05370     Purpose:    Sets up the generic EPS filter object to interface to all the installed
05371                 EPS filters.
05372 
05373 ********************************************************************************************/
05374 
05375 GenericEPSFilter::GenericEPSFilter()
05376 {
05377     // This is the generic EPS filter, so we want all EPS filters in it.
05378     pFilterType = CC_RUNTIME_CLASS(EPSFilter);
05379 }
05380 
05381 /********************************************************************************************
05382 
05383 >   BOOL GenericEPSFilter::Init()
05384 
05385     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
05386     Created:    28/03/94
05387     Returns:    TRUE if initalised ok; FALSE if error occurred.
05388     Purpose:    Set up a generic EPS filter object.  This creates the associated OILFilter
05389                 object, and sets up the filter ID number and strings.
05390     Errors:     Out of memory.
05391     SeeAlso:    FilterFamily; OILFilter; EPSFilter
05392 
05393 ********************************************************************************************/
05394 
05395 BOOL GenericEPSFilter::Init()
05396 {
05397     // Get the OILFilter object
05398     pOILFilter = new OILFilterFamily(this, _R(IDT_FILTERNAME_EPS));
05399     if (pOILFilter == NULL)
05400         return FALSE;
05401 
05402     // Load the description strings
05403     FilterName.Load(_R(IDT_EPS_FILTERNAME));
05404     FilterInfo.Load(_R(IDT_EPS_FILTERINFO));
05405     FilterID = FILTERID_EPS;
05406 
05407     // All ok
05408     return TRUE;
05409 }
05410 
05411 
05412 #ifndef NOCDRCMX
05413 
05414 /********************************************************************************************
05415 >   PaletteFilterFamily::PaletteFilterFamily()
05416 
05417     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
05418     Created:    30/4/96
05419     Purpose:    Sets up the filter object to interface to all the installed filters that
05420                 decode palette file formats.
05421 ********************************************************************************************/
05422 PaletteFilterFamily::PaletteFilterFamily()
05423 {
05424     PORTNOTETRACE("filter","PaletteFilterFamily::PaletteFilterFamily - do nothing");
05425 #ifndef EXCLUDE_FROM_XARALX
05426     pFilterType = CC_RUNTIME_CLASS(PaletteFilter);
05427 #endif
05428 
05429 }
05430 
05431 
05432 /********************************************************************************************
05433 >   BOOL PaletteFilterFamily::Init()
05434 
05435     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
05436     Created:    30/4/96
05437     Returns:    TRUE if initalised ok; FALSE if error occurred.
05438     Purpose:    Set up a filter object.  This creates the associated OILFilter object, and
05439                 sets up the filter ID number and strings.
05440     Errors:     Out of memory.
05441     SeeAlso:    FilterFamily; OILFilter
05442 ********************************************************************************************/
05443 BOOL PaletteFilterFamily::Init()
05444 {
05445 PORTNOTE("filter","Removed OILFilter usage")
05446 #ifndef EXCLUDE_FROM_XARALX
05447     // Get the OILFilter object
05448     pOILFilter = new OILFilterFamily(this, _R(IDT_FILTERNAME_PALETTE));
05449     if (pOILFilter == NULL)
05450         return FALSE;
05451 #endif
05452     // Load the description strings
05453     FilterName.Load(_R(IDT_FILTERNAME_PALETTE));
05454     FilterInfo.Load(_R(IDT_FILTERINFO_PALETTE));
05455     FilterID = FILTERID_PALETTE;
05456 
05457     // All ok
05458     return TRUE;
05459 }
05460 
05461 #endif
05462 
05463 /********************************************************************************************
05464 
05465 >   SnapShotItem::SnapShotItem()
05466 
05467     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
05468     Created:    16/10/95
05469     Inputs:     -
05470     Returns:    -
05471     Purpose:    Construct a SnapShotItem to record a list of current attributes
05472 
05473 *********************************************************************************************/
05474 
05475 SnapShotItem::SnapShotItem()
05476 {
05477     SnapShotAttrs = NULL;
05478     SnapShotAttrsStack = NULL;
05479 }
05480 
05481 
05482 /********************************************************************************************
05483 
05484 >   SnapShotItem::~SnapShotItem()
05485 
05486     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
05487     Created:    16/10/95
05488     Inputs:     -
05489     Returns:    -
05490     Purpose:    Destroy a SnapShotItem - removes all allocated arrays
05491 
05492 *********************************************************************************************/
05493 
05494 SnapShotItem::~SnapShotItem()
05495 {
05496     if (SnapShotAttrs!=NULL)
05497     {
05498         INT32 i, NumAttrs = AttributeManager::GetNumAttributes();
05499         for (i=0; i<NumAttrs; i++)
05500         {
05501             if (SnapShotAttrs[i] != NULL)
05502             {
05503                 delete SnapShotAttrs[i];
05504                 SnapShotAttrs[i]=NULL;
05505             }
05506         }
05507         CCFree(SnapShotAttrs);
05508         SnapShotAttrs=NULL;
05509     }
05510 
05511     if (SnapShotAttrsStack!=NULL)
05512     {
05513         CCFree(SnapShotAttrsStack);
05514         SnapShotAttrsStack=NULL;
05515     }
05516 }
05517 
05518 
05519 /********************************************************************************************
05520 
05521 >   BOOL SnapShotItem::Initialise(AttributeEntry* CurrAttrs)
05522 
05523     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
05524     Created:    16/10/95
05525     Inputs:     CurrAttrs = a pointer to a list of attributeentry items. There
05526                             as usual should be AttributeManager::NumAttributes() of them
05527     Returns:    TRUE if able to initialise this snapshot item
05528                 FALSE if not
05529     Purpose:    This function grabs a snap shot of the described attributes list
05530 
05531 *********************************************************************************************/
05532 
05533 BOOL SnapShotItem::Initialise(AttributeEntry* CurrAttrs)
05534 {
05535     INT32 i, NumAttrs = AttributeManager::GetNumAttributes();
05536 
05537     SnapShotAttrs = (NodeAttribute**)CCMalloc(NumAttrs*sizeof(NodeAttribute*));
05538     if (SnapShotAttrs==NULL)
05539         return FALSE;
05540 
05541     SnapShotAttrsStack = (AttributeEntry*)CCMalloc(NumAttrs*sizeof(AttributeEntry));
05542     if (SnapShotAttrsStack==NULL)
05543     {
05544         CCFree(SnapShotAttrs);
05545         SnapShotAttrs=NULL;
05546         return FALSE;
05547     }
05548 
05549     // store the temp values
05550     for (i=0; i<NumAttrs; i++)
05551     {
05552         // of course the following MakeNode may fail, but it just sets
05553         // the SnapShotAttrs ptr to NULL which we MUST check (and do) later on
05554         SnapShotAttrs[i] = (CurrAttrs[i].pAttr)->MakeNode();
05555     
05556         SnapShotAttrsStack[i].pAttr  = NULL;
05557         SnapShotAttrsStack[i].Temp   = FALSE;
05558         SnapShotAttrsStack[i].Ignore = TRUE;
05559     }
05560 
05561     return TRUE;
05562 }
05563 
05564 
05565 //********************************************************************************************
05566 //********************************************************************************************
05567 
05568 
05569 
05570 /********************************************************************************************
05571 
05572 >   SnapShotList::SnapShotList()
05573 
05574     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
05575     Created:    16/10/95
05576     Inputs:     -
05577     Purpose:    Constructs a snap shot list
05578 
05579 *********************************************************************************************/
05580 
05581 SnapShotList::SnapShotList()
05582 {
05583 }
05584 
05585 
05586 /********************************************************************************************
05587 
05588 >   SnapShotList::~SnapShotList()
05589 
05590     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
05591     Created:    16/10/95
05592     Inputs:     -
05593     Returns:    -
05594     Purpose:    Destroys a snapshot list. At this stage the snap shot list should be
05595                 empty (if Create and Destroy have been matched correctly). 
05596 
05597 *********************************************************************************************/
05598 
05599 SnapShotList::~SnapShotList()
05600 {
05601     BOOL notempty=FALSE;
05602     SnapShotItem* pItem=NULL;
05603     while ( (pItem=(SnapShotItem*)SnapShot.RemoveTail()) !=NULL )
05604     {
05605         notempty=TRUE;
05606         delete pItem;
05607     }
05608     if (notempty)
05609     {
05610         ERROR3("Destroyed a none empty snapshot list!\n");
05611     }
05612 }
05613 
05614 
05615 /********************************************************************************************
05616 
05617 >   SnapShotItem* SnapShotList::GetCurrentSnapShot()
05618 
05619     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
05620     Created:    16/10/95
05621     Inputs:     -
05622     Returns:    A pointer to the current snap shot.
05623     Purpose:    This function is an abstracted way of finding the current snap shot
05624                 created by the last CreateSnapShot() to be called (as snap shots can
05625                 be stacked)
05626 
05627 *********************************************************************************************/
05628 
05629 SnapShotItem* SnapShotList::GetCurrentSnapShot()
05630 {
05631     return (SnapShotItem*)SnapShot.GetTail();
05632 }
05633 
05634 
05635 /********************************************************************************************
05636 
05637 >   BOOL SnapShotList::CreateSnapShot(AttributeEntry* CurrAttrs)
05638 
05639     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
05640     Created:    16/10/95
05641     Inputs:     CurrAttrs = a pointer to a list of attributeentry items. There as usual 
05642                             should be AttributeManager::NumAttributes() of them
05643     Returns:    TRUE if a snap shot has been created
05644                 FALSE if not
05645     Purpose:    Take a snap shot of the attribute list described by CurrAttrs
05646 
05647 *********************************************************************************************/
05648 
05649 BOOL SnapShotList::CreateSnapShot(AttributeEntry* CurrAttrs)
05650 {
05651     SnapShotItem* pItem = new SnapShotItem;
05652     if (pItem==NULL)
05653         return FALSE;
05654 
05655     if (!pItem->Initialise(CurrAttrs))
05656     {
05657         delete pItem;
05658         return FALSE;
05659     }
05660 
05661     SnapShot.AddTail(pItem);
05662     return TRUE;
05663 }
05664 
05665 
05666 /********************************************************************************************
05667 
05668 >   void SnapShotList::DestroySnapShot()
05669 
05670     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
05671     Created:    16/10/95
05672     Inputs:     -
05673     Returns:    -
05674     Purpose:    Destroy the last snap shot taken by CreateSnapShot()
05675 
05676 *********************************************************************************************/
05677 
05678 void SnapShotList::DestroySnapShot()
05679 {
05680     SnapShotItem* pItem = (SnapShotItem*)SnapShot.RemoveTail();
05681     if (pItem==NULL)
05682     {
05683         ERROR3("underflow in SnapShotList::DestroySnapShot()");
05684         return;
05685     }        
05686         
05687     delete pItem;
05688 }
05689 
05690 
05691 /********************************************************************************************
05692 
05693 >   BOOL SnapShotList::ApplyChangedAttrs(Node* pNode, AttributeEntry* CurrAttrs)
05694 
05695     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
05696     Created:    16/10/95
05697     Inputs:     -
05698     Returns:    TRUE if the changed attributes have been applied to pNode
05699                 FALSE if nothing has been applied
05700     Purpose:    This function uses the snapshot facility to work out which of the
05701                 current attributes have changed. Obviously it expects a snap shot to have
05702                 been taken some time earlier. Only those attributes that have changes will be
05703                 applied to the node described on entry. Note, any changed attributes which
05704                 now match defaults will not be applied as the function calls
05705                 ApplyBasedOnDefaults() with the changes list.
05706 
05707 *********************************************************************************************/
05708 
05709 BOOL SnapShotList::ApplyChangedAttrs(Node* pNode, AttributeEntry* CurrAttrs)
05710 {
05711     // check that we have a snap shot attr mask
05712     SnapShotItem* pCurrItem = GetCurrentSnapShot();
05713     if (pCurrItem==NULL)
05714     {
05715         ERROR3("No snap shot taken of the current attributes in SnapShotList::ApplyChangedAttrs()");
05716         return FALSE;
05717     }
05718 
05719     // Now get a set of default attributes so we can use them to reset the
05720     // current values
05721     INT32 i, NumAttrs = AttributeManager::GetNumAttributes();
05722     AttributeEntry *pDefAtts = AttributeManager::GetDefaultAttributes();
05723     if (pDefAtts==NULL)
05724         return FALSE;
05725     
05726     // Alter the list of default attrs we've just created to include the differences
05727     // between our snap shot set and the current attributes described.
05728     for (i=0; i<NumAttrs; i++)
05729     {
05730         pDefAtts[i].Ignore = TRUE;
05731         NodeAttribute* pNodeAtt = pCurrItem->SnapShotAttrs[i];
05732         if (pNodeAtt)
05733         {
05734             AttributeValue* pSavedAttr = pNodeAtt->GetAttributeValue();
05735         
05736             if ((pSavedAttr!=NULL) && (CurrAttrs[i].pAttr->IsDifferent(pSavedAttr)))
05737             {
05738                 pDefAtts[i].pAttr  = CurrAttrs[i].pAttr;
05739                 pDefAtts[i].Temp   = FALSE;
05740                 pDefAtts[i].Ignore = FALSE;
05741             }
05742         }
05743     }
05744 
05745     // Now apply the attribute list we have built
05746     BOOL Success = AttributeManager::ApplyBasedOnDefaults(pNode, pDefAtts);
05747     
05748     // finally free up the array we have created and return
05749     CCFree(pDefAtts);
05750     return Success;
05751 }
05752 
05753 
05754 
05755 
05756 /********************************************************************************************
05757 
05758 >   void SnapShotList::PushAttrsBasedOnSnapShot(AttributeEntry* CurrAttrs)
05759 
05760     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
05761     Created:    16/10/95
05762     Inputs:     -
05763     Returns:    -
05764     Purpose:    This function uses the snap shot facility. It checks the snap shot list
05765                 against the current attribute list to find attributes which differ. Those
05766                 that do are obviously new attributes. ie attributes which have been parsed
05767                 by the filter after the snap shot was taken. This function takes the current
05768                 attrubute list and removes all those attributes which have changed in this
05769                 way. It resets them to their default none temp attribute types.
05770 
05771 *********************************************************************************************/
05772 
05773 void SnapShotList::PushAttrsBasedOnSnapShot(AttributeEntry* CurrAttrs)
05774 {
05775     // check that we have a snap shot attr mask
05776     SnapShotItem* pCurrItem = GetCurrentSnapShot();
05777     if (pCurrItem==NULL)
05778     {
05779         ERROR3("No snap shot taken of the current attributes in SnapShotList::PushAttrsBasedOnSnapShot()");
05780         return;
05781     }
05782 
05783     // Now get a set of default attributes so we can use them to reset the
05784     // current values
05785     INT32 i, NumAttrs = AttributeManager::GetNumAttributes();
05786     AttributeEntry *pDefAtts = AttributeManager::GetDefaultAttributes();
05787     if (pDefAtts==NULL)
05788         return;
05789     
05790     for (i=0; i<NumAttrs; i++)
05791     {
05792         pCurrItem->SnapShotAttrsStack[i].pAttr  = NULL;
05793         pCurrItem->SnapShotAttrsStack[i].Temp   = FALSE;
05794         pCurrItem->SnapShotAttrsStack[i].Ignore = TRUE;
05795         
05796         NodeAttribute* pNodeAtt = pCurrItem->SnapShotAttrs[i];
05797         
05798         if (pNodeAtt)
05799         {
05800             AttributeValue* pSavedAttr = pNodeAtt->GetAttributeValue();
05801         
05802             if ((pSavedAttr!=NULL) && (CurrAttrs[i].pAttr->IsDifferent(pSavedAttr)))
05803             {
05804                 // we don't want to apply this attr!
05805                 pCurrItem->SnapShotAttrsStack[i].pAttr  = CurrAttrs[i].pAttr;
05806                 pCurrItem->SnapShotAttrsStack[i].Temp   = CurrAttrs[i].Temp;
05807                 pCurrItem->SnapShotAttrsStack[i].Ignore = CurrAttrs[i].Ignore;  
05808                 
05809                 CurrAttrs[i].pAttr  = pDefAtts[i].pAttr;
05810                 CurrAttrs[i].Temp   = pDefAtts[i].Temp;
05811                 CurrAttrs[i].Ignore = pDefAtts[i].Ignore;
05812             }
05813         }
05814     }
05815 
05816     CCFree(pDefAtts);
05817 }
05818 
05819 
05820 
05821 /********************************************************************************************
05822 
05823 >   void SnapShotList::PopAttrsBasedOnSnapShot(AttributeEntry* CurrAttrs)
05824 
05825     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
05826     Created:    16/10/95
05827     Inputs:     -
05828     Returns:    -
05829     Purpose:    This function uses the snap shot facility. It checks the snap shot list
05830                 against the current attribute list to find attributes which differ. Those
05831                 that do are obviously new attributes. ie attributes which have been parsed
05832                 by the filter after the snap shot was taken. This function takes the current
05833                 attrubute list and removes all those attributes which have changed in this
05834                 way. It resets them to their default none temp attribute types.
05835 
05836 *********************************************************************************************/
05837 
05838 void SnapShotList::PopAttrsBasedOnSnapShot(AttributeEntry* CurrAttrs)
05839 {
05840     // check that we have a snap shot attr mask
05841     SnapShotItem* pCurrItem = GetCurrentSnapShot();
05842     if (pCurrItem==NULL)
05843     {
05844         ERROR3("No snap shot taken of the current attributes in SnapShotList::PopAttrsBasedOnSnapShot()");  
05845         return;
05846     }
05847 
05848     INT32 i, NumAttrs = AttributeManager::GetNumAttributes();
05849     AttributeEntry *pDefAtts = AttributeManager::GetDefaultAttributes();
05850     if (pDefAtts==NULL)
05851         return;
05852     
05853     for (i=0; i<NumAttrs; i++)
05854     {
05855         if (pCurrItem->SnapShotAttrsStack[i].pAttr != NULL)
05856         {
05857             if ( !(CurrAttrs[i].pAttr->IsDifferent(pDefAtts[i].pAttr)) )
05858             {           
05859                 CurrAttrs[i].pAttr  = pCurrItem->SnapShotAttrsStack[i].pAttr;
05860                 CurrAttrs[i].Temp   = pCurrItem->SnapShotAttrsStack[i].Temp;
05861                 CurrAttrs[i].Ignore = pCurrItem->SnapShotAttrsStack[i].Ignore;
05862             }
05863         }
05864     }
05865 
05866     CCFree(pDefAtts);
05867 }
05868 
05869 
05870 
05871 /********************************************************************************************
05872 
05873 >   BOOL Filter::SetTextFont(String_64 *EncodedFont, INT32 Millipoint)
05874 
05875     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
05876     Created:    17/05/95
05877     Returns:    TRUE if the font has been set correctly
05878                 FALSE if an error occured specifying the font
05879     Purpose:    Set the font specified in the encoded font name. The font which actually
05880                 gets set in the attribute stack is one found by GetCompatibleFont(), a super
05881                 new fontmanager call.
05882 
05883 ********************************************************************************************/
05884 
05885 BOOL Filter::SetTextFont(String_64 *EncodedName, INT32 MillFSize)
05886 {
05887     String_64 CompFont;
05888     INT32 Style;
05889     BOOL Bold,Italic;
05890 
05891     // Find a nice compatible font we can use
05892     FONTMANAGER->GetCompatibleFont(*EncodedName, CompFont, Style);
05893     // get the style bits
05894     Bold=((Style & 1) != 0);
05895     Italic=((Style & 2) != 0);
05896 
05897     return SetTextFontStyle(&CompFont, MillFSize, Bold, Italic);
05898 }
05899     
05900 /*  
05901 // This has all moved into the fontmanager, tada!
05902 
05903     if (EncodedName->Sub(String_32("_"),0,0) == 0)
05904         EncodedName->Remove(0,1);
05905 
05906     String_64 TryFont((*EncodedName));
05907     TryFont.SwapChar('-',' ');
05908 
05909     // Try to find the specified font name
05910     INT32 found = FONTMANAGER->DoesFontExist(&TryFont,TRUE,TRUE);
05911     if (found>0)
05912         return SetTextFontStyle(&TryFont, MillFSize, FALSE, FALSE);
05913 
05914     // Ok, if we can't find the whole thing, try decoding
05915     String_64 DecodedName;
05916     INT32 Style = FONTMANAGER->DecodeFontName(*EncodedName, DecodedName);
05917 
05918     // find out what styles this font has
05919     BOOL Bold,Italic;
05920     Bold=((Style & 1) != 0);
05921     Italic=((Style & 2) != 0);
05922 
05923     // if both bold and italic found
05924     if (Bold && Italic)
05925     {
05926         String_64 HoldName(TryFont);
05927         // try to find bold first
05928         INT32 pos = HoldName.Sub(String_32("Italic"),0,0);
05929         HoldName.Remove(pos,6);
05930         found =  FONTMANAGER->DoesFontExist(&HoldName,TRUE,TRUE);
05931         if (found>0)
05932             return SetTextFontStyle(&HoldName, MillFSize, FALSE, TRUE);
05933 
05934         // Then try Italic
05935         HoldName=TryFont;
05936         pos = HoldName.Sub(String_32("Bold"),0,0);
05937         HoldName.Remove(pos,4);
05938         found =  FONTMANAGER->DoesFontExist(&HoldName,TRUE,TRUE);
05939         if (found>0)
05940             return SetTextFontStyle(&HoldName, MillFSize, TRUE, FALSE);
05941     }
05942 
05943     // Does the decoded name exist?, so we can make the rest up in styles?
05944     found =  FONTMANAGER->DoesFontExist(&DecodedName,TRUE,TRUE);
05945     if (found>0)
05946         return SetTextFontStyle(&DecodedName, MillFSize, Bold, Italic);
05947 
05948     // otherwise, we have a font with an extension, eg Trinity.Bold
05949     // (1) Trinity.Bold   - does not exist
05950     // (2) Trinity        - does not exist
05951     // now we set the font to (1), which will be replaced by Times-Roman.
05952     // Now we should also set the font styles too to give us TimesRoman bold
05953     return SetTextFontStyle(&TryFont, MillFSize, Bold, Italic);
05954 }
05955 */
05956 
05957 /********************************************************************************************
05958 
05959 >   BOOL Filter::SetTextFontStyle(String_64 *FName, INT32 MillFSize, BOOL Bold, BOOL Italic)
05960 
05961     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
05962     Created:    17/05/95
05963     Returns:    TRUE if the font and styles have been set
05964                 FALSE if an error occured (out of memory)
05965     Purpose:    This function creates attributes for the typeface, the pointsize, bold and
05966                 italic all at once.
05967 
05968 ********************************************************************************************/
05969 
05970 BOOL Filter::SetTextFontStyle(String_64 *FName, INT32 MillFSize, BOOL Bold, BOOL Italic)
05971 {
05972     if ((FONTMANAGER->CacheNamedFont(FName) == ILLEGALFHANDLE))
05973         return FALSE;
05974 
05975     if (!SetTextTypeFace(FName))
05976         return FALSE;
05977 
05978     if (!SetTextSize(MillFSize))
05979         return FALSE;
05980 
05981     // Build any style definitions we need
05982     if (!SetTextBold(Bold))
05983         return FALSE;
05984 
05985     if (!SetTextItalic(Italic))
05986         return FALSE;
05987 
05988     return TRUE;
05989 }
05990 
05991 
05992 /********************************************************************************************
05993 
05994 >   BOOL Filter::SetTextSize(INT32 Size)
05995 
05996     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
05997     Created:    13/04/94
05998     Inputs:     Size - the new FontSize to use.
05999     Returns:    TRUE if the attribute was changed ok; 
06000                 FALSE otherwise.
06001     Purpose:    Updates the current attribute for TextSize to reflect the value passed 
06002                 in.
06003     Errors:     Out of memory.
06004     SeeAlso:    Filter; Filter::Init
06005 
06006 ********************************************************************************************/
06007 
06008 BOOL Filter::SetTextSize(INT32 Size)
06009 {
06010     // Sanity check
06011     ERROR2IF(CurrentAttrs == NULL, FALSE, "No current attributes in filter!");
06012 
06013     // If we haven't changed this attribute yet, then make a new attribute object for
06014     // our own personal use...
06015     if (!CurrentAttrs[ATTR_TXTFONTSIZE].Temp)
06016     {
06017         // Make the correct attribute value and install it as the current one.
06018         CurrentAttrs[ATTR_TXTFONTSIZE].pAttr = new TxtFontSizeAttribute(Size);
06019         if (CurrentAttrs[ATTR_TXTFONTSIZE].pAttr == NULL)
06020             return FALSE;
06021         CurrentAttrs[ATTR_TXTFONTSIZE].Temp = TRUE;
06022     }
06023     else
06024     {
06025         // We already have an attribute - just change it.
06026         TxtFontSizeAttribute *pAttr = 
06027         (TxtFontSizeAttribute *) CurrentAttrs[ATTR_TXTFONTSIZE].pAttr;
06028         pAttr->FontSize = Size;
06029     }
06030 
06031     // All worked ok.
06032     return TRUE;
06033 }
06034 
06035 
06036 /********************************************************************************************
06037 
06038 >   BOOL Filter::SetTextTypeFace(String_64 * Name, FontClass Class=FC_UNDEFINED)
06039 
06040     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
06041     Created:    13/04/94
06042     Inputs:     Name    - the font name to use when creating a new typeface attribute
06043                 Class   - the class of font this name is supposed to be eg FC_TRUETYPE.
06044                           the class defaults to FC_UDEFINED which means the first font
06045                           cached which matches the font name will be used whatever
06046                           type of font it is.
06047     Returns:    TRUE if the attribute was changed ok; 
06048                 FALSE otherwise.
06049     Purpose:    Updates the current attribute for TextSize to reflect the value passed 
06050                 in.
06051     Errors:     Out of memory.
06052     SeeAlso:    Filter; Filter::Init
06053 
06054 ********************************************************************************************/
06055 
06056 BOOL Filter::SetTextTypeFace(String_64 * Name, FontClass Class)
06057 {
06058     // Sanity check
06059     ERROR2IF(CurrentAttrs == NULL, FALSE, "No current attributes in filter!");
06060 
06061     WORD hTypeface = FONTMANAGER->GetFontHandle(Name, Class);
06062 
06063     // If we haven't changed this attribute yet, then make a new attribute object for
06064     // our own personal use...
06065     if (!CurrentAttrs[ATTR_TXTFONTTYPEFACE].Temp)
06066     {
06067         // Make the correct attribute value and install it as the current one.
06068         CurrentAttrs[ATTR_TXTFONTTYPEFACE].pAttr = new TxtFontTypefaceAttribute(hTypeface);
06069         if (CurrentAttrs[ATTR_TXTFONTTYPEFACE].pAttr == NULL)
06070             return FALSE;
06071         CurrentAttrs[ATTR_TXTFONTTYPEFACE].Temp = TRUE;
06072     }
06073     else
06074     {
06075         // We already have an attribute - just change it.
06076         TxtFontTypefaceAttribute *pAttr = (TxtFontTypefaceAttribute*) CurrentAttrs[ATTR_TXTFONTTYPEFACE].pAttr;
06077         pAttr->HTypeface = hTypeface;
06078         pAttr->IsBold = FALSE;
06079         pAttr->IsItalic = FALSE;
06080     }
06081 
06082     // All worked ok.
06083     return TRUE;
06084 }
06085 
06086 
06087 /********************************************************************************************
06088 
06089 >   BOOL Filter::SetTextBold(BOOL Bold)
06090 
06091     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
06092     Created:    13/04/94
06093     Inputs:     Bold - the new Bold state to use.
06094     Returns:    TRUE if the attribute was changed ok; 
06095                 FALSE otherwise.
06096     Purpose:    Updates the current attribute for Bold to reflect the value passed 
06097                 in.
06098     Errors:     Out of memory.
06099     SeeAlso:    Filter; Filter::Init
06100 
06101 ********************************************************************************************/
06102 
06103 BOOL Filter::SetTextBold(BOOL Bold)
06104 {
06105     // Sanity check
06106     ERROR2IF(CurrentAttrs == NULL, FALSE, "No current attributes in filter!");
06107 
06108     // If we haven't changed this attribute yet, then make a new attribute object for
06109     // our own personal use...
06110     if (!CurrentAttrs[ATTR_TXTBOLD].Temp)
06111     {
06112         // Make the correct attribute value and install it as the current one.
06113         CurrentAttrs[ATTR_TXTBOLD].pAttr = new TxtBoldAttribute(Bold);
06114         if (CurrentAttrs[ATTR_TXTBOLD].pAttr == NULL)
06115             return FALSE;
06116         CurrentAttrs[ATTR_TXTBOLD].Temp = TRUE;
06117     }
06118     else
06119     {
06120         // We already have an attribute - just change it.
06121         TxtBoldAttribute *pAttr = (TxtBoldAttribute*) CurrentAttrs[ATTR_TXTBOLD].pAttr;
06122         pAttr->BoldOn = Bold;
06123     }
06124 
06125     // All worked ok.
06126     return TRUE;
06127 }
06128 
06129 
06130 /********************************************************************************************
06131 
06132 >   BOOL Filter::SetTextItalic(BOOL Italic)
06133 
06134     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
06135     Created:    13/04/94
06136     Inputs:     Italic- the new Italic state to use.
06137     Returns:    TRUE if the attribute was changed ok; 
06138                 FALSE otherwise.
06139     Purpose:    Updates the current attribute for Italic to reflect the value passed 
06140                 in.
06141     Errors:     Out of memory.
06142     SeeAlso:    Filter; Filter::Init
06143 
06144 ********************************************************************************************/
06145 
06146 BOOL Filter::SetTextItalic(BOOL Italic)
06147 {
06148     // Sanity check
06149     ERROR2IF(CurrentAttrs == NULL, FALSE, "No current attributes in filter!");
06150 
06151     // If we haven't changed this attribute yet, then make a new attribute object for
06152     // our own personal use...
06153     if (!CurrentAttrs[ATTR_TXTITALIC].Temp)
06154     {
06155         // Make the correct attribute value and install it as the current one.
06156         CurrentAttrs[ATTR_TXTITALIC].pAttr = new TxtItalicAttribute(Italic);
06157         if (CurrentAttrs[ATTR_TXTITALIC].pAttr == NULL)
06158             return FALSE;
06159         CurrentAttrs[ATTR_TXTITALIC].Temp = TRUE;
06160     }
06161     else
06162     {
06163         // We already have an attribute - just change it.
06164         TxtItalicAttribute *pAttr = (TxtItalicAttribute*) CurrentAttrs[ATTR_TXTITALIC].pAttr;
06165         pAttr->ItalicOn = Italic;
06166     }
06167 
06168     // All worked ok.
06169     return TRUE;
06170 }
06171 
06172 
06173 /********************************************************************************************
06174 
06175 >   BOOL Filter::SetTextUnderline(BOOL Underline)
06176 
06177     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
06178     Created:    13/04/94
06179     Inputs:     Underline - the new Underline state to use.
06180     Returns:    TRUE if the attribute was changed ok; 
06181                 FALSE otherwise.
06182     Purpose:    Updates the current attribute for Underline to reflect the value passed 
06183                 in.
06184     Errors:     Out of memory.
06185     SeeAlso:    Filter; Filter::Init
06186 
06187 ********************************************************************************************/
06188 
06189 BOOL Filter::SetTextUnderline(BOOL Underline)
06190 {
06191     // Sanity check
06192     ERROR2IF(CurrentAttrs == NULL, FALSE, "No current attributes in filter!");
06193 
06194     // If we haven't changed this attribute yet, then make a new attribute object for
06195     // our own personal use...
06196     if (!CurrentAttrs[ATTR_TXTUNDERLINE].Temp)
06197     {
06198         // Make the correct attribute value and install it as the current one.
06199         CurrentAttrs[ATTR_TXTUNDERLINE].pAttr = new TxtUnderlineAttribute(Underline);
06200         if (CurrentAttrs[ATTR_TXTUNDERLINE].pAttr == NULL)
06201             return FALSE;
06202         CurrentAttrs[ATTR_TXTUNDERLINE].Temp = TRUE;
06203     }
06204     else
06205     {
06206         // We already have an attribute - just change it.
06207         TxtUnderlineAttribute *pAttr = (TxtUnderlineAttribute*) CurrentAttrs[ATTR_TXTUNDERLINE].pAttr;
06208         pAttr->Underlined = Underline;
06209     }
06210 
06211     // All worked ok.
06212     return TRUE;
06213 }
06214 
06215 
06216 /********************************************************************************************
06217 
06218 >   BOOL Filter::SetTextAspectRatio(FIXED16 AspectRatio)
06219 
06220     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
06221     Created:    13/04/94
06222     Inputs:     AspectRatio - the new Aspect Ratio to use.
06223     Returns:    TRUE if the attribute was changed ok; 
06224                 FALSE otherwise.
06225     Purpose:    Updates the current attribute for AspectRatio to reflect the value passed 
06226                 in.
06227     Errors:     Out of memory.
06228     SeeAlso:    Filter; Filter::Init
06229 
06230 ********************************************************************************************/
06231 
06232 BOOL Filter::SetTextAspectRatio(FIXED16 AspectRatio)
06233 {
06234     // Sanity check
06235     ERROR2IF(CurrentAttrs == NULL, FALSE, "No current attributes in filter!");
06236 
06237     // If we haven't changed this attribute yet, then make a new attribute object for
06238     // our own personal use...
06239     if (!CurrentAttrs[ATTR_TXTASPECTRATIO].Temp)
06240     {
06241         // Make the correct attribute value and install it as the current one.
06242         CurrentAttrs[ATTR_TXTASPECTRATIO].pAttr = new TxtAspectRatioAttribute(AspectRatio);
06243         if (CurrentAttrs[ATTR_TXTASPECTRATIO].pAttr == NULL)
06244             return FALSE;
06245         CurrentAttrs[ATTR_TXTASPECTRATIO].Temp = TRUE;
06246     }
06247     else
06248     {
06249         // We already have an attribute - just change it.
06250         TxtAspectRatioAttribute *pAttr = (TxtAspectRatioAttribute*) CurrentAttrs[ATTR_TXTASPECTRATIO].pAttr;
06251         pAttr->AspectRatio = AspectRatio;
06252     }
06253 
06254     // All worked ok.
06255     return TRUE;
06256 }
06257 
06258 
06259 /********************************************************************************************
06260 
06261 >   BOOL Filter::SetTextTracking(INT32 Tracking)
06262 
06263     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
06264     Created:    13/04/94
06265     Inputs:     Size - the new FontSize to use.
06266     Returns:    TRUE if the attribute was changed ok; 
06267                 FALSE otherwise.
06268     Purpose:    Updates the current attribute for TextSize to reflect the value passed 
06269                 in.
06270     Errors:     Out of memory.
06271     SeeAlso:    Filter; Filter::Init
06272 
06273 ********************************************************************************************/
06274 
06275 BOOL Filter::SetTextTracking(INT32 Tracking)
06276 {
06277     // Sanity check
06278     ERROR2IF(CurrentAttrs == NULL, FALSE, "No current attributes in filter!");
06279 
06280     // If we haven't changed this attribute yet, then make a new attribute object for
06281     // our own personal use...
06282     if (!CurrentAttrs[ATTR_TXTTRACKING].Temp)
06283     {
06284         // Make the correct attribute value and install it as the current one.
06285         CurrentAttrs[ATTR_TXTTRACKING].pAttr = new TxtTrackingAttribute(Tracking);
06286         if (CurrentAttrs[ATTR_TXTTRACKING].pAttr == NULL)
06287             return FALSE;
06288         CurrentAttrs[ATTR_TXTTRACKING].Temp = TRUE;
06289     }
06290     else
06291     {
06292         // We already have an attribute - just change it.
06293         TxtTrackingAttribute *pAttr = (TxtTrackingAttribute*) CurrentAttrs[ATTR_TXTTRACKING].pAttr;
06294         pAttr->Tracking = Tracking;
06295     }
06296 
06297     // All worked ok.
06298     return TRUE;
06299 }
06300 
06301 
06302 /********************************************************************************************
06303 
06304 >   BOOL Filter::SetTextJustification(Justification Justify)
06305 
06306     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
06307     Created:    13/04/94
06308     Inputs:     Size - the new FontSize to use.
06309     Returns:    TRUE if the attribute was changed ok; 
06310                 FALSE otherwise.
06311     Purpose:    Updates the current attribute for TextSize to reflect the value passed 
06312                 in.
06313     Errors:     Out of memory.
06314     SeeAlso:    Filter; Filter::Init
06315 
06316 ********************************************************************************************/
06317 
06318 BOOL Filter::SetTextJustification(Justification Justify)
06319 {
06320     // Sanity check
06321     ERROR2IF(CurrentAttrs == NULL, FALSE, "No current attributes in filter!");
06322 
06323     // If we haven't changed this attribute yet, then make a new attribute object for
06324     // our own personal use...
06325     if (!CurrentAttrs[ATTR_TXTJUSTIFICATION].Temp)
06326     {
06327         // Make the correct attribute value and install it as the current one.
06328         CurrentAttrs[ATTR_TXTJUSTIFICATION].pAttr = new TxtJustificationAttribute(Justify);
06329         if (CurrentAttrs[ATTR_TXTJUSTIFICATION].pAttr == NULL)
06330             return FALSE;
06331         CurrentAttrs[ATTR_TXTJUSTIFICATION].Temp = TRUE;
06332     }
06333     else
06334     {
06335         // We already have an attribute - just change it.
06336         TxtJustificationAttribute *pAttr = (TxtJustificationAttribute*) CurrentAttrs[ATTR_TXTJUSTIFICATION].pAttr;
06337         pAttr->justification = Justify;
06338     }
06339 
06340     // All worked ok.
06341     return TRUE;
06342 }
06343 
06344 
06345 /********************************************************************************************
06346 
06347 >   BOOL Filter::SetTextLineSpacing(    INT32 Type, 
06348                                         INT32 EMLSpace,
06349                                         MILLIPOINT MLSpace,
06350                                         double DLSpace)
06351 
06352     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
06353     Created:    24/04/94
06354     Inputs:     Type        = the type of linespacing to create (0,1 or 2)
06355                 0 EMLSpace  = linespacing in em's (units related to the current pointsize)
06356                 1 MLSpace   = absolute millipoint line spacing
06357                 2 DLSpace   = propoptional linespacing
06358     Returns:    TRUE if the attribute was changed ok; 
06359                 FALSE otherwise.
06360     Purpose:    Updates the current attribute for line spacing to reflect the value passed 
06361                 in. One of three values will be used depending on the type (as above)
06362     Errors:     Out of memory.
06363     SeeAlso:    Filter; Filter::Init
06364 
06365 ********************************************************************************************/
06366 
06367 BOOL Filter::SetTextLineSpacing(INT32 Type, 
06368                                    INT32 EMLSpace,
06369                                    MILLIPOINT MLSpace,
06370                                    double DLSpace)
06371 {
06372     // Sanity check
06373     ERROR2IF(CurrentAttrs == NULL, FALSE, "No current attributes in filter!");
06374 
06375     INT32 LLSpace=0;
06376     double RLSpace=0;
06377 
06378     switch (Type)
06379     {
06380         case 0:
06381         {
06382             // Use the default size.
06383             INT32 FSize = 19200;
06384             // Need to convert the linespacing to a sensible millipoint value
06385             if (CurrentAttrs[ATTR_TXTFONTSIZE].Temp)
06386             {
06387                 // We already have an attribute - just change it.
06388                 TxtFontSizeAttribute *pAttr = (TxtFontSizeAttribute*) CurrentAttrs[ATTR_TXTFONTSIZE].pAttr;
06389                 FSize = pAttr->FontSize;
06390             }
06391             // Convert line space to millipoints.
06392             double LS = (double)EMLSpace;
06393             LLSpace = (INT32)((LS*FSize/1000)+0.5);
06394             break;
06395          }
06396 
06397         case 1:
06398             LLSpace = MLSpace;
06399             break;
06400         
06401         case 2:
06402             RLSpace = DLSpace;
06403             break;
06404     }
06405 
06406     // If we haven't changed this attribute yet, then make a new attribute object for
06407     // our own personal use...
06408     if (!CurrentAttrs[ATTR_TXTLINESPACE].Temp)
06409     {
06410         // Make the correct attribute value and install it as the current one.
06411         CurrentAttrs[ATTR_TXTLINESPACE].pAttr = new TxtLineSpaceAttribute();
06412         if (CurrentAttrs[ATTR_TXTLINESPACE].pAttr == NULL)
06413             return FALSE;
06414         CurrentAttrs[ATTR_TXTLINESPACE].Temp = TRUE;
06415     }
06416 
06417     // Get a pointer to the attribute and set its new values
06418     TxtLineSpaceAttribute *pAttr = (TxtLineSpaceAttribute*) CurrentAttrs[ATTR_TXTLINESPACE].pAttr;
06419 
06420     switch (Type)
06421     {
06422         case 0:
06423         case 1:
06424             pAttr->IsRatio = FALSE;
06425             pAttr->Value = LLSpace;
06426             pAttr->Ratio = FIXED16(0);
06427             break;
06428         
06429         case 2:
06430             pAttr->IsRatio = TRUE;
06431             pAttr->Value = 0;
06432             pAttr->Ratio = RLSpace;
06433             break;
06434     }   
06435 
06436     // All worked ok.
06437     return TRUE;
06438 }
06439 
06440 
06441 /********************************************************************************************
06442 
06443 >   BOOL Filter::SetTextBaseLine(MILLIPOINT BaseShift)
06444 
06445     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
06446     Created:    24/04/94
06447     Inputs:     BaseShift - the new baseline shift to use.
06448     Returns:    TRUE if the attribute was changed ok; 
06449                 FALSE otherwise.
06450     Purpose:    Updates the current attribute for BaseLine shift to reflect the value passed 
06451                 in.
06452     Errors:     Out of memory.
06453     SeeAlso:    Filter; Filter::Init
06454 
06455 ********************************************************************************************/
06456 
06457 BOOL Filter::SetTextBaseLine(MILLIPOINT BaseShift)
06458 {
06459     // Sanity check
06460     ERROR2IF(CurrentAttrs == NULL, FALSE, "No current attributes in filter!");
06461 
06462     // If we haven't changed this attribute yet, then make a new attribute object for
06463     // our own personal use...
06464     if (!CurrentAttrs[ATTR_TXTBASELINE].Temp)
06465     {
06466         // Make the correct attribute value and install it as the current one.
06467         CurrentAttrs[ATTR_TXTBASELINE].pAttr = new TxtBaseLineAttribute(BaseShift);
06468         if (CurrentAttrs[ATTR_TXTBASELINE].pAttr == NULL)
06469             return FALSE;
06470         CurrentAttrs[ATTR_TXTBASELINE].Temp = TRUE;
06471     }
06472     else
06473     {
06474         // We already have an attribute - just change it.
06475         TxtBaseLineAttribute *pAttr = (TxtBaseLineAttribute*) CurrentAttrs[ATTR_TXTBASELINE].pAttr;
06476         pAttr->Value = BaseShift;
06477     }
06478 
06479     // All worked ok.
06480     return TRUE;
06481 }
06482 
06483 
06484 /********************************************************************************************
06485 
06486 >   BOOL Filter::SetTextScript(INT32 rise, INT32 pointsize)
06487 
06488     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
06489     Created:    24/04/94
06490     Inputs:     rise = signed rise in millipoints away from the baseline
06491                 pointsize = size of font to use in millipoints 
06492     Returns     TRUE if the attribute was changed ok
06493                 FALSE otherwise.
06494     Purpose:    Updates the current attribute for subscript or superscript
06495     Errors:     Out of memory.
06496     SeeAlso:    Filter; Filter::Init
06497 
06498 ********************************************************************************************/
06499 
06500 BOOL Filter::SetTextScript(INT32 rise, INT32 pointsize)
06501 {
06502     // Sanity check
06503     ERROR2IF(CurrentAttrs == NULL, FALSE, "No current attributes in filter!");
06504 
06505     // ignore any crazy values
06506     if (pointsize<=0)
06507         return TRUE;
06508 
06509     // Use the default size.
06510     INT32 fsize = 19200;
06511     if (CurrentAttrs[ATTR_TXTFONTSIZE].Temp)
06512     {
06513         TxtFontSizeAttribute *pAttr = (TxtFontSizeAttribute*) CurrentAttrs[ATTR_TXTFONTSIZE].pAttr;
06514         fsize = pAttr->FontSize;
06515     }
06516 
06517     double tr = (double)rise/(double)fsize;
06518     double tp = (double)pointsize/(double)fsize;
06519     FIXED16 offset(tr);
06520     FIXED16 size(tp);
06521 
06522     // If we haven't changed this attribute yet, then make a new attribute object for
06523     // our own personal use...
06524     if (!CurrentAttrs[ATTR_TXTSCRIPT].Temp)
06525     {
06526         // Make the correct attribute value and install it as the current one.
06527         CurrentAttrs[ATTR_TXTSCRIPT].pAttr = new TxtScriptAttribute(offset,size);
06528         if (CurrentAttrs[ATTR_TXTSCRIPT].pAttr == NULL)
06529             return FALSE;
06530         CurrentAttrs[ATTR_TXTSCRIPT].Temp = TRUE;
06531     }
06532     else
06533     {
06534         // We already have an attribute - just change it.
06535         CurrentAttrs[ATTR_TXTSCRIPT].Ignore = FALSE;
06536         TxtScriptAttribute *pAttr = (TxtScriptAttribute*) CurrentAttrs[ATTR_TXTSCRIPT].pAttr;
06537         pAttr->Offset = offset;
06538         pAttr->Size = size;
06539     }
06540 
06541     // All worked ok.
06542     return TRUE;
06543 }
06544 
06545 
06546 /********************************************************************************************
06547 
06548 >   BOOL Filter::RemoveTextScript()
06549 
06550     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
06551     Created:    26/04/94
06552     Inputs:     -
06553     Returns     TRUE if the attribute was removed
06554                 FALSE otherwise.
06555     Purpose:    Removes any script attribute which is currently active
06556     Errors:     Out of memory.
06557     SeeAlso:    
06558 
06559 ********************************************************************************************/
06560 
06561 BOOL Filter::RemoveTextScript()
06562 {
06563     // Sanity check
06564     ERROR2IF(CurrentAttrs == NULL, FALSE, "No current attributes in filter!");
06565 
06566     // if a script attribute exists, delete it.
06567     if (CurrentAttrs[ATTR_TXTSCRIPT].Temp)
06568         CurrentAttrs[ATTR_TXTSCRIPT].Ignore = TRUE;
06569     return TRUE;
06570 }
06571 
06572 
06573 /********************************************************************************************
06574 
06575 >   BOOL Filter::SetTextBoldFont(BOOL Bold)
06576 
06577     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
06578     Created:    13/06/95
06579     Returns:    TRUE if the font and style has been set
06580                 FALSE if an error occured (out current typeface)
06581     Purpose:    This function simply sets the bold style flag in the current
06582                 font typeface attribute (to be applied to the next created character).
06583 
06584 ********************************************************************************************/
06585 
06586 BOOL Filter::SetTextBoldFont(BOOL Bold)
06587 {
06588     // Sanity check
06589     ERROR2IF(CurrentAttrs == NULL, FALSE, "No current attributes in filter!");
06590 
06591     // If there is no current typeface then we cannot set its style
06592     if (!CurrentAttrs[ATTR_TXTFONTTYPEFACE].Temp)
06593         return FALSE;
06594 
06595     // There is an attribute - just change it.
06596     TxtFontTypefaceAttribute *pAttr = (TxtFontTypefaceAttribute*) CurrentAttrs[ATTR_TXTFONTTYPEFACE].pAttr;
06597     pAttr->IsBold = Bold;
06598 
06599     return TRUE;
06600 }
06601 
06602 
06603 /********************************************************************************************
06604 
06605 >   BOOL Filter::SetTextItalicFont(BOOL Italic)
06606 
06607     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
06608     Created:    13/06/95
06609     Returns:    TRUE if the font and style has been set
06610                 FALSE if an error occured (no current typeface)
06611     Purpose:    This function simply sets the italic style flag in the current
06612                 font typeface attribute (to be applied to the next created character).
06613 
06614 ********************************************************************************************/
06615 
06616 BOOL Filter::SetTextItalicFont(BOOL Italic)
06617 {
06618     // Sanity check
06619     ERROR2IF(CurrentAttrs == NULL, FALSE, "No current attributes in filter!");
06620 
06621     // If there is no current typeface then we cannot set its style
06622     if (!CurrentAttrs[ATTR_TXTFONTTYPEFACE].Temp)
06623         return FALSE;
06624 
06625     // There is an attribute - just change it.
06626     TxtFontTypefaceAttribute *pAttr = (TxtFontTypefaceAttribute*) CurrentAttrs[ATTR_TXTFONTTYPEFACE].pAttr;
06627     pAttr->IsItalic = Italic;
06628 
06629     return TRUE;
06630 }
06631 
06632 
06633 
06634 /********************************************************************************************
06635 >   Filter* FilterManager::FindFilterFromID(const UINT32 FilterID) const
06636 
06637     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com> (moved into this class by Graham 7/7/97)
06638     Created:    10/12/96
06639     Purpose:    Provides the Filter given its ID
06640 
06641                 (This function is also in Filter Manager. Unfortunately, having it there
06642                 means that every time you use it you have to get a pointer to the
06643                 application, then use that to get a pointer to the filter manager, then
06644                 use that pointer to call this function. So I've copied it here for
06645                 convenience)
06646 ********************************************************************************************/
06647 
06648 Filter* Filter::FindFilterFromID(const UINT32 FilterID)
06649 {
06650     Filter             *pFilter;
06651     for( pFilter = Filter::GetFirst();
06652          pFilter != 0;
06653          pFilter = Filter::GetNext(pFilter))
06654             if (pFilter->FilterID == FilterID)
06655             {
06656                 ERROR3IF(FilterID == FILTERID_NONE,
06657                             "Filter::FindFilterFromID: filter has _R(ID_NONE)?");
06658                 break;
06659             }
06660 
06661     return pFilter;
06662 }
06663 
06664 
06665 
06666 /*********************************************************************************************
06667 >   AttrRecordItem::AttrRecordItem()
06668 
06669     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
06670     Created:    1/12/95
06671     Purpose:    Constructor - initalises member variables
06672 **********************************************************************************************/  
06673 AttrRecordItem::AttrRecordItem()
06674 {
06675     RecordedAttrs = NULL;
06676 }
06677 
06678 
06679 /*********************************************************************************************
06680 >    AttrRecordItem::~AttrRecordItem()
06681 
06682      Author:    Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
06683      Created:   1/12/95
06684      Purpose:   Destructor - deletes any claimed memory
06685 **********************************************************************************************/  
06686 AttrRecordItem::~AttrRecordItem()
06687 {
06688     // Free the AttributeEntry array
06689     if (RecordedAttrs != NULL)
06690         CCFree(RecordedAttrs);
06691 }
06692 
06693 
06694 /*********************************************************************************************
06695 >   BOOL AttrRecordItem::Initialise(AttributeEntry* pCurrAttrs)
06696 
06697     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
06698     Created:    1/12/95
06699     Inputs:     pCurrAttrs - an AttributeEntry array
06700     Outputs:    -
06701     Returns:    TRUE/FALSE for success/failure
06702     Purpose:    Copies the current AttributeValues in the AttributeEntry array so the current
06703                 state can be restored at a later date
06704 **********************************************************************************************/  
06705 BOOL AttrRecordItem::Initialise(AttributeEntry* pCurrAttrs)
06706 {
06707     const INT32 NumAttrs = AttributeManager::GetNumAttributes();
06708 
06709     // Claim memory for copy of AttributeEntry array
06710     RecordedAttrs = (AttributeEntry*)CCMalloc(NumAttrs*sizeof(AttributeEntry));
06711     if (RecordedAttrs==NULL)
06712         return FALSE;
06713 
06714     // store the temp values
06715     for (INT32 i=0; i<NumAttrs; i++)
06716     {
06717         // Get the runtime class info on this object and create another object of that type
06718         CCRuntimeClass *pCCRuntimeClass = pCurrAttrs[i].pAttr->GetRuntimeClass();
06719         AttributeValue *pNewAttr = (AttributeValue *) pCCRuntimeClass->CreateObject();
06720         if (pNewAttr == NULL)
06721             return FALSE;
06722 
06723         // Object created ok - get the object to copy its contents across.
06724         pNewAttr->SimpleCopy(pCurrAttrs[i].pAttr);
06725         RecordedAttrs[i].pAttr = pNewAttr;
06726     }
06727 
06728     return TRUE;
06729 }
06730 
06731 
06732 /*********************************************************************************************
06733 >   BOOL AttrRecordItem::Restore(AttributeEntry* pCurrAttrs)
06734 
06735     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
06736     Created:    1/12/95
06737     Inputs:     pCurrAttrs - an AttributeEntry array
06738     Outputs:    -
06739     Returns:    TRUE/FALSE for success/failure
06740     Purpose:    Copies the stored attribute state back into the current attribute array
06741 **********************************************************************************************/  
06742 BOOL AttrRecordItem::Restore(AttributeEntry* pCurrAttrs)
06743 {
06744     const INT32 NumAttrs = AttributeManager::GetNumAttributes();
06745 
06746     for (INT32 i=0; i<NumAttrs; i++)
06747     {
06748         if (RecordedAttrs[i].pAttr != NULL)
06749         {
06750             pCurrAttrs[i].pAttr->SimpleCopy(RecordedAttrs[i].pAttr);
06751             delete RecordedAttrs[i].pAttr;
06752             RecordedAttrs[i].pAttr = NULL;
06753         }
06754     }
06755 
06756     return TRUE;
06757 }
06758 
06759 
06760 /*********************************************************************************************
06761 >   AttrRecordList::AttrRecordList()
06762 
06763     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
06764     Created:    1/12/95
06765     Purpose:    Constructor - initalises member variables
06766 **********************************************************************************************/  
06767 AttrRecordList::AttrRecordList()
06768 {
06769 }
06770 
06771 
06772 /*********************************************************************************************
06773 >    AttrRecordItem::~AttrRecordItem()
06774 
06775      Author:    Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
06776      Created:   1/12/95
06777      Purpose:   Destructor - deletes any claimed memory
06778 **********************************************************************************************/  
06779 AttrRecordList::~AttrRecordList()
06780 {
06781 }
06782 
06783 
06784 /*********************************************************************************************
06785 >   BOOL AttrRecordList::SaveContext(AttributeEntry* pCurrAttrs)
06786 
06787     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
06788     Created:    1/12/95
06789     Inputs:     pCurrAttrs - an AttributeEntry array
06790     Outputs:    -
06791     Returns:    TRUE/FALSE for success/failure
06792     Purpose:    Stores the current state of the attribute entry array
06793 **********************************************************************************************/  
06794 BOOL AttrRecordList::SaveContext(AttributeEntry* pCurrAttrs)
06795 {
06796     // Create a new record
06797     AttrRecordItem* pItem = new AttrRecordItem;
06798     if (pItem==NULL)
06799         return FALSE;
06800 
06801     // Copy the attributes into it
06802     if (!pItem->Initialise(pCurrAttrs))
06803     {
06804         delete pItem;
06805         return FALSE;
06806     }
06807     else
06808     {
06809         AttrRecord.AddTail(pItem);
06810         return TRUE;
06811     }
06812 }
06813 
06814 
06815 /*********************************************************************************************
06816 >   BOOL AttrRecordList::RestoreContext(AttributeEntry* pCurrAttrs)
06817 
06818     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
06819     Created:    1/12/95
06820     Inputs:     pCurrAttrs - an AttributeEntry array
06821     Outputs:    -
06822     Returns:    TRUE/FALSE for success/failure
06823     Purpose:    Returns the current attribute array back to the stored state
06824 **********************************************************************************************/  
06825 BOOL AttrRecordList::RestoreContext(AttributeEntry* pCurrAttrs)
06826 {
06827     AttrRecordItem* pItem = (AttrRecordItem*)AttrRecord.RemoveTail();
06828     ERROR2IF(pItem == NULL, FALSE, "Record list empty");
06829     pItem->Restore(pCurrAttrs);
06830     delete pItem;
06831 
06832     return TRUE;
06833 }

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