cdrfiltr.cpp

Go to the documentation of this file.
00001 // $Id: cdrfiltr.cpp 1282 2006-06-09 09:46:49Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 // *********CDR file filter
00099 
00100 /*
00101 */
00102 
00103 // this line disables extrudes as they don't *quite* work yet - corel still need some
00104 // interegation about what's going on. It seems the object is pre-transformed by some
00105 // random values. Weird. #define this to include the stuff.
00106 #undef CDR_DOEXTRUDES
00107 
00108 #include "camtypes.h"
00109 #include "cdrfiltr.h"
00110 //#include "oilfltrs.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 //#include "ben.h"
00112 //#include "ccfile.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 #include "progress.h"
00114 #include "cdrcol.h"
00115 #include "rifffile.h"
00116 #include "cdrform.h"
00117 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00118 #include "nodepath.h"
00119 //#include "group.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00120 #include "page.h"
00121 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00122 #include "nodershp.h"
00123 //#include "resource.h"
00124 //#include "fixst256.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00125 #include "ndoptmz.h"
00126 #include "collist.h"
00127 #include "layer.h"
00128 #include "sglayer.h"
00129 #include "sprdmsg.h"
00130 #include "nodebmp.h"
00131 #include "nodetxts.h"
00132 //#include "textinfo.h"
00133 #include "zoomops.h"
00134 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00135 #include "nodemold.h"
00136 #include "moldshap.h"
00137 #include "ndmldpth.h"
00138 #include "nodemldr.h"
00139 //#include "nev.h"
00140 #include "fontman.h"
00141 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00142 //#include "cmxres.h"
00143 #include "cmxifltr.h"       // so we can pass stuff to it nicely
00144 
00145 DECLARE_SOURCE("$Revision: 1282 $");
00146 
00147 CC_IMPLEMENT_DYNAMIC(CDRFilter, VectorFilter)
00148 CC_IMPLEMENT_MEMDUMP(CDRAttributeStore, List)
00149 CC_IMPLEMENT_MEMDUMP(CDRAttributeStoredItem, ListItem)
00150 CC_IMPLEMENT_MEMDUMP(CDRArrowheadStore, List)
00151 CC_IMPLEMENT_MEMDUMP(CDRArrowheadStoredItem, ListItem)
00152 CC_IMPLEMENT_MEMDUMP(CDRBitmapStore, List)
00153 CC_IMPLEMENT_MEMDUMP(CDRBitmapStoredItem, ListItem)
00154 CC_IMPLEMENT_MEMDUMP(CDRVectorStore, List)
00155 CC_IMPLEMENT_MEMDUMP(CDRVectorStoredItem, ListItem)
00156 CC_IMPLEMENT_MEMDUMP(CDRFontnameStore, List)
00157 CC_IMPLEMENT_MEMDUMP(CDRFontnameStoredItem, ListItem)
00158 CC_IMPLEMENT_MEMDUMP(CDRLayerList, List)
00159 CC_IMPLEMENT_MEMDUMP(CDRLayerListItem, ListItem)
00160 CC_IMPLEMENT_MEMDUMP(CDRPageList, List)
00161 CC_IMPLEMENT_MEMDUMP(CDRPageListItem, ListItem)
00162 CC_IMPLEMENT_MEMDUMP(CDRActionList, List)
00163 CC_IMPLEMENT_DYNAMIC(CDRActionListItem, ListItem)
00164 CC_IMPLEMENT_DYNAMIC(CDRActionTransform, CDRActionListItem)
00165 CC_IMPLEMENT_DYNAMIC(CDRActionGroupEnd, CDRActionListItem)
00166 CC_IMPLEMENT_MEMDUMP(CDRTransformConvertor, CC_CLASS_MEMDUMP)
00167 CC_IMPLEMENT_MEMDUMP(CDRTransformConvertor5, CDRTransformConvertor)
00168 CC_IMPLEMENT_MEMDUMP(CDRTransformConvertor4, CDRTransformConvertor)
00169 CC_IMPLEMENT_MEMDUMP(CDRTransformConvertor3, CDRTransformConvertor)
00170 CC_IMPLEMENT_MEMDUMP(CDRTextOnPathLink, ListItem)
00171 
00172 
00173 #define new CAM_DEBUG_NEW
00174 
00175 #define PROGRESSUPDATE_MASK 0x7f
00176 
00177 INT32 CDRFilter::BitmapNumber = 0;
00178 INT32 CDRFilter::PatternNumber = 0;
00179 
00180 /********************************************************************************************
00181 
00182 >   static void CDRFilter::UpdateProgress(BOOL Now = FALSE)
00183 
00184     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00185     Created:    22 03 95
00186     Inputs:     None
00187     Returns:    None
00188     Purpose:    Updating the progress everysooften - called at every significant place
00189                 to get a nice smooth update on that progress bar thingy
00190     SeeAlso:    Filter
00191 
00192 ********************************************************************************************/
00193 
00194 BOOL CDRFilter::UpdateProgress(BOOL Now)
00195 {
00196     BOOL Result = TRUE;
00197     
00198     if(Now)
00199     {
00200         Result = ContinueSlowJob(RIFF->ProgressNow());
00201         ProgressCount = 0;
00202     }
00203     else
00204     {
00205         if((ProgressCount & PROGRESSUPDATE_MASK) == 0) {
00206             Result = ContinueSlowJob(RIFF->ProgressNow());
00207         }
00208 
00209         ProgressCount++;
00210     }
00211 
00212     if(!Result)
00213     {
00214         Error::ClearError();        // because this may not be handled the first time around
00215         Error::SetError(_R(IDN_USER_CANCELLED));
00216     }
00217     
00218     return Result;
00219 }
00220 
00221 /********************************************************************************************
00222 
00223 >   CDRFilter::CDRFilter(void)
00224 
00225     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00226     Created:    21 03 95
00227     Inputs:     As for the Filter class
00228     Returns:    As for the Filter class
00229     Purpose:    Constructor
00230     SeeAlso:    Filter
00231 
00232 ********************************************************************************************/
00233 
00234 CDRFilter::CDRFilter(void)
00235 {
00236     // Set up filter descriptions.
00237     FilterName.Load(_R(IDT_CDRFILTER_FILTERNAME));
00238     FilterInfo.Load(_R(IDT_CDRFILTER_FILTERINFO));
00239     FilterID = FILTERID_CDR;
00240 
00241     Flags.CanImport = TRUE;
00242     Flags.CanExport = FALSE;
00243 
00244     Version = CDRVERSION_NULL;
00245 }
00246 
00247 
00248 /********************************************************************************************
00249 
00250 >   BOOL CDRFilter::Init(void)
00251 
00252     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00253     Created:    21 03 95
00254     Inputs:     As for the Filter class
00255     Returns:    As for the Filter class
00256     Purpose:    Initialisation
00257     SeeAlso:    Filter
00258 
00259 ********************************************************************************************/
00260 
00261 BOOL CDRFilter::Init(void)
00262 {
00263     // Get the OILFilter object
00264     pOILFilter = new CDROILFilter(this);
00265     if (pOILFilter == NULL)
00266         return FALSE;
00267 
00268     // make sure we'll complain about life if HowCompatable isn't called
00269     Version  = CDRVERSION_NULL;
00270 
00271     // All ok
00272     return TRUE;
00273 }
00274 
00275 /********************************************************************************************
00276 
00277 >   INT32 CDRFilter::HowCompatible(PathName& Filename, ADDR  HeaderStart,
00278         UINT32 HeaderSize, UINT32 FileSize)
00279 
00280     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00281     Created:    21 03 95
00282     Inputs:     As for the Filter class
00283     Returns:    As for the Filter class
00284     Purpose:    Examines a file to see how compatable it is with this filter.
00285     SeeAlso:    Filter
00286 
00287 ********************************************************************************************/
00288 
00289 INT32 CDRFilter::HowCompatible(PathName& Filename, ADDR  HeaderStart,
00290         UINT32 HeaderSize, UINT32 FileSize)
00291 {
00292 PORTNOTE("byteorder", "TODO: Check byte ordering")
00293     BOOL ExtensionMatches = pOILFilter->DoesExtensionOfPathNameMatch(&Filename);
00294 
00295     // check for version 2 files if the extension matches...
00296     if (ExtensionMatches)
00297     {
00298         if(camStrncmp((char *)HeaderStart, "WL", 2) == 0)
00299             return 10;          // a version 2.xx CDR file
00300     }
00301 
00302     // check for version 3 - 5 files...
00303     FOURCC FormType;
00304 
00305     FormType = RIFFFile::CheckRIFFHeader(HeaderStart, FileSize);
00306 
00307     Version  = CDRVERSION_NULL;
00308     
00309     switch (FormType)
00310     {
00311         case cdrT_CDR:
00312             Version = CDRVERSION_3;
00313             break;
00314         
00315         case cdrT_CDR4:
00316         case cdrT_CDST:         // version 4 template
00317             Version = CDRVERSION_4;
00318             break;
00319 
00320         case cdrT_CDR5:
00321         case cdrT_CDT5:
00322             Version = CDRVERSION_5;
00323             break;
00324 
00325         case cdrT_CDR6:
00326         case cdrT_CDT6:
00327             Version = CDRVERSION_6;
00328             break;
00329 
00330         default:
00331             break;
00332     }
00333 
00334     INT32 HowMuchWeLikedThisFile = 0;
00335 
00336     if(Version != CDRVERSION_NULL)
00337     {
00338         HowMuchWeLikedThisFile = 10;        // loved the file
00339 
00340         // check to see if there is a CMX file embedded in there
00341         if(HasCDRFileGotCMXFile(&Filename))
00342         {
00343             HowMuchWeLikedThisFile = 5;     // didn't like it so much then -- let the CMX filter grab it
00344         }
00345     }
00346 
00347     return HowMuchWeLikedThisFile;
00348 }
00349 
00350 /********************************************************************************************
00351 
00352 >   BOOL CDRFilter::DoImport(SelOperation *Op, CCLexFile *pDiskFile, Document *DestDoc, 
00353         BOOL AutoChosen, ImportPosition *Pos,
00354         KernelBitmap** ppImportedBitmap, DocCoord* pPosTranslate, String_256* URL)
00355 
00356     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00357     Created:    21 03 95
00358     Inputs:     As for the Filter class
00359     Returns:    As for the Filter class
00360     Purpose:    Does the import of a CDR (.cdr or .cdt)
00361     SeeAlso:    Filter
00362 
00363 ********************************************************************************************/
00364 
00365 #define CDRFILTER_DI_RETURNERROR {Success = FALSE; return ClearUp();}
00366 
00367 BOOL CDRFilter::DoImport(SelOperation *Op, CCLexFile *pDiskFile, Document *DestDoc, 
00368         BOOL AutoChosen, ImportPosition *Pos,
00369         KernelBitmap** ppImportedBitmap, DocCoord* pPosTranslate, String_256* URL)
00370 {
00371     // check to see if we've got a CMX file in there, but only if we weren't autochosen
00372     if(!AutoChosen && HasCDRFileGotCMXFile(NULL, pDiskFile))
00373     {
00374         TRACEUSER( "Ben", _T(">>> loading CDR file with new CMXImportFilter\n"));
00375         // right, somehow we got here -- probably because the user specifically
00376         // asked to see CorelDRAW files only
00377         CMXImportFilter *pFilter = new CMXImportFilter;
00378 
00379         if(pFilter == NULL)
00380             return FALSE;
00381 
00382         BOOL ok = pFilter->DoImport(Op, pDiskFile, DestDoc, AutoChosen, Pos);
00383 
00384         delete pFilter;
00385         pFilter = NULL;
00386 
00387         return ok;
00388     }
00389 
00390     // normal CDR import stuff
00391     BOOL ExtensionMatches = pOILFilter->DoesExtensionOfFileMatch(pDiskFile);
00392 
00393     RIFFFile RIFFo;
00394 
00395 TRACEUSER( "Ben", _T("In CDRFilter::DoImport\n"));
00396     //ERROR2IF(Version == CDRVERSION_NULL, FALSE, "CDRFilter::HowCompatible failed to set recognised version\n");
00397 
00398     // in debug builds, warn about fills hanging around
00399     ERROR3IF(Fills.IsEmpty() == FALSE, "Fills store not empty");
00400     ERROR3IF(Outlines.IsEmpty() == FALSE, "Outlines store not empty");
00401     ERROR3IF(Styles.IsEmpty() == FALSE, "Styles store not empty");
00402     ERROR3IF(Fonts.IsEmpty() == FALSE, "Fonts store not empty");
00403     ERROR3IF(Arrowheads.IsEmpty() == FALSE, "Arrowheads store not empty");
00404     ERROR3IF(Patterns.IsEmpty() == FALSE, "Patterns store not empty");
00405     ERROR3IF(Bitmaps.IsEmpty() == FALSE, "Bitmap store not empty");
00406     ERROR3IF(Vectors.IsEmpty() == FALSE, "Vector store not empty");
00407     ERROR3IF(TextBBoxes.IsEmpty() == FALSE, "TextBBoxes list not empty");
00408     ERROR3IF(TextV4.IsEmpty() == FALSE, "TextV4 store not empty");
00409     ERROR3IF(TextOnPathLinks.IsEmpty() == FALSE, "TextOnPathLinks not empty");
00410 
00411     // in retail builds, just vape any contents
00412     Fills.DeleteAll();
00413     Outlines.DeleteAll();
00414     Styles.DeleteAll();
00415     Fonts.DeleteAll();
00416     Arrowheads.DeleteAll();
00417     Patterns.DeleteAll();
00418     Bitmaps.DeleteAll();
00419     Vectors.DeleteAll();
00420     TextV4.DeleteAll();
00421     Pages.DeleteAll();
00422     Actions.DeleteAll();
00423     TextBBoxes.DeleteAll();
00424     TextOnPathLinks.DeleteAll();
00425 
00426     // set a few flags and initialise some variables
00427     pDocument = DestDoc;
00428     Success = TRUE;
00429     SlowJobStarted = FALSE;
00430     TranslateByX = 0;
00431     TranslateByY = 0;
00432     PageX = 0;
00433     PageY = 0;
00434     pLevelNodeList = 0;
00435     DoneDoc = FALSE;
00436     DoneMasterPage = FALSE;
00437     InMasterPage = FALSE;
00438     ThisPage = 0;
00439     ThisLayer = 0;
00440     pMadeNode = 0;
00441     ObjectsConverted = 0;
00442     ObjectsFormatWrong = 0;
00443     ObjectsUnknown = 0;
00444     EnvelopesApproximated = 0;
00445     ObjDataBlock = 0;
00446     ObjDataBlockSize = 0;
00447     AttrsAlreadyApplied = FALSE;
00448     TransformChunk = 0;
00449     FontTableV3 = 0;
00450     FontStylesV3 = 0;
00451     LinkTable = 0;
00452     ThisOp = Op;
00453     LinkTransformsExist = FALSE;
00454     TheDocument = DestDoc;
00455 
00456     // if the extension matches, check it for being a 2.xx file
00457     if(ExtensionMatches)
00458     {
00459         // get the first few bytes
00460         TCHAR FirstBit[8];
00461 
00462         if(pDiskFile->read((void *)FirstBit, sizeof(FirstBit)).bad())
00463             return FALSE;
00464 
00465         ERROR1IF(camStrncmp((char *)FirstBit, "WL", 2) == 0, FALSE, _R(IDT_CDRFILTER_ISAV2FILE));
00466     
00467         // let's pop the file back to the beginning
00468         if(pDiskFile->seek(0).bad())
00469             return FALSE;
00470     }
00471 
00472     // sort out the RIFF file
00473     RIFF = &RIFFo;
00474 
00475     FOURCC FormType = RIFF->Init(pDiskFile);
00476 
00477     if(FormType == 1)       // error
00478     {
00479         CDRFILTER_DI_RETURNERROR;
00480     }
00481     
00482     // sort out which version we're on
00483     switch(FormType)
00484     {
00485         case cdrT_CDR:
00486             Version = CDRVERSION_3;
00487             break;
00488         
00489         case cdrT_CDR4:
00490         case cdrT_CDST:         // version 4 template
00491             Version = CDRVERSION_4;
00492             break;
00493 
00494         case cdrT_CDR5:
00495         case cdrT_CDT5:
00496             Version = CDRVERSION_5;
00497             break;
00498 
00499         case cdrT_CDR6:
00500         case cdrT_CDT6:
00501             // version 6 file -- we don't support these
00502             ERROR1(FALSE, _R(IDE_CDRFILTER_CDR6));
00503             break;
00504 
00505         default:
00506 TRACEUSER( "Ben", _T("Attempted to load something which wasn't a CDR file. I don't think so..."));
00507             ERROR1(FALSE, _R(IDE_CDRFILTER_NOTCDR));
00508             break;
00509     }
00510 
00511     // sort out a colour list
00512     ColList = DestDoc->GetIndexedColours();
00513     
00514     // do we want to import with layers?
00515     UseLayers = FALSE;
00516 #ifdef WEBSTER
00517     // In Webster, just use the default preference settings as these should be set to
00518     // ImportWithLayers to False.
00519     if (
00520         (!DestDoc->IsImporting() && Filter::OpenWithLayers) ||
00521         (DestDoc->IsImporting() && Filter::ImportWithLayers)
00522         )
00523         UseLayers = TRUE;
00524 #else
00525     // In Camelot, we must check to see if the document is being imported and if so if
00526     // there are any frames present. If there are then don't use layers, if there are
00527     // then use the preference setting.
00528     if (DestDoc->IsImporting())
00529     {
00530         Spread * pTheSpread = DestDoc->GetSelectedSpread();
00531         Layer * pFrame = NULL;
00532         if (pTheSpread != NULL)
00533             pFrame = pTheSpread->FindFirstFrameLayer();
00534         if (pFrame != NULL)
00535             UseLayers = FALSE;                      // Frames present so do not import layers
00536         else
00537             UseLayers = Filter::ImportWithLayers;   // No frames so use the preference setting
00538     }
00539     else
00540     {
00541         UseLayers = Filter::OpenWithLayers;
00542     }
00543 #endif
00544 
00545     // If importing without layers, make sure there is a layer to put things on, and make one if not
00546     if(UseLayers == FALSE)
00547     {
00548         if (!MakeSureLayerExists(DestDoc))
00549         {
00550             // clean up and return and error
00551             CDRFILTER_DI_RETURNERROR;
00552         }
00553     }
00554 
00555     // For now, position Draw objects on 1st page of spread 1
00556     pSpread = DestDoc->GetSelectedSpread();
00557     pPage = (Page *) pSpread->FindFirstPageInSpread();
00558     
00559     // Use bottom left of page as origin
00560     DocRect PageRect = pPage->GetPageRect();
00561     Origin = PageRect.lo;
00562 
00563     // OK, let's get into the swing of things!
00564     
00565     // Get a default set of attributes for ink objects.
00566     if (!SetUpCurrentAttrs())
00567         return FALSE;
00568 
00569     // Let start off by setting the progress indicatorx
00570     UINT32 id;
00571     switch(Version)
00572     {
00573         case CDRVERSION_4:  id = _R(IDT_IMPORTMSG_CDR4);    break;
00574         case CDRVERSION_5:  id = _R(IDT_IMPORTMSG_CDR5);    break;
00575         default:            id = _R(IDT_IMPORTMSG_CDR3);    break;
00576     }
00577     if(!DestDoc->IsImporting())
00578         id += _R(IDT_OPENMSG_CDR3) - _R(IDT_IMPORTMSG_CDR3);
00579     //String_64 ImportMessage(id);
00580     String_64 ImportMessage = GetImportProgressString(pDiskFile, id);
00581     
00582     // this slow job doesn't have a delay because if the CDR file has a bitmap at the
00583     // beginning, ContinueSlowJob can't be called for rather a long time (sometimes)
00584     // and you get 'Nothing Selected' instead of a message telling you what's happening.
00585     BeginSlowJob(RIFF->ProgressLimit(), FALSE, &ImportMessage);
00586     SlowJobStarted = TRUE;
00587 
00588     // loop through looking at top level lists, and dispatch them to various handlers
00589     do
00590     {
00591         // get the next object in the file
00592         if(!RIFF->NextObject())
00593             CDRFILTER_DI_RETURNERROR;
00594 
00595         if(RIFF->GetObjType() == RIFFOBJECTTYPE_LISTSTART)
00596         {
00597             switch(RIFF->GetObjChunkType())
00598             {
00599                 case cdrT_doc:
00600                     if(!ProcessDoc())
00601                     {
00602 TRACEUSER( "Ben", _T("ProcessDoc returned FALSE\n"));
00603                         CDRFILTER_DI_RETURNERROR;
00604                     }
00605                     break;
00606 
00607                 case cdrT_page:
00608                     if(!ProcessPage())
00609                     {
00610 TRACEUSER( "Ben", _T("ProcessPage returned FALSE\n"));
00611                         CDRFILTER_DI_RETURNERROR;
00612                     }
00613                     break;
00614 
00615                 default:
00616                     // we're not interested in any other root level list, so skip it
00617                     if(!RIFF->SkipToListEnd(RIFF->GetObjLevel()))
00618                         CDRFILTER_DI_RETURNERROR;
00619                     break;
00620             }
00621         }
00622 
00623         if(!UpdateProgress())
00624             return FALSE;
00625     } while(RIFF->GetObjType() != RIFFOBJECTTYPE_FILEEND);
00626 
00627     // make sure we're at the end
00628     ContinueSlowJob(RIFF->ProgressLimit());
00629 
00630     // attach paths to text stories
00631     if(!AttachTextToPaths())
00632         return FALSE;
00633 
00634     // only stick objects into the document if some were converted
00635     if(ObjectsConverted > 0)
00636     {
00637     
00638         // check that there were at least two pages
00639         if(Pages.GetCount() < 1)
00640         {
00641     TRACEUSER( "Ben", _T("not enough pages in file\n"));
00642             CDRFILTER_DI_RETURNERROR;
00643         }
00644     
00645         // get the pointer to the list of levels on the master pages
00646         CDRLayerList *MasterLayers;
00647         CDRPageListItem *En = (CDRPageListItem *)Pages.GetHead();
00648 
00649         if(En == 0)
00650             CDRFILTER_DI_RETURNERROR;
00651 
00652         MasterLayers = &En->Layers;
00653     
00654         // get the list of levels on the actual page
00655         CDRLayerList *PageLayers;
00656         En = (CDRPageListItem *)Pages.GetNext(En);
00657 
00658         if(Version != CDRVERSION_3)
00659         {
00660             if(En == 0)
00661                 CDRFILTER_DI_RETURNERROR;
00662 
00663             PageLayers = &En->Layers;
00664 
00665             // check that they have the same number of layers in their lists
00666             if(MasterLayers->GetCount() != PageLayers->GetCount())
00667             {
00668         TRACEUSER( "Ben", _T("not the same number of layers on master page and on page\n"));
00669                 CDRFILTER_DI_RETURNERROR;
00670             }
00671         } else
00672         {
00673             PageLayers = 0;
00674         }
00675 
00676         if(MasterLayers->GetCount() <= 0)
00677             CDRFILTER_DI_RETURNERROR;
00678 
00679         // if it's a CDR 3 file set the page size and translation things
00680         if(Version == CDRVERSION_3)
00681         {
00682             // set the page size?
00683             if(!DestDoc->IsImporting() && PageX > 0 && PageY > 0)
00684             {
00685 // Make the pasteboard an extra page width either side of the page and an extra
00686 // half page height above and below the page. That should be nicely proportional.
00687 
00688                 INT32 ms = (PageX > PageY)?PageX:PageY;
00689     
00690                 // we're opening the file, so set the page size
00691                 if (pSpread)
00692                 {
00693                     BOOL ok = pSpread->SetPageSize(PageX, PageY, ms, 0, FALSE, TRUE);
00694                     // Must set the origin of the grid to the bottom left corner of the
00695                     // union rectangle of all pages on the spread as this is where the x,y
00696                     // measurements are made from.
00697                     DocRect PagesRect;
00698                     NodeGrid* pGrid = pSpread->FindFirstDefaultGridInSpread();
00699                     ok = ok && pSpread->GetPagesRect(&PagesRect);
00700                     if (pGrid)
00701                         pGrid->SetOrigin(PagesRect.lox, PagesRect.loy);
00702                     
00703                     if (!ok)
00704                         CDRFILTER_DI_RETURNERROR;
00705                 }
00706             }
00707         
00708             DocRect PageRect = pPage->GetPageRect();
00709             Origin = PageRect.lo;
00710 
00711             TranslateByX = Origin.x + (PageX / 2);
00712             TranslateByY = Origin.y + (PageY / 2);
00713         }
00714 
00715         // set up pointers to the layers
00716         CDRLayerListItem *MasterEn = (CDRLayerListItem *)MasterLayers->GetTail();
00717         CDRLayerListItem *PageEn = 0;
00718         if(PageLayers != 0)
00719             PageEn = (CDRLayerListItem *)PageLayers->GetTail();
00720 
00721         EndSlowJob();
00722         BeginSlowJob();
00723 
00724         // insert everything into the document
00725         if(UseLayers)
00726         {
00727             // go through inserting every layer which has sometime on it
00728             while(MasterEn != 0)
00729             {
00730                 // check to see if we have objects to import
00731                 if(MasterEn->Objects != 0 || (PageEn != 0 && PageEn->Objects != 0))
00732                 {
00733                     // OK, we've got some objects to import, create a layer to put them in
00734                     Layer *pLayer = new Layer();
00735 
00736                     if(pLayer == 0)
00737                         CDRFILTER_DI_RETURNERROR;
00738 
00739                     // set it's name and attributes
00740                     pLayer->SetLayerID(MasterEn->Name);
00741                     pLayer->SetVisible(MasterEn->IsVisible);
00742                     pLayer->SetLocked(MasterEn->IsLocked);
00743                     pLayer->SetActive(FALSE);
00744                     pLayer->SetPrintable(TRUE);
00745                     pLayer->SetBackground(FALSE);
00746                     pLayer->SetOutline(FALSE);
00747 
00748                     // stick objects below it
00749                     Node *Objects = 0;
00750 
00751                     if(MasterEn->Objects != 0)
00752                     {
00753                         Objects = MasterEn->Objects;
00754                         MasterEn->LayerInDocument = TRUE;
00755                     }
00756                     else
00757                     {
00758                         Objects = PageEn->Objects;
00759                         PageEn->LayerInDocument = TRUE;
00760                     }
00761 
00762                     ERROR3IF(Objects == 0, "Er, tried to make a layer for objects which didn't exist");
00763 
00764                     // attach the objects to the layer
00765                     Objects->InsertChainSimple(pLayer, FIRSTCHILD);
00766 
00767                     // if it's a CDR 3 file and translate it
00768                     if(Version == CDRVERSION_3)
00769                     {
00770                         Trans2DMatrix Trans(TranslateByX, TranslateByY);
00771                         pLayer->Transform(Trans);
00772                     }
00773                     
00774                     // insert the layer...
00775                     if (!Op->DoInsertNewNode(pLayer, (Node *)pSpread, LASTCHILD, TRUE))
00776                     {
00777                         // It didn't work - delete the sub-tree we just created
00778                         pLayer->CascadeDelete();
00779                         delete pLayer;
00780                         pLayer = NULL;
00781                         CDRFILTER_DI_RETURNERROR;
00782                     }
00783 
00784                     // make sure it's name is unique
00785                     pLayer->EnsureUniqueLayerID();
00786                     
00787                     // ... and finally optimise it's attributes
00788                     if(!pLayer->OptimiseAttributes())
00789                         CDRFILTER_DI_RETURNERROR;
00790                 }
00791     
00792                 // get the next (previous) layer to import
00793                 MasterEn = (CDRLayerListItem *)MasterLayers->GetPrev(MasterEn);
00794                 if(PageEn != 0)
00795                     PageEn = (CDRLayerListItem *)PageLayers->GetPrev(PageEn);
00796             }       
00797 
00798             // get the insertation node set up
00799             DestDoc->ResetInsertionPosition();
00800         }
00801         else 
00802         {
00803             // get a group node to put everything in as we're not using layers here.
00804             NodeGroup *pGroup = new NodeGroup;
00805             if(pGroup == 0)
00806                 CDRFILTER_DI_RETURNERROR;
00807     
00808             // run through the layers putting in the stuff - remember they're in reverse order
00809             while(MasterEn != 0)
00810             {
00811         TRACEUSER( "Ben", _T("Putting layer '%s' into document\n"), (TCHAR *)MasterEn->Name);       
00812         
00813                 // put the master pages objects onto this group
00814                 if(MasterEn->Objects != 0)
00815                 {
00816                     MasterEn->Objects->InsertChainSimple(pGroup, LASTCHILD);
00817         
00818                     MasterEn->LayerInDocument = TRUE;
00819                 }
00820 
00821                 // put the page objects into this group
00822                 if(PageEn != 0 && PageEn->Objects != 0)
00823                 {
00824                     PageEn->Objects->InsertChainSimple(pGroup, LASTCHILD);
00825 
00826                     PageEn->LayerInDocument = TRUE;
00827                 }
00828 
00829         
00830                 // get the next (previous) layer to import
00831                 MasterEn = (CDRLayerListItem *)MasterLayers->GetPrev(MasterEn);
00832                 if(PageEn != 0)
00833                     PageEn = (CDRLayerListItem *)PageLayers->GetPrev(PageEn);
00834             }
00835 
00836             // if it's a CDR 3 file translate it
00837             if(Version == CDRVERSION_3)
00838             {
00839                 Trans2DMatrix Trans(TranslateByX, TranslateByY);
00840                 pGroup->Transform(Trans);
00841             }
00842 
00843             // check to see if the group node has more than one child
00844             // if it doesn't just insert the child and not the group, and then
00845             // delete the group node afterwards
00846             NodeRenderableBounded *InsertNode = pGroup;
00847 
00848             NodeRenderableBounded *FirstChild = (NodeRenderableBounded *)pGroup->FindFirstChild();
00849 
00850             if(FirstChild != 0)
00851             {
00852                 // if the first child hasn't got a sibling, then there's only one
00853                 // child to the group, so just insert the child
00854                 if(FirstChild->FindNext() == 0)
00855                     InsertNode = FirstChild;
00856             }
00857 
00858             // and slap the group into the document
00859             if (!Op->DoInsertNewNode(InsertNode, pSpread, TRUE))
00860             {
00861                 // It didn't work - delete the sub-tree we just created
00862                 pGroup->CascadeDelete();
00863                 delete pGroup;
00864                 pGroup = NULL;
00865                 CDRFILTER_DI_RETURNERROR;
00866             }
00867 
00868             if(InsertNode != pGroup)
00869                 delete pGroup;
00870 
00871             // optimise the attributes in our nice new group
00872             if(!InsertNode->OptimiseAttributes())
00873                 CDRFILTER_DI_RETURNERROR;
00874         }
00875     }
00876     else
00877     {
00878         // if we were opening the document, then we need make a layer and set the insertation node
00879         if(!DestDoc->IsImporting())
00880         {
00881             if (!MakeSureLayerExists(DestDoc))
00882                 CDRFILTER_DI_RETURNERROR;
00883 
00884             DestDoc->ResetInsertionPosition();
00885         }
00886     }
00887 
00888     // add some standard colours
00889     if(!AddStandardColourSet(pDocument))
00890         CDRFILTER_DI_RETURNERROR;
00891 
00892     // do a quick post import on it
00893     DestDoc->PostImport();
00894     
00895     // find out how many dodgy objects were encountered along the way
00896     INT32 ObjNotConv = ObjectsFormatWrong + ObjectsUnknown;
00897 
00898     if(ObjNotConv > 0)
00899     {
00900         // tell the user that some objects couldn't be converted
00901         String_256 WarnMsg;
00902         WarnMsg.MakeMsg((ObjNotConv == 1)?_R(IDT_CDRFILTER_OBJWARNING1):_R(IDT_CDRFILTER_OBJWARNING), ObjNotConv);
00903         Error::SetError(0, WarnMsg, 0);
00904         InformWarning();
00905         Error::ClearError();
00906     }
00907 
00908     if(EnvelopesApproximated > 0)
00909     {
00910         // tell the user that some envelopes were approximated
00911         String_256 WarnMsg;
00912         WarnMsg.MakeMsg((EnvelopesApproximated == 1)?_R(IDT_CDRFILTER_ENVAPPROXWARNING1):_R(IDT_CDRFILTER_ENVAPPROXWARNING), EnvelopesApproximated);
00913         Error::SetError(0, WarnMsg, 0);
00914         InformWarning();
00915         Error::ClearError();
00916     }
00917 
00918 TRACEUSER( "Ben", _T("Do import finished\n"));
00919     return ClearUp();
00920 }
00921 
00922 /********************************************************************************************
00923 
00924 >   BOOL CDRFilter::ProcessDoc(void)
00925 
00926     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00927     Created:    22 03 95
00928     Inputs:     none
00929     Returns:    error flag
00930     Purpose:    Processes the root level doc chunk of a CDR file
00931     SeeAlso:    Filter
00932 
00933 ********************************************************************************************/
00934 
00935 BOOL CDRFilter::ProcessDoc(void)
00936 {
00937     BOOL InFillTable = FALSE;
00938     BOOL InOutlineTable = FALSE;
00939     BOOL InStyleTable = FALSE;
00940     BOOL InFontTable = FALSE;
00941     BOOL InArrowheadTable = FALSE;
00942     BOOL InPatternTable = FALSE;
00943     BOOL InBitmapTable = FALSE;
00944     BOOL GotPageInfo = FALSE;
00945 
00946     ADDR VectorListContents = 0;
00947     INT32 VectorListContentsSize;
00948 
00949 TRACEUSER( "Ben", _T("In ProcessDoc\n"));
00950 
00951     // store the level we're working on
00952     UINT32 StartLevel = RIFF->GetObjLevel();
00953 
00954     do
00955     {
00956         switch(RIFF->GetObjType())
00957         {
00958             case RIFFOBJECTTYPE_LISTSTART:
00959                 // list start - attributes are stored in lists
00960                 switch(RIFF->GetObjChunkType())
00961                 {
00962                     case cdrT_filt:     InFillTable = TRUE;         break;
00963                     case cdrT_otlt:     InOutlineTable = TRUE;      break;
00964                     case cdrT_stlt:     InStyleTable = TRUE;        break;
00965                     case cdrT_fntt:     InFontTable = TRUE;         break;
00966                     case cdrT_arrt:     InArrowheadTable = TRUE;    break;
00967                     case cdrT_bpft:     InPatternTable = TRUE;      break;
00968                     case cdrT_bmpt:     InBitmapTable = TRUE;       break;
00969                     default:                                        break;
00970 
00971                     case cdrT_vect:
00972                         // get the contents of this list for later
00973                         if(!RIFF->GetListContents(&VectorListContents, &VectorListContentsSize))
00974                             return FALSE;
00975 
00976                         // and skip to the end of it
00977                         if(!RIFF->SkipToListEnd(RIFF->GetObjLevel()))
00978                             return FALSE;
00979                         break;
00980                     
00981                     case cdrT_btxt:
00982                         if(Version == CDRVERSION_4)
00983                         {
00984                             // if we're in a version 4 file, this contains text for the paragraph text objects
00985                             if(!ProcessTextList4())
00986                                 return FALSE;
00987                         }
00988                         break;
00989                 }
00990                 break;
00991 
00992             case RIFFOBJECTTYPE_LISTEND:
00993                 switch(RIFF->GetObjChunkType())
00994                 {
00995                     case cdrT_filt:     InFillTable = FALSE;        break;
00996                     case cdrT_otlt:     InOutlineTable = FALSE;     break;
00997                     case cdrT_stlt:     InStyleTable = FALSE;       break;
00998                     case cdrT_fntt:     InFontTable = FALSE;        break;
00999                     case cdrT_arrt:     InArrowheadTable = FALSE;   break;
01000                     case cdrT_bpft:     InPatternTable = FALSE;     break;
01001                     case cdrT_bmpt:     InBitmapTable = FALSE;      break;
01002                     default:                                        break;
01003                 }
01004                 break;
01005 
01006             case RIFFOBJECTTYPE_CHUNK:
01007                 // got a chunk to be interested about!
01008                 switch(RIFF->GetObjChunkType())
01009                 {
01010                     case cdrT_fill:
01011                         if(InFillTable)
01012                             Fills.AddChunkToStore(RIFF);
01013                         break;
01014 
01015                     case cdrT_outl:
01016                         if(InOutlineTable)
01017                             Outlines.AddChunkToStore(RIFF);
01018                         break;
01019 
01020                     case cdrT_styd:
01021                         if(InStyleTable)
01022                             Styles.AddChunkToStore(RIFF);
01023                         break;
01024 
01025                     case cdrT_font:
01026                         if(InFontTable)
01027                             Fonts.AddChunkToStore(RIFF, Version);
01028                         break;
01029 
01030                     case cdrT_arrw:
01031                         if(InArrowheadTable)
01032                             Arrowheads.AddChunkToStore(RIFF);
01033                         break;
01034 
01035                     case cdrT_bmpf:
01036                         if(InPatternTable)
01037                             Patterns.AddChunkToStore(RIFF, TRUE, this);
01038 
01039                         UpdateProgress(TRUE);
01040                         break;
01041 
01042                     case cdrT_bmp:
01043                         // a couple of forced progress updates here to ensure a
01044                         // resonably often updated progress bar
01045                         UpdateProgress(TRUE);
01046 
01047                         if(InBitmapTable)
01048                             Bitmaps.AddChunkToStore(RIFF, FALSE, this);
01049 
01050                         UpdateProgress(TRUE);
01051                         break;
01052 
01053                     case cdrT_mcfg:
01054                         {   // get the chunk and read the page size
01055                             if(GotPageInfo)     // if we've already got it, then there's a problem with the file
01056                             {
01057 TRACEUSER( "Ben", _T("mcfg chunk encountered twice in doc list\n"));                                
01058                                 ERROR1(FALSE, _R(IDE_CDRFILTER_FORMATERROR));
01059                             }
01060 
01061                             if(!RIFF->AquireChunkData())
01062                                 return FALSE;
01063 
01064                             cdrfPageInfo *i = (cdrfPageInfo *)RIFF->GetAquiredData();
01065 
01066                             ERROR3IF(i == 0, "No aquired data returned from RIFF chunk");
01067 
01068                             PageX = CDRDATA_WORD(i->PageX) * CDRCOORDS_TO_MILLIPOINTS;
01069                             PageY = CDRDATA_WORD(i->PageY) * CDRCOORDS_TO_MILLIPOINTS;
01070                             Landscape = (CDRDATA_WORD(i->Orientation) == cdrf_ORIENTATION_LANDSCAPE)?TRUE:FALSE;
01071 
01072                             GotPageInfo = TRUE;
01073                         }
01074                         break;
01075 
01076                     case cdrT_tspc:     // font style table for version 3
01077                         if(Version == CDRVERSION_3)
01078                         {
01079                             // store the font styles
01080                             if((FontStylesV3 = (ADDR)CCMalloc(RIFF->GetObjSize())) == 0)
01081                                 return FALSE;
01082 
01083                             if(!RIFF->GetChunkData(FontStylesV3, RIFF->GetObjSize()))
01084                                 return FALSE;
01085                         }
01086                         break;
01087 
01088                     case cdrT_ftbl:     // font name table for version 3
01089                         if(Version == CDRVERSION_3)
01090                         {
01091                             // store the font names
01092                             if((FontTableV3 = (ADDR)CCMalloc(RIFF->GetObjSize())) == 0)
01093                                 return FALSE;
01094 
01095                             if(!RIFF->GetChunkData(FontTableV3, RIFF->GetObjSize()))
01096                                 return FALSE;
01097 
01098                             // store number of entries
01099                             FontTableEntriesV3 = RIFF->GetObjSize() / sizeof(cdrfFontTableEntryV3);
01100                             
01101                             // cache the font names
01102                             cdrfFontTableEntryV3 *FT = (cdrfFontTableEntryV3 *)FontTableV3;
01103                             for(INT32 l = 0; l < FontTableEntriesV3; l++)
01104                             {
01105                                 if(FT[l].Name[0] != '\0' && FT[l].Name[0] != ' ')
01106                                 {
01107                                     //GetApplication()->GetFontManager()->CacheNamedFont(&String_64((TCHAR *)&FT[l].Name));
01108                                 
01109                                     Fonts.AddFontToStore(FT[l].Reference, (TCHAR *)&FT[l].Name);
01110                                 }
01111                             }
01112 
01113                         }
01114                         break;
01115 
01116                     case cdrT_lnkt:
01117                         // store the link table - it's a pretty useful piece of kit
01118                         if((LinkTable = (ADDR)CCMalloc(RIFF->GetObjSize())) == 0)
01119                             return FALSE;
01120 
01121                         if(!RIFF->GetChunkData(LinkTable, RIFF->GetObjSize()))
01122                             return FALSE;
01123 
01124                         // generate the links from paths to text text from it
01125                         if(!MakeTextOnPathLinkList())
01126                             return FALSE;
01127                         break;
01128 
01129                     default:
01130                         break;
01131                 }
01132                 break;
01133 
01134             default:
01135                 break;
01136         }
01137         UpdateProgress();
01138         
01139         if(!RIFF->NextObject())
01140             return FALSE;
01141         
01142         ERROR3IF(RIFF->GetObjType() == RIFFOBJECTTYPE_FILEEND, "Unexpected end of RIFF file in ProcessDoc");
01143     } while(RIFF->GetObjType() != RIFFOBJECTTYPE_LISTEND || RIFF->GetObjLevel() > StartLevel);
01144 
01145     // process the vector list, if we got one
01146     if(VectorListContents != 0)
01147     {
01148         if(!ProcessVectorList(VectorListContents, VectorListContentsSize))
01149         {
01150             CCFree(VectorListContents);
01151             return FALSE;
01152         }
01153 
01154         CCFree(VectorListContents);
01155     }
01156 
01157     // if this isn't a version 3 file, check that we got some page info
01158     if(Version != CDRVERSION_3)
01159     {
01160         if(GotPageInfo == FALSE)
01161         {
01162 TRACEUSER( "Ben", _T("mcfg chunk not found in doc list\n"));
01163             ERROR1(FALSE, _R(IDE_CDRFILTER_FORMATERROR));
01164         
01165         }
01166 
01167         // set the page size?
01168         if(!pDocument->IsImporting() && PageX > 0 && PageY > 0)
01169         {
01170 // Make the pasteboard an extra page width either side of the page and an extra
01171 // half page height above and below the page. That should be nicely proportional.
01172 
01173             INT32 ms = (PageX > PageY)?PageX:PageY;
01174 
01175             // we're opening the file, so set the page size
01176             if (pSpread)
01177             {
01178                 BOOL ok = pSpread->SetPageSize(PageX, PageY, ms, 0, FALSE, TRUE);
01179 
01180                 // Must set the origin of the grid to the bottom left corner of the
01181                 // union rectangle of all pages on the spread as this is where the x,y
01182                 // measurements are made from.
01183                 DocRect PagesRect;
01184                 NodeGrid* pGrid = pSpread->FindFirstDefaultGridInSpread();
01185                 ok = ok && pSpread->GetPagesRect(&PagesRect);
01186                 if (pGrid)
01187                     pGrid->SetOrigin(PagesRect.lox, PagesRect.loy);
01188 
01189                 if (!ok)
01190                     return FALSE;
01191             }
01192         }
01193     
01194         // Use bottom left of page as origin
01195         DocRect PageRect = pPage->GetPageRect();
01196         Origin = PageRect.lo;
01197 
01198         // set the translation variables to position the bottom left hand corner of the page
01199         // at the bottom left hand corner of the page we're importing onto. The origin of
01200         // a CDR file is in the centre of the page
01201         TranslateByX = Origin.x + (PageX / 2);
01202         TranslateByY = Origin.y + (PageY / 2);
01203     }
01204 
01205 TRACEUSER( "Ben", _T("PageX = %d, PageY = %d\n"), PageX, PageY);
01206 
01207     return TRUE;
01208 }
01209 
01210 
01211 /********************************************************************************************
01212 
01213 >   BOOL CDRFilter::ProcessPage(void)
01214 
01215     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01216     Created:    22 03 95
01217     Inputs:     none
01218     Returns:    error flag
01219     Purpose:    Processes a page list of a CDR file
01220     SeeAlso:    Filter
01221 
01222 ********************************************************************************************/
01223 
01224 BOOL CDRFilter::ProcessPage(void)
01225 {
01226 TRACEUSER( "Ben", _T("In ProcessPage\n"));
01227     // first of all, create a new page item in the page list
01228     ERROR3IF(ThisPage != 0, "ThisPage is not null - ProcessPage called in wrong context");
01229     ThisPage = new CDRPageListItem;
01230     
01231     if(ThisPage == 0)
01232         return FALSE;
01233     
01234     // link it into the page list
01235     Pages.AddTail(ThisPage);
01236 
01237     // set the master page flag
01238     if(DoneMasterPage == FALSE)
01239         InMasterPage = TRUE;
01240     
01241     // go through the page list processing the layers
01242         // store the level we're working on
01243     UINT32 StartLevel = RIFF->GetObjLevel();
01244 
01245     do
01246     {
01247         if(RIFF->GetObjType() == RIFFOBJECTTYPE_LISTSTART &&
01248                     RIFF->GetObjChunkType() == cdrT_layr)
01249         {
01250             // it's a layer, process it
01251             if(!ProcessLayer())
01252             {
01253 TRACEUSER( "Ben", _T("ProcessLayer returned FALSE\n"));
01254                 return FALSE;
01255             }
01256         }
01257 
01258         // if we're doing a version 3 file, have we got a page
01259         // size chunk to play with?
01260         if(Version == CDRVERSION_3 && RIFF->GetObjType() == RIFFOBJECTTYPE_CHUNK &&
01261                     RIFF->GetObjChunkType() == cdrT_mcfg)
01262         {
01263             if(!RIFF->AquireChunkData())
01264                 return FALSE;
01265             
01266             cdrfPageInfoV3 *i = (cdrfPageInfoV3 *)RIFF->GetAquiredData();
01267 
01268             // in a CDR 3 file, the page size is half what it should be 
01269             PageX = CDRDATA_WORD(i->PageX) * CDRCOORDS_TO_MILLIPOINTS * 2;
01270             PageY = CDRDATA_WORD(i->PageY) * CDRCOORDS_TO_MILLIPOINTS * 2;
01271             Landscape = FALSE;
01272         }
01273 
01274         UpdateProgress();
01275         
01276         if(!RIFF->NextObject())
01277             return FALSE;
01278         
01279         ERROR3IF(RIFF->GetObjType() == RIFFOBJECTTYPE_FILEEND, "Unexpected end of RIFF file in ProcessDoc");
01280     } while(RIFF->GetObjType() != RIFFOBJECTTYPE_LISTEND || RIFF->GetObjLevel() > StartLevel);
01281 
01282 
01283     // finally make ThisPage as not used
01284     ThisPage = 0;
01285 
01286     // sort out master page flags
01287     if(InMasterPage)
01288     {
01289         InMasterPage = FALSE;
01290         DoneMasterPage = TRUE;
01291     }
01292 
01293 TRACEUSER( "Ben", _T("End ProcessPage\n"));
01294 
01295     return TRUE;
01296 }
01297 
01298 
01299 /********************************************************************************************
01300 
01301 >   BOOL CDRFilter::ProcessLayer(void)
01302 
01303     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01304     Created:    24 03 95
01305     Inputs:     none
01306     Returns:    error flag
01307     Purpose:    Processes a layer list of a CDR file. This is the function which actually
01308                 grabs objects to convert.
01309     SeeAlso:    
01310 
01311 ********************************************************************************************/
01312 
01313 BOOL CDRFilter::ProcessLayer(void)
01314 {
01315 TRACEUSER( "Ben", _T("In ProcessLayer\n")); 
01316     // first of all, create a new layer item in the page list
01317     ERROR3IF(ThisLayer != 0, "ThisLayer is not null - ProcessLayer called in wrong context");
01318     ThisLayer = new CDRLayerListItem;
01319     
01320     if(ThisLayer == 0)
01321         return FALSE;
01322     
01323     // link it into the layer list on the page we're working on
01324     ThisPage->Layers.AddTail(ThisLayer);
01325 
01326     // store the level we're working on
01327     UINT32 StartLevel = RIFF->GetObjLevel();
01328 
01329     ThisLayer->Objects = 0;
01330     ThisLayer->IsVisible = TRUE;
01331     ThisLayer->IsLocked = FALSE;
01332 
01333     // set up the pointer to the node list to add to
01334     ERROR3IF(pLevelNodeList != 0, "Level node list is not empty");
01335     pLevelNodeList = 0;
01336 
01337     // if we're on the master page, find the layer name
01338     if(InMasterPage)
01339     {
01340         BOOL Done = FALSE;
01341         FOURCC LookingFor = (Version == CDRVERSION_3)?cdrT_lobj:cdrT_loda;
01342 
01343         do
01344         {
01345             if(RIFF->GetObjType() == RIFFOBJECTTYPE_CHUNK && RIFF->GetObjChunkType() == LookingFor)
01346             {
01347                 // found the interesting chunk of data
01348                 if(!RIFF->AquireChunkData())
01349                     return FALSE;
01350 
01351                 cdrfMasterLayerInfo *i = (cdrfMasterLayerInfo *)RIFF->GetAquiredData();
01352 
01353                 if(i == 0)      // data couldn't be got
01354                     return FALSE;
01355 
01356                 if(i->Size != RIFF->GetObjSize()) {
01357 TRACEUSER( "Ben", _T("level data in master page has wrong size\n"));
01358                     ERROR1(FALSE, _R(IDE_CDRFILTER_FORMATERROR));
01359                 }
01360 
01361                 // different format of layer info for version 3
01362                 if(Version == CDRVERSION_3)
01363                 {
01364                     cdrfMasterLayerInfoV3 *ii = (cdrfMasterLayerInfoV3 *)RIFF->GetAquiredData();
01365 TRACEUSER( "Ben", _T("name of layer = %s\n"), ii->Name);
01366                     ThisLayer->Name = (char *)ii->Name;
01367                 } else
01368                 {
01369 TRACEUSER( "Ben", _T("name of layer = %s\n"), i->Name);
01370                     ThisLayer->Name = (char *)i->Name;
01371                 }
01372 
01373                 Done = TRUE;
01374             }
01375             else if(RIFF->GetObjType() == RIFFOBJECTTYPE_CHUNK && RIFF->GetObjChunkType() == cdrT_flgs)
01376             {
01377                 // look at the flags of the layer...
01378                 if(!RIFF->AquireChunkData())
01379                     return FALSE;
01380 
01381                 WORD *pFlags = (WORD *)RIFF->GetAquiredData();
01382 
01383                 ERROR3IF(pFlags == 0, "RIFF class shouldn't have done that");
01384 
01385                 INT32 Flags = CDRDATA_WORD(*pFlags);
01386 
01387                 if((Flags & cdrfLAYERFLAGS_INVISIBLE) != 0)
01388                     ThisLayer->IsVisible = FALSE;
01389 
01390                 if((Flags & cdrfLAYERFLAGS_LOCKED) != 0)
01391                     ThisLayer->IsLocked = TRUE;
01392             }
01393 
01394             if(!RIFF->NextObject())
01395                 return FALSE;
01396         
01397         } while(Done == FALSE && (RIFF->GetObjType() != RIFFOBJECTTYPE_LISTEND || RIFF->GetObjLevel() > StartLevel));
01398     
01399         if(Done == FALSE)
01400         {
01401 TRACEUSER( "Ben", _T("Reached level end in master page layer without finding layer attributes\n"));     
01402             ERROR1(FALSE, _R(IDE_CDRFILTER_FORMATERROR));
01403         }
01404     } else {
01405         ThisLayer->Name = "";
01406     }
01407     
01408     // go through the layer list processing the objects
01409     if(!ProcessObjectTree(StartLevel))
01410         return FALSE;
01411 
01412     // put the nodes we got onto the layer we're processing
01413     ThisLayer->Objects = pLevelNodeList;
01414     pLevelNodeList = 0;
01415 
01416     // finally mark ThisLayer as not used
01417     ThisLayer = 0;
01418 
01419 TRACEUSER( "Ben", _T("End ProcessLayer\n"));
01420     return TRUE;
01421 }
01422 
01423 
01424 /********************************************************************************************
01425 
01426 >   BOOL CDRFilter::ProcessObjectTree(void)
01427 
01428     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01429     Created:    19/04/95
01430     Inputs:     the RIFF level the list we're processing starts at
01431     Returns:    error flag
01432     Purpose:    process objects from the CDR file - they end up linked to pLevelNodeList.
01433     SeeAlso:    Filter, CDRFilter::ProcessLayer, CDRFilter::ProcessVectorList
01434 
01435 ********************************************************************************************/
01436 
01437 BOOL CDRFilter::ProcessObjectTree(UINT32 Level)
01438 {
01439     do
01440     {
01441         switch(RIFF->GetObjType())
01442         {
01443             case RIFFOBJECTTYPE_LISTSTART:
01444                 // see if it's anything we're interested in
01445                 switch(RIFF->GetObjChunkType())
01446                 {
01447                     case cdrT_obj:      // found an object
01448                         if(!ProcessObject())
01449                             return FALSE;
01450                         break;
01451 
01452                     
01453                     case cdrT_grp:
01454                         // found a group type objects
01455                         if(!ProcessGroup(RIFF->GetObjLevel()))
01456                             return FALSE;
01457                         break;
01458 
01459                     case cdrT_lnkg:
01460                         // found a link object - treated as the same as a group, but searched for a
01461                         // transformation matrix
01462                         if(!ProcessLink())
01463                             return FALSE;
01464                         break;
01465 
01466                     default:
01467                         break;
01468                 }
01469                 break;
01470 
01471             case RIFFOBJECTTYPE_LISTEND:
01472                 // check to see if any actions are associated with this list end
01473                 if(!Actions.IsEmpty())
01474                 {
01475                     CDRActionListItem *Act, *Previous;
01476 
01477                     Act = (CDRActionListItem *)Actions.GetTail();
01478 
01479                     // perform the actions which end on this level
01480                     while(Act != 0)
01481                     {
01482                         if(Act->GetLevel() >= RIFF->GetObjLevel())
01483                         {
01484                             // the last action ended on this level - perform the action
01485                             if(!Act->DoAction(this))
01486                                 return FALSE;
01487 
01488                             // get the previous item
01489                             Previous = (CDRActionListItem *)Actions.GetPrev(Act);
01490 
01491                             // remove and delete the action we just performed
01492                             delete Actions.RemoveTail();
01493 
01494                             // and set up the pointer to the next action to look at
01495                             Act = Previous;
01496                         } else {
01497                             // the action shouldn't be performed yet - stop looking
01498                             break;
01499                         }
01500                     }
01501                 }
01502                 break;
01503 
01504             default:
01505                 break;
01506         }
01507         
01508         if(!UpdateProgress())
01509             return FALSE;
01510         
01511         if(!RIFF->NextObject())
01512             return FALSE;
01513         
01514         ERROR3IF(RIFF->GetObjType() == RIFFOBJECTTYPE_FILEEND, "Unexpected end of RIFF file in ProcessLayer");
01515 
01516     } while(RIFF->GetObjType() != RIFFOBJECTTYPE_LISTEND || RIFF->GetObjLevel() > Level);
01517 
01518     return TRUE;
01519 }
01520 
01521 
01522 /********************************************************************************************
01523 
01524 >   BOOL CDRFilter::ProcessGroup(UINT32 Level, BOOL FromLink = FALSE)
01525 
01526     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01527     Created:    26 03 95
01528     Inputs:     none
01529     Returns:    error flag
01530     Purpose:    Sets up a group end action and alters the level node list to be a new list
01531     SeeAlso:    
01532 
01533 ********************************************************************************************/
01534 
01535 BOOL CDRFilter::ProcessGroup(UINT32 Level, BOOL FromLink)
01536 {
01537     // if it's a CDR3 file we need a transform action
01538     if(Version == CDRVERSION_3)
01539     {
01540         // see if there's a transform object around
01541         BOOL Found = FALSE;
01542         do {
01543             if(!RIFF->NextObject())
01544                 return FALSE;
01545 
01546             FOURCC id = RIFF->GetObjChunkType();
01547 
01548             // the group need not have a transform chunk, so we've got to be a little careful
01549             if(id == cdrT_grp || id == cdrT_lnkg || id == cdrT_obj)
01550             {
01551                 // oh dear, it didn't - make sure this object we've just run onto is seen again
01552                 RIFF->RepeatCurrent();
01553         
01554                 break;
01555             }
01556 
01557             if(id == cdrT_lobj && RIFF->GetObjType() == RIFFOBJECTTYPE_CHUNK)
01558             {
01559                 // found a transform chunk
01560                 Found = TRUE;
01561             }
01562         } while(Found == FALSE);
01563 
01564         // if there is, set up a post transform action
01565         if(Found)
01566         {
01567 TRACEUSER( "Ben", _T("Setting transform for CDR3 group at level %d\n"), Level);
01568             CDRActionTransform *TAct = new CDRActionTransform;
01569 
01570             if(TAct == 0)
01571                 return FALSE;
01572 
01573             // initialise my new action, giving it the RIFFFile we're using
01574             // it takes the current chunk as it's data.
01575             if(!TAct->Init(RIFF, Version))
01576                 return FALSE;
01577 
01578             // set it to act on the same level ending as the group
01579             TAct->SetLevel(Level);
01580         
01581             // add my new action to the action list
01582             Actions.AddTail(TAct);
01583         }
01584     }
01585     else if(!FromLink)
01586     {
01587         // see if there's a transform chunk, and if there is, whether it's got a non matrix transform in it or not
01588         BOOL Found = FALSE;
01589         do {
01590             if(!RIFF->NextObject())
01591                 return FALSE;
01592 
01593             FOURCC id = RIFF->GetObjChunkType();
01594 
01595             // the group need not have a transform chunk, so we've got to be a little careful
01596             if(id == cdrT_grp || id == cdrT_lnkg || id == cdrT_obj)
01597             {
01598                 // oh dear, it didn't - make sure this object we've just run onto is seen again
01599                 RIFF->RepeatCurrent();
01600         
01601                 break;
01602             }
01603 
01604             if(id == cdrT_trfl && RIFF->GetObjType() == RIFFOBJECTTYPE_LISTSTART)
01605             {
01606                 // found a transform list
01607                 Found = TRUE;
01608             }
01609         } while(Found == FALSE);
01610 
01611         // if there is, set up a post transform action
01612         if(Found)
01613         {
01614             CDRActionTransform *Act = new CDRActionTransform;
01615 
01616             if(Act == 0)
01617                 return FALSE;
01618 
01619             // initialise my new action, giving it the RIFFFile we're using
01620             // it takes the current chunk as it's data.
01621             if(!Act->Init(RIFF, Version))
01622                 return FALSE;
01623 
01624             // check to see if the transform contains a non-matrix thingy
01625             if(IsTransformJustMatrices(Act->Chunk, Act->ChunkSize))
01626             {
01627                 // just matrices - don't do this action
01628                 delete Act;
01629             }
01630             else
01631             {
01632                 // set it to act on the same level ending as the group
01633                 Act->SetLevel(Level);
01634         
01635                 // set it to ignore matrices
01636                 Act->SetIsAGroupTransform(TRUE);
01637 
01638                 // add my new action to the action list
01639                 Actions.AddTail(Act);
01640             }
01641         }
01642     }
01643     
01644     CDRActionGroupEnd *Act = new CDRActionGroupEnd;
01645 
01646     if(Act == 0)
01647         return FALSE;
01648 
01649     // store this levels node list
01650     Act->pOldLevelNodeList = pLevelNodeList;
01651 
01652     // set up the level it's interested in
01653     Act->SetLevel(Level);
01654 
01655     // and start a new level node list for this group
01656     pLevelNodeList = 0;
01657 
01658     Actions.AddTail(Act);
01659 
01660     return TRUE;
01661 }
01662 
01663 
01664 /********************************************************************************************
01665 
01666 >   BOOL CDRActionGroupEnd::DoAction(CDRFilter *C)
01667 
01668     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01669     Created:    26 03 95
01670     Inputs:     none
01671     Returns:    error flag
01672     Purpose:    does some funcky stuff to put objects in a group
01673     SeeAlso:    
01674 
01675 ********************************************************************************************/
01676 
01677 BOOL CDRActionGroupEnd::DoAction(CDRFilter *C)
01678 {
01679     // make sure we have some objects to put in a group
01680     if(C->pLevelNodeList == 0)
01681     {
01682         // restore the pointer
01683         C->pLevelNodeList = pOldLevelNodeList;
01684         // and exit
01685         return TRUE;
01686     }
01687     
01688     // make a new group node
01689     NodeGroup *pGroup = new NodeGroup;
01690 
01691     if(pGroup == 0)
01692         return FALSE;
01693 
01694     // OK, pop everything on the level node list onto this nice new group
01695     C->pLevelNodeList->InsertChainSimple(pGroup, LASTCHILD);
01696 
01697     // restore the old pointer
01698     C->pLevelNodeList = pOldLevelNodeList;
01699 
01700     // and attach!
01701     if(C->pLevelNodeList == 0)
01702     {
01703         C->pLevelNodeList = pGroup;
01704     } else {
01705         pGroup->AttachNode(C->pLevelNodeList, PREV);
01706         C->pLevelNodeList = pGroup; 
01707     }
01708 
01709     // and that's it
01710     return TRUE;
01711 }
01712 
01713 
01714 /********************************************************************************************
01715 
01716 >   void CDRActionGroupEnd::ImportFailure(CDRFilter *C)
01717 
01718     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01719     Created:    26 03 95
01720     Inputs:     none
01721     Returns:    error flag
01722     Purpose:    ensures no memory leaks if the import fails
01723     SeeAlso:    
01724 
01725 ********************************************************************************************/
01726 
01727 void CDRActionGroupEnd::ImportFailure(CDRFilter *C)
01728 {
01729     if(pOldLevelNodeList != 0)
01730     {
01731         // delete all the entries stored in this action
01732         C->DeleteNodeList(pOldLevelNodeList);
01733     }
01734 }
01735 
01736 /********************************************************************************************
01737 
01738 >   BOOL CDRFilter::ProcessLink(void)
01739 
01740     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01741     Created:    26 03 95
01742     Inputs:     none
01743     Returns:    error flag
01744     Purpose:    Sets up a group end action and a post transform action and alters the level
01745                 node list to be a new list
01746     SeeAlso:    
01747 
01748 ********************************************************************************************/
01749 
01750 BOOL CDRFilter::ProcessLink(void)
01751 {
01752     // store the level we're on
01753     UINT32 GroupLevel = RIFF->GetObjLevel();
01754 
01755     // only search for a transform block if this isn't a CDR3 file - ProcessGroup
01756     // takes care of it in that case
01757     if(Version != CDRVERSION_3)
01758     {
01759         // we want to set up the transform object first so that it's done *after* the group end
01760         // object as the transform object acts on the last object converted
01761     
01762         // see if there's a transform object around
01763         BOOL Found = FALSE;
01764         do {
01765             if(!RIFF->NextObject())
01766                 return FALSE;
01767 
01768             FOURCC id = RIFF->GetObjChunkType();
01769 
01770             // the group need not have a transform chunk, so we've got to be a little careful
01771             if(id == cdrT_grp || id == cdrT_lnkg || id == cdrT_obj)
01772             {
01773                 // oh dear, it didn't - make sure this object we've just run onto is seen again
01774                 RIFF->RepeatCurrent();
01775         
01776                 break;
01777             }
01778 
01779             if(id == cdrT_trfl && RIFF->GetObjType() == RIFFOBJECTTYPE_LISTSTART)
01780             {
01781                 // found a transform list
01782                 Found = TRUE;
01783             }
01784         } while(Found == FALSE);
01785 
01786         // if there is, set up a post transform action
01787         if(Found)
01788         {
01789             CDRActionTransform *Act = new CDRActionTransform;
01790 
01791             if(Act == 0)
01792                 return FALSE;
01793 
01794             // initialise my new action, giving it the RIFFFile we're using
01795             // it takes the current chunk as it's data.
01796             if(!Act->Init(RIFF, Version))
01797                 return FALSE;
01798 
01799             // set it to act on the same level ending as the group
01800             Act->SetLevel(GroupLevel);
01801             
01802             // set up link translation things
01803             Act->LinkTrans = TRUE;
01804             LinkTransformsExist = TRUE;
01805         
01806             // add my new action to the action list
01807             Actions.AddTail(Act);
01808         }
01809     }
01810     
01811     // set up a group end action
01812     if(!ProcessGroup(GroupLevel, TRUE))
01813         return FALSE;
01814 
01815     return TRUE;
01816 }
01817 
01818 
01819 /********************************************************************************************
01820 
01821 >   BOOL CDRActionTransform::Init(RIFFFile *RIFF, CDRVersion Version)
01822 
01823     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01824     Created:    27 03 95
01825     Inputs:     none
01826     Returns:    error flag
01827     Purpose:    sets up a transform action - stored given chunk
01828     SeeAlso:    
01829 
01830 ********************************************************************************************/
01831 
01832 BOOL CDRActionTransform::Init(RIFFFile *RIFF, CDRVersion Version)
01833 {
01834     if(Version == CDRVERSION_3)
01835     {
01836         // it's a version 3 file, so get the chunk
01837         ERROR3IF(RIFF->GetObjType() != RIFFOBJECTTYPE_CHUNK, "CDRActionTransform::Init called with RIFFFile in wrong state");
01838 
01839         ERROR3IF(Chunk != 0, "CDRActionTransform::Init called more than once");
01840 
01841         // claim some memory to put the transform in
01842         if((Chunk = (ADDR)CCMalloc(RIFF->GetObjSize())) == 0)
01843             return FALSE;
01844 
01845         // and get the chunk data into this nice block
01846         if(!RIFF->GetChunkData(Chunk, RIFF->GetObjSize()))
01847             return FALSE;
01848     }
01849     else
01850     {
01851         // it's a version 5 file, so get the list contents
01852         ERROR3IF(RIFF->GetObjType() != RIFFOBJECTTYPE_LISTSTART, "CDRActionTransform::Init called with RIFFFile in wrong state");
01853 
01854         ERROR3IF(Chunk != 0, "CDRActionTransform::Init called more than once");
01855     
01856         // get the list contents
01857         if(!RIFF->GetListContents(&Chunk, &ChunkSize))
01858             return FALSE;
01859     }
01860 
01861     // that's it for now
01862     return TRUE;
01863 }
01864 
01865 
01866 /********************************************************************************************
01867 
01868 >   BOOL CDRActionTransform::DoAction(CDRFilter *C)
01869 
01870     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01871     Created:    27 03 95
01872     Inputs:     none
01873     Returns:    error flag
01874     Purpose:    transforms the last object converted
01875     SeeAlso:    
01876 
01877 ********************************************************************************************/
01878 
01879 BOOL CDRActionTransform::DoAction(CDRFilter *C)
01880 {
01881     ERROR3IF(Chunk == 0, "CDRActionTransform not initialised");
01882     
01883     if(LinkTrans)
01884     {
01885         return TRUE;
01886     }
01887     
01888     ADDR Transform = Chunk;
01889 
01890     // if this is a version 3 file we need to find the transform in the data - it's in
01891     // a standard offset header
01892     if(C->Version == CDRVERSION_3)
01893     {
01894         cdrfOffsetHeader *Header = (cdrfOffsetHeader *)Chunk;
01895 
01896         // if there isn't a transform, then we're not worried
01897         if((Transform = C->FindDataInObject(Header, cdrfOBJOFFSETTYPE_TRANSFORM_V3)) == 0)
01898             return TRUE;
01899     }
01900 
01901     // transform the last node created
01902 
01903     // unlink it from the tree first...
01904     Node *pNext = C->pLevelNodeList->FindNext();
01905     C->pLevelNodeList->UnlinkNodeFromTree();
01906 
01907     // we don't want to scale it to translate the origin because it's already been done
01908     if(!LinkTrans && C->pLevelNodeList != 0)
01909         C->TransformConvertedObject(&C->pLevelNodeList, Transform, ChunkSize, FALSE, IsAGroupTransform, TRUE);
01910 
01911     // relink it in
01912     if(pNext != 0)
01913         C->pLevelNodeList->AttachNode(pNext, PREV);
01914     
01915     return TRUE;
01916 }
01917 
01918 
01919 /********************************************************************************************
01920 
01921 >   void CDRActionTransform::ImportFailure(CDRFilter *C)
01922 
01923     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01924     Created:    27 03 95
01925     Inputs:     none
01926     Returns:    error flag
01927     Purpose:    don't actually need to do anything - the chunk will be deleted on object
01928                 destruction
01929     SeeAlso:    
01930 
01931 ********************************************************************************************/
01932 
01933 void CDRActionTransform::ImportFailure(CDRFilter *C)
01934 {
01935 }
01936 
01937 
01938 /********************************************************************************************
01939 
01940 >   CDRActionTransform::~CDRActionTransform
01941 
01942     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01943     Created:    27 03 95
01944     Inputs:     none
01945     Returns:    error flag
01946     Purpose:    destructor
01947     SeeAlso:    
01948 
01949 ********************************************************************************************/
01950 
01951 CDRActionTransform::~CDRActionTransform()
01952 {
01953     CCFree(Chunk);
01954 }
01955 
01956 
01957 /********************************************************************************************
01958 
01959 >   BOOL CDRFiler::ConvertColour(cdrfColour *Col, DocColour *Out)
01960 
01961     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01962     Created:    28 03 95
01963     Inputs:     cdr colour and a DocColour to put it into
01964     Returns:    error flag
01965     Purpose:    converts a colour from the CDR definition taking into account the version
01966     SeeAlso:    Filter
01967 
01968 ********************************************************************************************/
01969 
01970 BOOL CDRFilter::ConvertColour(cdrfColour *Col, DocColour *Out)
01971 {
01972     ERROR3IF(Col == 0 || Out == 0, "Null pointers passed to ConvertColour");
01973     
01974     ImportedNewColour ICol;
01975     
01976     switch(Version)
01977     {
01978         case CDRVERSION_5:  CDRColour::Convert5(Col, &ICol);    break;
01979         case CDRVERSION_4:  CDRColour::Convert4(Col, &ICol);    break;
01980         default:            CDRColour::Convert3(Col, &ICol);    break;
01981     }
01982     
01983     IndexedColour *NewCol = new IndexedColour(ICol.Model, &ICol.Colour);
01984 
01985     if(NewCol == 0)
01986         return FALSE;
01987 
01988     ColList->GetUnnamedColours()->AddTail(NewCol);
01989 
01990     Out->MakeRefToIndexedColour(NewCol);
01991 
01992     return TRUE;
01993 }
01994 
01995 
01996 /********************************************************************************************
01997 
01998 >   BOOL CDRFilter::ProcessObject(void)
01999 
02000     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02001     Created:    24 03 95
02002     Inputs:     none
02003     Returns:    error flag
02004     Purpose:    Converts an object. If there's a problem with the object, then it's skipped
02005                 rather than reporting an error, and the count of problem objects incremented
02006     SeeAlso:    
02007 
02008 ********************************************************************************************/
02009 
02010 BOOL CDRFilter::ProcessObject(void)
02011 {
02012     UINT32 StartLevel = RIFF->GetObjLevel();
02013 
02014     // set the made node to none
02015     pMadeNode = 0;
02016 
02017     // set the already applied flag
02018     AttrsAlreadyApplied = FALSE;
02019     
02020     // set the is text things to make sure bodges don't happen
02021     IsText = FALSE;
02022     IsTextStory = FALSE;
02023 
02024     // find the loda (4 or 5) or lobj (3) chunk... contains the object header
02025     BOOL Found = FALSE;
02026     FOURCC LookingFor = (Version == CDRVERSION_3)?cdrT_lobj:cdrT_loda;
02027     do
02028     {
02029         // is the serial number?
02030         if(RIFF->GetObjType() == RIFFOBJECTTYPE_CHUNK && RIFF->GetObjChunkType() == cdrT_spnd) {
02031             // got the serial number block - get it...
02032             if(!RIFF->AquireChunkData())
02033                 return FALSE;
02034         
02035             WORD *Data = (WORD *)RIFF->GetAquiredData();
02036         
02037             if(Data == 0)
02038                 return FALSE;
02039 
02040             // store it...
02041             SerialNumber = CDRDATA_WORD(*Data);
02042         }
02043 
02044         if(RIFF->GetObjType() == RIFFOBJECTTYPE_CHUNK && RIFF->GetObjChunkType() == LookingFor) {
02045             Found = TRUE;
02046             break;
02047         }
02048 
02049         if(!UpdateProgress())
02050             return FALSE;
02051         
02052         if(!RIFF->NextObject())
02053             return FALSE;
02054         
02055     } while(RIFF->GetObjType() != RIFFOBJECTTYPE_LISTEND || RIFF->GetObjLevel() > StartLevel);
02056 
02057     // if we didn't find anything, then the object has a wrong format
02058     if(Found == FALSE)
02059     {
02060 TRACEUSER( "Ben", _T("Could not find loda (or lobj) chunk in object\n"));       
02061         ObjectsFormatWrong++;
02062         return TRUE;
02063     }
02064 
02065     // get the header - but get it into our block, not the one in RIFFFile as we need
02066     // to refer to it later. It shouldn't be too big to make this inefficient...
02067     cdrfOffsetHeader *Header;
02068     
02069     // ensure we have a block big enough
02070     if(ObjDataBlock == 0 || ObjDataBlockSize < RIFF->GetObjSize())
02071     {
02072         // free the old one
02073         CCFree(ObjDataBlock);
02074 
02075         // size?
02076         INT32 Size = RIFF->GetObjSize();
02077 
02078         if((ObjDataBlock = (ADDR)CCMalloc(Size)) == 0)
02079             return FALSE;
02080 
02081         ObjDataBlockSize = Size;
02082     }
02083     
02084     if(!RIFF->GetChunkData(ObjDataBlock, ObjDataBlockSize))
02085         return FALSE;
02086 
02087     Header = (cdrfOffsetHeader *)ObjDataBlock;
02088 
02089     // look at the type and dispatch to appropriate processing function
02090     FormatError = FALSE;
02091     
02092     INT32 ObjectType = CDRDATA_WORD(Header->ObjectType);
02093 
02094     // if this is a version 3 object, alter it's type
02095     if(Version == CDRVERSION_3)
02096         ObjectType += cdrfOBJTYPE_V3ADD;
02097 
02098     switch(ObjectType) {
02099         case cdrfOBJTYPE_RECTANGLE:
02100             if(!ConvertRectangle(Header))
02101                 return FALSE;
02102             break;
02103         
02104         case cdrfOBJTYPE_ELLIPSE:
02105             if(!ConvertEllipse(Header))
02106                 return FALSE;
02107             break;
02108         
02109         case cdrfOBJTYPE_PATH:
02110             if(!ConvertPath(Header))
02111                 return FALSE;
02112             break;
02113 
02114         case cdrfOBJTYPE_TEXT:
02115         case cdrfOBJTYPE_TEXTSTORY:
02116             if(!ConvertText(Header))
02117                 return FALSE;
02118             break;
02119 
02120         case cdrfOBJTYPE_BITMAP:
02121             if(!ConvertBitmap(Header))
02122                 return FALSE;
02123             break;
02124 
02125         default:
02126             // unknown object type
02127             ObjectsUnknown++;
02128             RIFF->SkipToListEnd(StartLevel);
02129             return TRUE;
02130             break;
02131     }
02132     
02133     // check to see if the format was OK
02134     if(FormatError)
02135     {
02136 TRACEUSER( "Ben", _T("A convert object function returned a format error\n"));
02137         ObjectsFormatWrong++;
02138 
02139         if(TransformChunk != 0)
02140         {
02141             CCFree(TransformChunk);
02142             TransformChunk = 0;
02143         }
02144 
02145         return TRUE;
02146     }
02147 
02148     ERROR3IF(pMadeNode == 0, "No node made, but still nothing errored\n");
02149     
02150     // think about lenses
02151     BOOL UnsetTransparency = FALSE;
02152     if(Version == CDRVERSION_5)
02153     {
02154         cdrfLensDefn *Lens = (cdrfLensDefn *)FindDataInObject(Header, cdrfOBJOFFSETTYPE_LENS);
02155 
02156         if(Lens != 0)
02157         {
02158             // we have a lens to worry about... what type is it?
02159             if(Lens->Type == cdrfLENSTYPE_TRANSPARENT)
02160             {
02161                 // check the percentage
02162                 UINT32 Percent = CDRDATA_WORD(Lens->Percent) / 10;
02163                 if(Percent <= 100)
02164                 {
02165                     // munge the percentage a bit to get it to a Camelot definition
02166                     Percent = 256 - ((Percent * 256) / 100);
02167 
02168                     // what subtype is it?
02169                     switch(Lens->SubType)
02170                     {
02171                         case cdrfTRANSPARENTTYPE_MIX:
02172                             SetFlatTranspFill(T_REFLECTIVE, Percent);
02173                             UnsetTransparency = TRUE;
02174                             break;
02175 
02176                         case cdrfTRANSPARENTTYPE_STAINED:
02177                             SetFlatTranspFill(T_SUBTRACTIVE, Percent);
02178                             UnsetTransparency = TRUE;
02179                             break;
02180 
02181                         case cdrfTRANSPARENTTYPE_BLEACH:
02182                             SetFlatTranspFill(T_ADDITIVE, Percent);
02183                             UnsetTransparency = TRUE;
02184                             break;
02185 
02186                         default:
02187                             break;
02188                     }
02189                 }
02190             }
02191         }
02192     }
02193     
02194     // find the transform chunk - it's in a seperate chunk for version 4 or 5 file,
02195     // and in the data chunk for version 3 files
02196     ADDR TransformData = 0;
02197     INT32 TransformDataSize = 0;
02198     if(TransformChunk != 0)
02199     {
02200         // if something had to move forward in the file (for example, text objects)
02201         // past the transform chunk, it will have stored it here.
02202         TransformData = TransformChunk;
02203         TransformDataSize = TransformChunkSize;
02204     } 
02205     else if(Version == CDRVERSION_3)
02206     {
02207         TransformData = FindDataInObject(Header, cdrfOBJOFFSETTYPE_TRANSFORM_V3);
02208     }
02209     else 
02210     {
02211         Found = FALSE;
02212         do
02213         {
02214             if(RIFF->GetObjType() == RIFFOBJECTTYPE_LISTSTART && RIFF->GetObjChunkType() == cdrT_trfl) {
02215                 Found = TRUE;
02216                 break;
02217             }
02218 
02219             UpdateProgress();
02220         
02221             if(!RIFF->NextObject())
02222                 return FALSE;
02223         
02224         } while(RIFF->GetObjType() != RIFFOBJECTTYPE_LISTEND || RIFF->GetObjLevel() > StartLevel);
02225 
02226         // if we didn't find anything, then the object has a wrong format
02227         if(Found == FALSE)
02228         {
02229     TRACEUSER( "Ben", _T("Could not find trfd chunk in object\n"));     
02230             ObjectsFormatWrong++;
02231             // delete the current node
02232             delete pMadeNode;
02233             return TRUE;
02234         }
02235 
02236         // aquire the chunk data
02237         if(!RIFF->AquireListContents(&TransformDataSize))
02238         {
02239             delete pMadeNode;
02240             return FALSE;
02241         }
02242         TransformData = RIFF->GetAquiredData();
02243     }
02244 
02245     if(TransformData == 0)
02246     {
02247         ObjectsFormatWrong++;
02248         // delete the current node
02249         delete pMadeNode;
02250         return TRUE;
02251     }
02252 
02253     // go through any link transforms which may exist
02254     if(Version != CDRVERSION_3)
02255     {
02256         if(LinkTransformsExist)
02257         {
02258             BOOL FoundSome = FALSE;
02259         
02260             CDRActionListItem *Act = (CDRActionListItem *)Actions.GetTail();
02261 
02262             while(Act != 0)
02263             {
02264                 if(IS_A(Act, CDRActionTransform))
02265                 {
02266                     CDRActionTransform *Tran = (CDRActionTransform *)Act;
02267                 
02268                     if(Tran->LinkTrans)
02269                     {
02270                         // set the flag to say we found a link transform
02271                         FoundSome = TRUE;
02272 
02273                         // transform the converte object
02274                         if(!TransformConvertedObject(&pMadeNode, Tran->Chunk, Tran->ChunkSize, FALSE))
02275                         {
02276                             delete pMadeNode;
02277                             return FALSE;
02278                         }
02279                     }
02280                 }
02281 
02282                 Act = (CDRActionListItem *)Actions.GetPrev(Act);
02283             }
02284 
02285             LinkTransformsExist = FoundSome;
02286         }
02287     }
02288 
02289     // apply the transform to the converted node
02290     if(!TransformConvertedObject(&pMadeNode, TransformData, TransformDataSize))
02291     {
02292         delete pMadeNode;
02293         return FALSE;
02294     }
02295 
02296     // apply attributes
02297     if(AttrsAlreadyApplied == FALSE)
02298     {
02299         // look at fill attributes
02300         if(!SetFillAttr(Header))
02301             return FALSE;
02302 
02303         // look at line attributes
02304         if(!SetLineAttr(Header))
02305             return FALSE;
02306     }
02307 
02308     BOOL Result;
02309     if(AttrsAlreadyApplied == FALSE)
02310     {
02311         // apply the attributes to the object
02312         // If not filled, then set the ignore bit on the fill attribute.
02313         if (ObjFilled == FALSE)
02314             CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = TRUE;
02315 
02316         // Add attributes to the path, if they are different from the default...
02317         Result = AttributeManager::ApplyBasedOnDefaults(pMadeNode, CurrentAttrs);
02318 
02319         // Enable the fill attribute again
02320         CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = FALSE;
02321     } else {
02322         Result = TRUE;
02323     }
02324 
02325     if(!Result)
02326         return FALSE;
02327 
02328     if(UnsetTransparency)
02329     {
02330         SetNoTranspFill();
02331     }
02332 
02333     // attach the node to the level list
02334     if(pLevelNodeList != 0)
02335         pMadeNode->AttachNode(pLevelNodeList, PREV);
02336 
02337     pLevelNodeList = pMadeNode; 
02338     
02339     // set the made node pointer to zero to prevent accidents
02340     pMadeNode = 0;
02341 
02342     // increment the count of converted objects
02343     ObjectsConverted++;
02344 
02345     // if necessary, get rid of any transform chunk
02346     if(TransformChunk != 0)
02347     {
02348         CCFree(TransformChunk);
02349         TransformChunk = 0;
02350     }
02351     
02352     return TRUE;
02353 }
02354 
02355 
02356 /********************************************************************************************
02357 
02358 >   BOOL CDRFilter::ConvertPath(void)
02359 
02360     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02361     Created:    24 03 95
02362     Inputs:     none
02363     Returns:    error flag
02364     Purpose:    actually converts a path object to a node. If the object has an unexpected
02365                 format, then FormatError is set and it return *TRUE* - the return value only
02366                 indicated environmental errors such as lack of memory
02367     SeeAlso:    
02368 
02369 ********************************************************************************************/
02370 
02371 BOOL CDRFilter::ConvertPath(cdrfOffsetHeader *Header)
02372 {
02373     // find the address of the coordinates in the header
02374     cdrfPathCoordHeader *CHdr = (cdrfPathCoordHeader *)FindDataInObject(Header, cdrfOBJOFFSETTYPE_COORDS);
02375 
02376     // it has got some coords, hasn't it?
02377     if(CHdr == 0)
02378     {
02379         FormatError = TRUE;
02380         return TRUE;
02381     }
02382 
02383     // find the address of the types and the coordinates
02384     cdrfCoord *Coords = (cdrfCoord *)(CHdr + 1);
02385 
02386     // and the address of the types
02387     UINT32 NCoords = CDRDATA_WORD(CHdr->NCoords);
02388     BYTE *Types = (BYTE *)(Coords + NCoords);
02389 
02390     // check the path a little
02391     if((NCoords * (sizeof(cdrfCoord) + sizeof(BYTE))) > CDRDATA_WORD(Header->Size) || NCoords < 2)
02392     {
02393         FormatError = TRUE;
02394         return TRUE;
02395     }
02396     
02397     // knock up a path node
02398     NodePath *pPath = new NodePath;
02399     if(pPath == 0 || (!pPath->SetUpPath()))
02400     {
02401         delete pPath;
02402         return FALSE;           // no room to create it
02403     }
02404 
02405     // position the new elements at the beginning of the path
02406     pPath->InkPath.FindStartOfPath();
02407 
02408     // flag the initial status of the fill/stokedness of the path
02409     ObjFilled = FALSE;
02410     ObjStroked = TRUE;
02411 
02412     if(!AddElementsToPath(&pPath->InkPath, NCoords, Coords, Types, &ObjFilled))
02413         goto NoMemory;
02414 
02415     // check that the path is OK
02416     if(!pPath->InkPath.EnsureValid())
02417     {
02418         // no, it's completely knackered
02419         delete pPath;
02420         FormatError = TRUE;
02421         return TRUE;
02422     }
02423 
02424     // finish off the path
02425     pPath->InvalidateBoundingRect();                
02426     pPath->InkPath.IsFilled = ObjFilled;
02427 
02428     // save node pointer
02429     pMadeNode = pPath;
02430 
02431     // check to see if text goes along this...
02432     {
02433         CDRTextOnPathLink *Item = (CDRTextOnPathLink *)TextOnPathLinks.GetHead();
02434 
02435         while(Item != 0)
02436         {
02437             // does this link refer to this text story?
02438             if(SerialNumber == Item->PathSerialNumber)
02439             {
02440                 // yep - store a pointer to this path
02441                 Item->pPath = pPath;
02442             }
02443         
02444             // next!
02445             Item = (CDRTextOnPathLink *)TextOnPathLinks.GetNext(Item);
02446         }
02447     }
02448     
02449     // everything was nice
02450     return TRUE;
02451 
02452 NoMemory:
02453     // get rid of any path which is in the process of being created
02454     if(pPath != 0)
02455         pPath->CascadeDelete();
02456 
02457     delete pPath;
02458 
02459     return FALSE;
02460 }
02461 
02462 
02463 /********************************************************************************************
02464 
02465 >   BOOL CDRFilter::AddElementsToPath(Path *pPath, INT32 NCoords, cdrfCoord *Coords, BYTE *Types, BOOL *IsClosed);
02466 
02467     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02468     Created:    06/05/95
02469     Inputs:     path to add too, number of coords, pointer to coord data, pointer to types
02470     Returns:    error flag
02471     Purpose:    Adds elements to a path from a CDR path data
02472     SeeAlso:    
02473 
02474 ********************************************************************************************/
02475 
02476 BOOL CDRFilter::AddElementsToPath(Path *pPath, INT32 NCoords, cdrfCoord *Coords, BYTE *Types, BOOL *IsClosed)
02477 {
02478     // go through the coordinates in the CDR path adding them to the Camelot path
02479     INT32 c;                    // coord counter
02480     UINT32 CoordType;           // type of this coordinate
02481     UINT32 Control1 = 0;        // number of first control point
02482     UINT32 Control2 = 0;        // of second
02483     DocCoord co, cn1, cn2;  // coordinates
02484     PathFlags Flags;
02485     BOOL NeedMoveTo = TRUE;
02486 
02487     if(IsClosed != 0)
02488         (*IsClosed) = FALSE;
02489     
02490     // go though converting all the coords
02491     for(c = 0; c < NCoords; c++)
02492     {
02493         CoordType = Types[c] & cdrfPATHCOORDTYPE_MASK;
02494 
02495         co.x = CDRDATA_SWORD(Coords[c].X) * CDRCOORDS_TO_MILLIPOINTS;
02496         co.y = CDRDATA_SWORD(Coords[c].Y) * CDRCOORDS_TO_MILLIPOINTS;
02497 
02498         // add in a move to if necessary
02499         if(NeedMoveTo && CoordType != cdrfPATHCOORDTYPE_MOVE)
02500         {
02501             if(!pPath->InsertMoveTo(co))
02502                 return FALSE;
02503         }
02504 
02505         NeedMoveTo = FALSE;
02506         
02507         // process the coordinate       
02508         switch(CoordType)
02509         {
02510             case cdrfPATHCOORDTYPE_MOVE:
02511                 // add a move to this path
02512                 if(!pPath->InsertMoveTo(co))
02513                     return FALSE;
02514                 break;
02515             
02516             case cdrfPATHCOORDTYPE_LINETO:
02517                 // add a line to this coord to the path
02518                 if(!pPath->InsertLineTo(co))
02519                     return FALSE;
02520                 break;
02521             
02522             case cdrfPATHCOORDTYPE_CURVE:
02523                 // check we have some control points for this curve
02524                 // a control point cannot be the first coord, so it's OK to check against 0
02525                 if(Control1 == 0 || Control2 == 0)
02526                 {
02527 TRACEUSER( "Ben", _T("No control points for curve element\n"));
02528                     break;
02529                 }
02530 
02531                 // convert the control points
02532                 cn1.x = CDRDATA_SWORD(Coords[Control1].X) * CDRCOORDS_TO_MILLIPOINTS;
02533                 cn1.y = CDRDATA_SWORD(Coords[Control1].Y) * CDRCOORDS_TO_MILLIPOINTS;
02534                 cn2.x = CDRDATA_SWORD(Coords[Control2].X) * CDRCOORDS_TO_MILLIPOINTS;
02535                 cn2.y = CDRDATA_SWORD(Coords[Control2].Y) * CDRCOORDS_TO_MILLIPOINTS;
02536                 
02537                 // create the curve
02538                 Flags.IsSelected = FALSE;
02539                 Flags.IsSmooth = Flags.IsRotate = ((Types[c] & cdrfPATHCOORDATTR_SMOOTH) != 0)?TRUE:FALSE;
02540                 Flags.IsEndPoint;
02541                 
02542                 // insert it into the path
02543                 if(!pPath->InsertCurveTo(cn1, cn2, co, &Flags))
02544                     return FALSE;
02545                 break;
02546 
02547             case cdrfPATHCOORDTYPE_CONTROL:
02548                 // shuffle the control points we've already got and add the new one
02549                 Control1 = Control2;
02550                 Control2 = c;
02551                 break;
02552             
02553             default:
02554                 // can't get here as mask won't allow any other value than the ones above.
02555                 break;
02556         }
02557 
02558         // is this a close subpath situtation?
02559         if((Types[c] & cdrfPATHCOORDATTR_CLOSE) != 0)
02560         {
02561             if(IsClosed != 0)
02562                 (*IsClosed) = TRUE;     // path has at least one closed element and should be filled
02563             
02564             // close the sub path
02565             if(CoordType != cdrfPATHCOORDTYPE_MOVE)
02566             {
02567                 if(!pPath->CloseSubPath())
02568                     return FALSE;
02569 
02570                 // ensure that the next coord is a moveto
02571                 NeedMoveTo = TRUE;
02572             }
02573         }
02574     }
02575 
02576     return TRUE;
02577 }
02578 
02579 
02580 /********************************************************************************************
02581 
02582 >   BOOL CDRFilter::ConvertRectangle(cdrfOffsetHeader *Header)
02583 
02584     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02585     Created:    27 03 95
02586     Inputs:     pointer to header
02587     Returns:    error flag
02588     Purpose:    generates a rectangle object
02589     SeeAlso:    
02590 
02591 ********************************************************************************************/
02592 
02593 #define RECTANGLE_CORNER_MAGIC (1.0 - 0.552)
02594 
02595 #define RECT_MOVE(px, py) {co.x = (px); co.y = (py); if(!pPath->InkPath.InsertMoveTo(co)) goto NoMemory;}
02596 #define RECT_LINE(px, py) {co.x = (px); co.y = (py); if(!pPath->InkPath.InsertLineTo(co)) goto NoMemory;}
02597 #define RECT_CURVE(cx1, cy1, cx2, cy2, px, py) {cn1.x = (cx1); cn1.y = (cy1); cn2.x = (cx2); cn2.y = (cy2); \
02598             co.x = (px); co.y = (py); if(!pPath->InkPath.InsertCurveTo(cn1, cn2, co)) goto NoMemory;}
02599 #define RECT_CLOSE {if(!pPath->InkPath.CloseSubPath()) goto NoMemory;}
02600 
02601 
02602 BOOL CDRFilter::ConvertRectangle(cdrfOffsetHeader *Header)
02603 {
02604     // find the address of the coordinates in the header
02605     cdrfRectangleData *Size = (cdrfRectangleData *)FindDataInObject(Header, cdrfOBJOFFSETTYPE_COORDS);
02606 
02607     // it has got some coords, hasn't it?
02608     if(Size == 0)
02609     {
02610         FormatError = TRUE;
02611         return TRUE;
02612     }
02613 
02614     // get the dimensions from the object
02615     INT32 Width = CDRDATA_SWORD(Size->Width) * CDRCOORDS_TO_MILLIPOINTS;
02616     INT32 Height = CDRDATA_SWORD(Size->Height) * CDRCOORDS_TO_MILLIPOINTS;
02617     INT32 CornerRadius = CDRDATA_SWORD(Size->CornerRadius) * CDRCOORDS_TO_MILLIPOINTS;
02618     
02619     if(CornerRadius < 0)
02620         CornerRadius = 0 - CornerRadius;
02621 
02622     // make a rectangle quickshape...
02623     NodeRegularShape *NewShape = new (NodeRegularShape);
02624 
02625     if ((NewShape == NULL) || !NewShape->SetUpShape() )
02626     {
02627         ERROR1(FALSE, _R(IDS_OUT_OF_MEMORY));
02628     }
02629 
02630     INT32 AWidth = Width;
02631     INT32 AHeight = Height;
02632     if(AWidth < 0) AWidth = 0 - AWidth;
02633     if(AHeight < 0) AHeight = 0 - AHeight;
02634     
02635     if(!NewShape->MakeRectangle(AWidth, AHeight, CornerRadius))
02636         return FALSE;
02637 
02638     // translate it a bit so the corner is on the origin, not the thingy
02639     Trans2DMatrix Trans(Width / 2, Height / 2);
02640 
02641     NewShape->Transform(Trans);
02642 
02643     // finish off the shape
02644     NewShape->InvalidateBoundingRect();
02645 
02646     // set up an attribute or two
02647     ObjFilled = TRUE;
02648     ObjStroked = TRUE;              
02649 
02650     // set the made node
02651     pMadeNode = NewShape;
02652 
02653     return TRUE;
02654 
02655 }
02656 
02657 
02658 /********************************************************************************************
02659 
02660 >   BOOL CDRFilter::ConvertEllipse(cdrfOffsetHeader *Header)
02661 
02662     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02663     Created:    27 03 95
02664     Inputs:     pointer to header
02665     Returns:    error flag
02666     Purpose:    generates an ellipse object
02667     SeeAlso:    
02668 
02669 ********************************************************************************************/
02670 
02671 BOOL CDRFilter::ConvertEllipse(cdrfOffsetHeader *Header)
02672 {
02673     // find the address of the coordinates in the header
02674     cdrfEllipseData *Size = (cdrfEllipseData *)FindDataInObject(Header, cdrfOBJOFFSETTYPE_COORDS);
02675 
02676     // it has got some coords, hasn't it?
02677     if(Size == 0)
02678     {
02679         FormatError = TRUE;
02680         return TRUE;
02681     }
02682 
02683     // Create the ellipse
02684     NodeRegularShape *NewShape = new (NodeRegularShape);
02685 
02686     if ((NewShape == NULL) || !NewShape->SetUpShape() )
02687     {
02688         ERROR1(FALSE, _R(IDS_OUT_OF_MEMORY));
02689     }
02690 
02691     // fill it all in for an ellipse
02692     NewShape->SetNumSides(4);
02693 
02694     INT32 Width = CDRDATA_SWORD(Size->Width) * CDRCOORDS_TO_MILLIPOINTS;
02695     INT32 Height = CDRDATA_SWORD(Size->Height) * CDRCOORDS_TO_MILLIPOINTS;
02696 
02697     DocCoord co;
02698     co.x = Width / 2;       // centre - it all starts at (0,0)
02699     co.y = Height / 2;
02700     NewShape->SetCentrePoint(co);
02701     co.x = Width;
02702     NewShape->SetMajorAxes(co);
02703     co.x /= 2;
02704     co.y = Height;
02705     NewShape->SetMinorAxes(co);
02706 
02707     NewShape->SetCircular(TRUE);
02708     NewShape->SetStellated(FALSE);
02709     NewShape->SetPrimaryCurvature(TRUE);
02710     NewShape->SetStellationCurvature(FALSE);
02711 
02712     // finish off the path
02713     NewShape->InvalidateBoundingRect();
02714     
02715     // set up an attribute or two
02716     ObjFilled = TRUE;
02717     ObjStroked = TRUE;              
02718 
02719     // set the made node
02720     pMadeNode = NewShape;
02721 
02722     return TRUE;
02723 }
02724 
02725 
02726 /********************************************************************************************
02727 
02728 >   BOOL CDRFilter::ConvertBitmap(cdrfOffsetHeader *Header)
02729 
02730     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02731     Created:    12/04/95
02732     Inputs:     pointer to header
02733     Returns:    error flag
02734     Purpose:    generates a bitmap object
02735     SeeAlso:    
02736 
02737 ********************************************************************************************/
02738 
02739 #define BITM_MOVE(px, py) {co.x = (px); co.y = (py); if(!pPath->InkPath.InsertMoveTo(co)) return FALSE;}
02740 #define BITM_LINE(px, py) {co.x = (px); co.y = (py); if(!pPath->InkPath.InsertLineTo(co)) return FALSE;}
02741 #define BITM_CLOSE {if(!pPath->InkPath.CloseSubPath()) return FALSE;}
02742 
02743 BOOL CDRFilter::ConvertBitmap(cdrfOffsetHeader *Header)
02744 {
02745     // find the address of the coordinates in the header
02746     cdrfBitmapData *BInfo = (cdrfBitmapData *)FindDataInObject(Header, cdrfOBJOFFSETTYPE_COORDS);
02747 
02748     // it has got some object data, hasn't it?
02749     if(BInfo == 0)
02750     {
02751         FormatError = TRUE;
02752         return TRUE;
02753     }
02754 
02755     // OK, let's get the information in a nice structure to start off with
02756     struct {
02757         DWORD Reference;
02758         INT32 SizeX;
02759         INT32 SizeY;
02760         INT32 Left;         // cropping coordinates
02761         INT32 Right;
02762         INT32 Bottom;
02763         INT32 Top;
02764     } Info;
02765 
02766     // choose the right reference - it's in a slightly different place in CDR 3 files
02767     if(Version != CDRVERSION_3)
02768     {
02769         Info.Reference = CDRDATA_WORD(BInfo->BitmapReference);
02770         Info.SizeX = CDRDATA_SWORD(BInfo->SizeX) * CDRCOORDS_TO_MILLIPOINTS;
02771         Info.SizeY = CDRDATA_SWORD(BInfo->SizeY) * CDRCOORDS_TO_MILLIPOINTS;
02772         Info.Left = CDRDATA_SWORD(BInfo->Left) * CDRCOORDS_TO_MILLIPOINTS;
02773         Info.Right = CDRDATA_SWORD(BInfo->Right) * CDRCOORDS_TO_MILLIPOINTS;
02774         Info.Bottom = CDRDATA_SWORD(BInfo->Bottom) * CDRCOORDS_TO_MILLIPOINTS;
02775         Info.Top = CDRDATA_SWORD(BInfo->Top) * CDRCOORDS_TO_MILLIPOINTS;
02776     }
02777     else
02778     {
02779         cdrfBitmapData3 *B3Info = (cdrfBitmapData3 *)BInfo;
02780         
02781         Info.Reference = CDRDATA_WORD(B3Info->BitmapReference);
02782         Info.SizeX = CDRDATA_SWORD(B3Info->SizeX) * CDRCOORDS_TO_MILLIPOINTS;
02783         Info.SizeY = CDRDATA_SWORD(B3Info->SizeY) * CDRCOORDS_TO_MILLIPOINTS;
02784         Info.Left = CDRDATA_SWORD(B3Info->Left) * CDRCOORDS_TO_MILLIPOINTS;
02785         Info.Right = CDRDATA_SWORD(B3Info->Right) * CDRCOORDS_TO_MILLIPOINTS;
02786         Info.Bottom = CDRDATA_SWORD(B3Info->Bottom) * CDRCOORDS_TO_MILLIPOINTS;
02787         Info.Top = CDRDATA_SWORD(B3Info->Top) * CDRCOORDS_TO_MILLIPOINTS;
02788     }
02789 
02790     // find that there bitmap
02791     KernelBitmap *pBitmap = Bitmaps.FindBitmap(Info.Reference);
02792 
02793     if(pBitmap == 0)
02794     {
02795         FormatError = TRUE;
02796         return TRUE;
02797     }
02798 
02799     // find a bounding box for the bitmap on the page
02800     DocRect BoundsRect;
02801 
02802     if(Info.SizeX > 0)
02803     {
02804         BoundsRect.lo.x = 0;
02805         BoundsRect.hi.x = Info.SizeX;
02806     } else {
02807         BoundsRect.lo.x = Info.SizeX;
02808         BoundsRect.hi.x = 0;
02809     }
02810 
02811     if(Info.SizeY > 0)
02812     {
02813         BoundsRect.lo.y = 0;
02814         BoundsRect.hi.y = Info.SizeY;
02815     } else {
02816         BoundsRect.lo.y = Info.SizeY;
02817         BoundsRect.hi.y = 0;
02818     }
02819 
02820 
02821     // OK, if the bitmap isn't cropped, create a bitmap object, otherwise
02822     // create a rectangle which is the right size and pop a bitmap fill on it
02823     if(Info.Left == 0 && Info.Right == Info.SizeX && Info.Top == 0 && Info.Bottom == Info.SizeY)
02824     {
02825         // create a bitmap object
02826         NodeBitmap *NewBitmap = new NodeBitmap;
02827 
02828         if((NewBitmap == NULL) || !NewBitmap->SetUpPath())
02829             return FALSE;
02830         
02831         NewBitmap->CreateShape(BoundsRect);
02832 
02833         // set the reference to the bitmap
02834         NewBitmap->GetBitmapRef()->Attach(pBitmap, GetDocument());
02835         if (NewBitmap->GetBitmap() != pBitmap)
02836         {
02837             // It didn't use the bitmap we gave it, so we can delete it
02838             delete pBitmap;
02839         }
02840     
02841         // apply a few nice attributes to it
02842         NewBitmap->ApplyDefaultBitmapAttrs(0);
02843 
02844         // invalidate the bounding rectangle
02845         NewBitmap->InvalidateBoundingRect();
02846 
02847         // cool.
02848         ObjFilled = FALSE;
02849         ObjStroked = FALSE; 
02850 
02851         // we don't want any of those fancy attributes things on this object.
02852         AttrsAlreadyApplied = TRUE;
02853 
02854         // set the made node
02855         pMadeNode = NewBitmap;
02856     }
02857     else
02858     {
02859         // create a rectangular path object...
02860         // generate a path
02861         NodePath *pPath = new NodePath;
02862         if(pPath == 0 || (!pPath->SetUpPath()))
02863         {
02864             delete pPath;
02865             return FALSE;           // no room to create it
02866         }
02867 
02868         // position the new elements at the beginning of the path
02869         pPath->InkPath.FindStartOfPath();
02870 
02871         DocCoord co, cn1, cn2;
02872     
02873         // make the rectangle shape
02874         BITM_MOVE(Info.Left,    Info.Bottom)
02875         BITM_LINE(Info.Right,   Info.Bottom)
02876         BITM_LINE(Info.Right,   Info.Top)
02877         BITM_LINE(Info.Left,    Info.Top)
02878         BITM_LINE(Info.Left,    Info.Bottom)
02879         BITM_CLOSE
02880 
02881         // finish off the path
02882         pPath->InvalidateBoundingRect();
02883         pPath->InkPath.IsFilled = TRUE;
02884     
02885         // set up an attribute or two
02886         ObjFilled = TRUE;
02887         ObjStroked = FALSE;
02888 
02889         // set up a nice attribute for this thingy
02890         if(!SetLineColour(DocColour(COLOUR_TRANS)))
02891             return FALSE;
02892 
02893         // set a nice bitmap fill
02894         DocCoord Start  = DocCoord(BoundsRect.lo.x, BoundsRect.lo.y);
02895         DocCoord End1   = DocCoord(BoundsRect.hi.x, BoundsRect.lo.y);
02896         DocCoord End2   = DocCoord(BoundsRect.lo.x, BoundsRect.hi.y);
02897         if(!SetBitmapFill(pBitmap, Start, End1, End2))
02898             return FALSE;
02899         
02900         // apply attributes
02901         SetPathFilled(TRUE);
02902         CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = FALSE;
02903         if(!AttributeManager::ApplyBasedOnDefaults(pPath, CurrentAttrs))
02904             return FALSE;
02905         
02906         // don't apply attributes later
02907         AttrsAlreadyApplied = TRUE;
02908 
02909         // set the made node
02910         pMadeNode = pPath;
02911     }
02912 
02913     return TRUE;
02914 }
02915 
02916 
02917 /********************************************************************************************
02918 
02919 >   ADDR CDRFilter::FindDataInObject(cdrfOffsetHeader *Header, WORD Type)
02920 
02921     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02922     Created:    25 03 95
02923     Inputs:     none
02924     Returns:    error flag
02925     Purpose:    returns the address of data of the given type in an objects with a standard
02926                 offset header
02927     SeeAlso:    Filter
02928 
02929 ********************************************************************************************/
02930 
02931 ADDR CDRFilter::FindDataInObject(cdrfOffsetHeader *Header, WORD Type)
02932 {
02933     WORD *Types;
02934     WORD *Offsets;
02935 
02936     Types = (WORD *)(((BYTE *)Header) + CDRDATA_WORD(Header->TypesOffset));
02937     Offsets = (WORD *)(((BYTE *)Header) + CDRDATA_WORD(Header->OffsetsOffset));
02938 
02939     UINT32 l;
02940 
02941     for(l = 0; l < CDRDATA_WORD(Header->NOffsets); l++)
02942     {
02943         if(CDRDATA_WORD(Types[l]) == Type)
02944         {
02945             UINT32 Off = CDRDATA_WORD(Offsets[Header->NOffsets - l - 1]);
02946             if(Off > CDRDATA_WORD(Header->Size))
02947                 return 0;
02948             
02949             return (ADDR)(((BYTE *)Header) + Off);
02950         }
02951     }
02952 
02953     return 0;
02954 }
02955 
02956 
02957 /********************************************************************************************
02958 
02959 >   BOOL CDRFilter::GetMatrixFromTransform(Matrix *M, ADDR Trans, INT32 Size, BOOL TranslateForPage)
02960 
02961     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02962     Created:    25 03 95
02963     Inputs:     the node to transform, and the trfd chunk to transform it by
02964     Returns:    error flag
02965     Purpose:    given some transform data, works out a matrix. This ignores any 3D transforms,
02966                 TransformConvertedObject should be used in preference.
02967     SeeAlso:    Filter
02968 
02969 ********************************************************************************************/
02970 
02971 BOOL CDRFilter::GetMatrixFromTransform(Matrix *M, ADDR Trans, INT32 Size, BOOL TranslateForPage)
02972 {
02973     // set up a matrix conversion object
02974     CDRTransformConvertor *Conv;
02975     
02976     // putting the convertors here is probably more efficicent than allocating
02977     // a new one in the heap as they're not very big at all
02978     CDRTransformConvertor5 Conv5;
02979     CDRTransformConvertor4 Conv4;
02980     CDRTransformConvertor3 Conv3;
02981     
02982     switch(Version)
02983     {
02984         case CDRVERSION_5:  Conv = &Conv5;  break;
02985         case CDRVERSION_4:  Conv = &Conv4;  break;
02986         case CDRVERSION_3:  Conv = &Conv3;  break;
02987         default:            return FALSE;   break;
02988     }
02989 
02990     // initialise the convertor object
02991     Conv->Init(Trans, Size);
02992     
02993     // set up the initial matrix which just converts to millipoints
02994     // note that these elements are in Corel order
02995     cdrMatrix Ma, Mb, Mt;
02996     BOOL DoneFirst = FALSE;
02997 
02998     // apply all the transformations in the chunk
02999     INT32 t;
03000     for(t = Conv->GetNTransforms() - 1; t >= 0; t--)
03001     {
03002         // check that the transform is a matrix - for now we can only do matrices
03003         if(Conv->GetTransformType(t) != CDRTRANSFORMTYPE_MATRIX)
03004             continue;
03005 
03006         if(DoneFirst)
03007         {
03008             // done the first matrix, so we need get the matrix into another one and then combine.
03009             
03010             // get the matrix
03011             if(!Conv->GetMatrix(&Mb, t))
03012                 return FALSE;
03013 
03014             // and combine it with the matrix we've already got
03015             Mt.a = (Mb.a * Ma.a) + (Mb.d * Ma.b);
03016             Mt.b = (Mb.b * Ma.a) + (Mb.e * Ma.b);
03017             Mt.c = (Mb.c * Ma.a) + (Mb.f * Ma.b) + Ma.c;
03018             Mt.d = (Mb.a * Ma.d) + (Mb.d * Ma.e);
03019             Mt.e = (Mb.b * Ma.d) + (Mb.e * Ma.e);
03020             Mt.f = (Mb.c * Ma.d) + (Mb.f * Ma.e) + Ma.f;
03021 
03022             Ma = Mt;
03023         } else {
03024             // just get the matrix
03025             if(!Conv->GetMatrix(&Ma, t))
03026                 return FALSE;
03027 
03028             DoneFirst = TRUE;
03029         }
03030     }
03031 
03032     // if we didn't get a matrix at all, knock up a quick dummy one
03033     if(!DoneFirst)
03034     {
03035         cdrMatrix Mx = {1, 0, 0, 0, 1, 0};
03036     
03037         Ma = Mx;
03038     }
03039     
03040     // add in the translation bit
03041     if(TranslateForPage)
03042     {
03043         Ma.c += TranslateByX;
03044         Ma.f += TranslateByY;
03045     }
03046 
03047     // convert the final matrix into a Camelot matrix
03048     *M = Matrix(Ma.a, Ma.d, Ma.b, Ma.e, (INT32)Ma.c, (INT32)Ma.f);
03049     
03050     return TRUE;
03051 }
03052 
03053 
03054 /********************************************************************************************
03055 
03056 >   BOOL CDRFilter::IsTransformJustMatrices(ADDR Trans)
03057 
03058     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
03059     Created:    22/05/95
03060     Inputs:     trfd chunk to examine
03061     Returns:    error flag
03062     Purpose:    scans a transform chunk. Returns TRUE if the transform was just composed of
03063                 matrices and unknown transforms.
03064     SeeAlso:    Filter
03065 
03066 ********************************************************************************************/
03067 
03068 BOOL CDRFilter::IsTransformJustMatrices(ADDR Trans, INT32 Size)
03069 {
03070     // set up a matrix conversion object
03071     CDRTransformConvertor *Conv;
03072     
03073     // putting the convertors here is probably more efficicent than allocating
03074     // a new one in the heap as they're not very big at all
03075     CDRTransformConvertor5 Conv5;
03076     CDRTransformConvertor4 Conv4;
03077     CDRTransformConvertor3 Conv3;
03078     
03079     switch(Version)
03080     {
03081         case CDRVERSION_5:  Conv = &Conv5;  break;
03082         case CDRVERSION_4:  Conv = &Conv4;  break;
03083         case CDRVERSION_3:  Conv = &Conv3;  break;
03084         default:            return FALSE;   break;
03085     }
03086 
03087     // initialise the convertor object
03088     Conv->Init(Trans, Size);
03089     
03090     // check all the transformations in the chunk
03091     for(INT32 t = Conv->GetNTransforms() - 1; t >= 0; t--)
03092     {
03093         switch(Conv->GetTransformType(t))
03094         {
03095             case CDRTRANSFORMTYPE_MATRIX:
03096             case CDRTRANSFORMTYPE_UNKNOWN:
03097                 break;
03098 
03099             default:
03100                 return FALSE;
03101                 break;
03102         }
03103 
03104     }
03105 
03106     return TRUE;
03107 }
03108 
03109 
03110 /********************************************************************************************
03111 
03112 >   BOOL CDRFilter::TransformConvertedObject(NodeRenderable **N, cdrfTransform *Trans, BOOL TranslateForPage = TRUE,
03113             BOOL IsAGroupTransform = FALSE, BOOL WorkAtOrigin = FALSE)
03114 
03115     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
03116     Created:    25 03 95
03117     Inputs:     the node to transform, and the trfd chunk to transform it by
03118     Returns:    error flag
03119     Purpose:    transforms an object we converted, given a trfd chunk. If TranslateForPage
03120                 is true (defaults to TRUE) then the object will also be translated to get
03121                 the origin in the right place. The pointer may be modified to be a pointer
03122                 to a different object.
03123                 WorkAtOrigin causes the object to be translated back to the origin
03124                 before being hacked apon, except if it's in a CDR3 file when it's ignored
03125                 as the file is mass-translated at the end of the conversion..
03126     SeeAlso:    Filter
03127 
03128 ********************************************************************************************/
03129 
03130 BOOL CDRFilter::TransformConvertedObject(NodeRenderable **N, ADDR Trans, INT32 Size, BOOL TranslateForPage,
03131                         BOOL IsAGroupTransform, BOOL WorkAtOrigin)
03132 {
03133     if(IsText)
03134     {
03135         (*N)->OptimiseAttributes();
03136     }
03137 
03138     // make sure the WorkAtOrigin flag is set correctly - we mustn't use it if we're fiddling with a v3 file
03139     if(Version == CDRVERSION_3) WorkAtOrigin = FALSE;
03140 
03141     // transform it back to the origin if necessary
03142     if(WorkAtOrigin)
03143     {
03144         Trans2DMatrix Trans(-TranslateByX, -TranslateByY);
03145         (*N)->Transform(Trans);
03146     }
03147 
03148     // set up a transform conversion object
03149     CDRTransformConvertor *Conv;
03150 
03151     // putting the convertors here is probably more efficicent than allocating
03152     // a new one in the heap as they're not very big at all
03153     CDRTransformConvertor5 Conv5;
03154     CDRTransformConvertor4 Conv4;
03155     CDRTransformConvertor3 Conv3;
03156     
03157     switch(Version)
03158     {
03159         case CDRVERSION_5:  Conv = &Conv5;  break;
03160         case CDRVERSION_4:  Conv = &Conv4;  break;
03161         case CDRVERSION_3:  Conv = &Conv3;  break;
03162         default:            return FALSE;   break;
03163     }
03164 
03165     // initialise the convertor object
03166     Conv->Init(Trans, Size);
03167     
03168     // note that these elements are in Corel order
03169     cdrMatrix Ma, Mb, Mt;
03170     BOOL HaveMatrix = FALSE;
03171 
03172     BOOL ApplyMatrices = IsAGroupTransform?FALSE:TRUE;
03173 
03174 #ifdef CDR_DOEXTRUDE
03175     for(UINT32 g = 0; g < Conv->GetNTransforms(); g++)
03176     {
03177         CDRTransformType Type = Conv->GetTransformType(t);
03178 
03179         if(Type == CDRTRANSFORMTYPE_EXTRUDE)
03180             ApplyMatrices = FALSE;
03181     }
03182 #endif
03183 
03184 
03185     // apply all the transformations in the chunk
03186     for(UINT32 t = 0; t < Conv->GetNTransforms(); t++)
03187     {
03188         CDRTransformType Type = Conv->GetTransformType(t);
03189         
03190         // check that the transform is something we know about
03191         if(Type == CDRTRANSFORMTYPE_UNKNOWN)
03192             continue;
03193 
03194         // if it's a matrix, then append it to the previous one, if any
03195         if(Type == CDRTRANSFORMTYPE_MATRIX)
03196         {
03197             if(ApplyMatrices)
03198             {
03199                 if(HaveMatrix)
03200                 {
03201                     // done the first matrix, so we need get the matrix into another one and then combine.
03202             
03203                     // get the matrix
03204                     if(!Conv->GetMatrix(&Mb, t))
03205                         return FALSE;
03206 
03207                     // and combine it with the matrix we've already got
03208                     Mt.a = (Ma.a * Mb.a) + (Ma.d * Mb.b);
03209                     Mt.b = (Ma.b * Mb.a) + (Ma.e * Mb.b);
03210                     Mt.c = (Ma.c * Mb.a) + (Ma.f * Mb.b) + Mb.c;
03211                     Mt.d = (Ma.a * Mb.d) + (Ma.d * Mb.e);
03212                     Mt.e = (Ma.b * Mb.d) + (Ma.e * Mb.e);
03213                     Mt.f = (Ma.c * Mb.d) + (Ma.f * Mb.e) + Mb.f;
03214 
03215                     Ma = Mt;
03216                 } else {
03217                     // just get the matrix
03218                     if(!Conv->GetMatrix(&Ma, t))
03219                         return FALSE;
03220 
03221                     HaveMatrix = TRUE;
03222                 }
03223             }
03224         }
03225         else
03226         {
03227             // wasn't a matrix - apply a matrix if we've got one
03228             if(HaveMatrix)
03229             {
03230                 // apply it
03231                 if(!ApplyMatrices)
03232                 {
03233                     if(!TransformConvertedObjectDoMatrix(N, &Ma, FALSE))
03234                         return FALSE;
03235                 }
03236 
03237             }
03238         
03239             // unset the flag
03240             HaveMatrix = FALSE;
03241 
03242             // deal with the transformation
03243             ERROR3IF(Type == CDRTRANSFORMTYPE_MATRIX, "Matrix got through in TransformConvertedObject")
03244 
03245             switch(Type)
03246             {
03247                 case CDRTRANSFORMTYPE_PERSPECTIVE:
03248                     {
03249                         // convert the perpective
03250                         cdrPerspective P;
03251 
03252                         if(!Conv->GetPerspective(&P, t))
03253                             return FALSE;
03254 
03255                         // apply it to the object
03256                         if(!TransformConvertedObjectDoPerspective(N, &P, IsAGroupTransform))
03257                             return FALSE;
03258                     }
03259                     break;
03260 
03261                 case CDRTRANSFORMTYPE_ENVELOPE:
03262                     if(!(Version != CDRVERSION_3 && IsTextStory))       // text stories don't get enveloped - this is used as the frame shape
03263                     {
03264                         // convert the envelope into a path
03265                         DocRect OBBox;
03266                         Path *Shape = 0;
03267                         INT32 Corners[4];
03268 
03269                         if(Conv->GetEnvelope(&Shape, &OBBox, (INT32 *)&Corners, t))
03270                         {
03271                             // apply to object
03272                             if(!TransformConvertedObjectDoEnvelope(N, Shape, &OBBox, (INT32 *)&Corners, IsAGroupTransform))
03273                                 return FALSE;
03274 
03275                             // delete the shape
03276                             delete Shape;
03277                         }
03278                     }
03279                     break;
03280 
03281                 case CDRTRANSFORMTYPE_EXTRUDE:
03282                     {
03283                         cdrExtrudeInfo Info;
03284 
03285                         if(Conv->GetExtrude(&Info, t))
03286                         {
03287                             // apply to object
03288                             if(!TransformConvertedObjectDoExtrude(N, &Info, IsAGroupTransform))
03289                                 return FALSE;
03290                         }
03291                         ApplyMatrices = TRUE;       // start applying the matrices...
03292                     }
03293                     break;
03294  
03295                 default:
03296                     break;
03297             }
03298             
03299             if(Version == CDRVERSION_5)
03300             {
03301                 // we want to apply matrices from now on
03302                 ApplyMatrices = TRUE;
03303             }
03304         }
03305     }
03306 
03307     // if we've got a matrix still to do...
03308     if(HaveMatrix)
03309     {
03310         // apply it
03311         if(ApplyMatrices)
03312         {
03313             if(!TransformConvertedObjectDoMatrix(N, &Ma, TranslateForPage))
03314                 return FALSE;
03315         }
03316     }
03317     else if(!HaveMatrix && TranslateForPage)
03318     {
03319         // we need to apply an identity matrix which then gets translated, but only if we need to
03320         cdrMatrix Mi = {1, 0, 0, 0, 1, 0};
03321         
03322         // apply it
03323         if(!TransformConvertedObjectDoMatrix(N, &Mi, TranslateForPage))
03324             return FALSE;
03325     }
03326 
03327     // reverse the effect of the previous translation
03328     if(WorkAtOrigin)
03329     {
03330         Trans2DMatrix Trans(TranslateByX, TranslateByY);
03331         (*N)->Transform(Trans);
03332     }
03333 
03334     return TRUE;
03335 }
03336 
03337 /********************************************************************************************
03338 
03339 >   BOOL CDRFilter::TransformConvertedObjectDoMatrix(NodeRenderable **N, cdrMatrix *Ma, BOOL TranslateForPage)
03340 
03341     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
03342     Created:    18/05/95
03343     Inputs:     the node to transform, and the trfd chunk to transform it by
03344     Returns:    error flag
03345     Purpose:    transforms an object given a CDR matrix
03346     SeeAlso:    Filter
03347 
03348 ********************************************************************************************/
03349 
03350 BOOL CDRFilter::TransformConvertedObjectDoMatrix(NodeRenderable **N, cdrMatrix *Ma, BOOL TranslateForPage)
03351 {
03352     // make a camelot matrix
03353     Matrix M(Ma->a, Ma->d, Ma->b, Ma->e, (INT32)Ma->c + (TranslateForPage?TranslateByX:0),
03354             (INT32)Ma->f + (TranslateForPage?TranslateByY:0));
03355 
03356     // if it's a text story node, then it needs to be dealt with differently, and it's got
03357     // an associated bounding box which need transforming
03358     if(IS_A(*N, TextStory))
03359     {       
03360         // find it's bounding box
03361         DocRect *BBox = TextBBoxes.Find(*N);
03362 
03363         // transform it with the unmodifed matrix
03364         Trans2DMatrix TTransform(M);
03365         if(BBox != 0)
03366             TTransform.GetMatrix().TransformBounds(BBox);
03367 
03368         // if it's a text story, not just an artisitic text then don't scale it, but scale the import width
03369         if(IsTextStory)
03370         {
03371             // work out the scale factors along the axes
03372             double ScaleX = sqrt((Ma->a * Ma->a) + (Ma->b * Ma->b));
03373             double ScaleY = sqrt((Ma->d * Ma->d) + (Ma->e * Ma->e));
03374             
03375             // knock up a new matrix which isn't scaled along these axes
03376             M = Matrix(Ma->a / ScaleX, Ma->d / ScaleY, Ma->b / ScaleX, Ma->e / ScaleY,
03377                     (INT32)Ma->c + (TranslateForPage?TranslateByX:0),
03378                     (INT32)Ma->f + (TranslateForPage?TranslateByY:0));
03379         
03380             // get the import format width scaled nicely
03381             TextStory *TSNode = (TextStory *)(*N);
03382             double Width = ((double)TSNode->GetImportFormatWidth()) * ScaleX;
03383             TSNode->SetImportFormatWidth((INT32)Width);
03384         }
03385     }
03386     
03387     // transform the node
03388     Trans2DMatrix Transform(M);
03389     (*N)->Transform(Transform);
03390 
03391     return TRUE;
03392 }
03393 
03394 
03395 /********************************************************************************************
03396 
03397 >   CDRFilter::TransformConvertedObjectDoPerspective(NodeRenderable *N, cdrPerspective *P, BOOL TranslateShapeForPage = FALSE)
03398 
03399     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
03400     Created:    18/05/95
03401     Inputs:     the node to transform, and the trfd chunk to transform it by
03402     Returns:    error flag
03403     Purpose:    transforms an object given a CDR perspective
03404     SeeAlso:    Filter
03405 
03406 ********************************************************************************************/
03407 
03408 #define PERS_MOVE(co) {if(!pShape->InkPath.InsertMoveTo(co)) return FALSE;}
03409 #define PERS_LINE(co) {if(!pShape->InkPath.InsertLineTo(co)) return FALSE;}
03410 #define PERS_CLOSE {if(!pShape->InkPath.CloseSubPath()) return FALSE;}
03411 
03412 BOOL CDRFilter::TransformConvertedObjectDoPerspective(NodeRenderable **N, cdrPerspective *P, BOOL TranslateShapeForPage)
03413 {
03414 TRACEUSER( "Ben", _T("applying perspective\n"));
03415 
03416     // create a mould parent and insert it in the tree
03417     NodeMould* pMouldParent = new NodeMould;
03418     if (pMouldParent == 0)
03419         return FALSE;
03420 
03421     // give the parent mould object a shape and mould space to work with and stick it
03422     // in the tree
03423     if(!pMouldParent->CreateGeometry(MOULDSPACE_PERSPECTIVE))
03424     {   
03425         delete pMouldParent;
03426         return FALSE;
03427     }
03428 
03429     // create a nice shape to mould into
03430     NodePath *pShape = new NodePath;
03431     if(pShape == 0 || (!pShape->SetUpPath()))
03432     {   
03433         delete pMouldParent;
03434         return FALSE;
03435     }
03436 
03437     // position the new elements at the beginning of the path
03438     pShape->InkPath.FindStartOfPath();
03439 
03440     // make a nice shape out of the corners
03441     DocCoord co;
03442     PERS_MOVE(P->NewCorners[0])
03443     PERS_LINE(P->NewCorners[1])
03444     PERS_LINE(P->NewCorners[2])
03445     PERS_LINE(P->NewCorners[3])
03446     PERS_LINE(P->NewCorners[0])
03447     PERS_CLOSE
03448 
03449     // maybe translate it a bit
03450     DocRect OriginalBBox = P->OriginalBBox;
03451     if(TranslateShapeForPage)
03452     {
03453         Trans2DMatrix Transform(Matrix(TranslateByX, TranslateByY));
03454         pShape->Transform(Transform);
03455     
03456         OriginalBBox.Translate(TranslateByX, TranslateByY);
03457     }
03458 
03459     // Create and add a mould shape object
03460     NodeMouldPath* pNodeMPath = pMouldParent->AddNewMouldShape(&pShape->InkPath, 0, NULL);
03461     if (!pNodeMPath)
03462         return FALSE;
03463 
03464     // set the geometry using this new mould shape
03465     if(!pMouldParent->GetGeometry()->Define(&(pNodeMPath->InkPath), &OriginalBBox))
03466         return FALSE;
03467 
03468     // now create the mould group object
03469     NodeMouldGroup* pMouldGroup = pMouldParent->AddNewMouldGroup(NULL);
03470     if (!pMouldGroup)
03471         return FALSE;
03472 
03473     // and attach the node to the molder group
03474     (*N)->AttachNode((Node *) pMouldGroup, FIRSTCHILD, FALSE);
03475         
03476     // set the node to the converted one
03477     *N = pMouldParent;
03478 
03479     // delete the shape
03480     delete pShape;
03481 
03482     return TRUE;
03483 }
03484 
03485 
03486 /********************************************************************************************
03487 
03488 >   BOOL CDRFilter::TransformConvertedObjectDoEnvelope(NodeRenderable **N, Path *P, DocRect *OriginalBBox, INT32 *Corners, BOOL TranslateShapeForPage = FALSE);
03489 
03490     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
03491     Created:    23/05/95
03492     Inputs:     the node to transform, and the trfd chunk to transform it by
03493     Returns:    error flag
03494     Purpose:    transforms an object given a path to envelope into
03495     SeeAlso:    Filter
03496 
03497 ********************************************************************************************/
03498 
03499 BOOL CDRFilter::TransformConvertedObjectDoEnvelope(NodeRenderable **N, Path *P, DocRect *pOriginalBBox, INT32 *Corners, BOOL TranslateShapeForPage)
03500 {
03501 TRACEUSER( "Ben", _T("applying envelope\n"));
03502 
03503     // create a mould parent and insert it in the tree
03504     NodeMould* pMouldParent = new NodeMould;
03505     if (pMouldParent == 0)
03506         return FALSE;
03507 
03508     // give the parent mould object a shape and mould space to work with and stick it
03509     // in the tree
03510     if(!pMouldParent->CreateGeometry(MOULDSPACE_ENVELOPE))
03511     {   
03512         delete pMouldParent;
03513         return FALSE;
03514     }
03515 
03516     // validate the path a bit, and get a good one if this is duff
03517     Path *Shape = P;
03518     UINT32 errID;
03519     if(pMouldParent->GetGeometry()->Validate(Shape,errID) == FALSE)
03520     {
03521         // OK, it's not suitiable so try to create an approximation which is
03522         Path *NewShape;
03523         if(!pMouldParent->GetGeometry()->MakeValidFrom(&NewShape, Shape, Corners))
03524         {
03525             // couldn't make a proper one, so return TRUE to ignore the moulding
03526             return TRUE;
03527         }
03528 
03529         Shape = NewShape;
03530 
03531         // inc count of approximated envelopes so the user can be warned later
03532         EnvelopesApproximated++;
03533     }
03534     
03535     // maybe translate it a bit
03536     DocRect OriginalBBox = *pOriginalBBox;
03537     if(TranslateShapeForPage)
03538     {
03539         Shape->Translate(TranslateByX, TranslateByY);
03540     
03541         OriginalBBox.Translate(TranslateByX, TranslateByY);
03542     }
03543 
03544     // Create and add a mould shape object
03545     NodeMouldPath* pNodeMPath = pMouldParent->AddNewMouldShape(Shape, 0, NULL);
03546     if (!pNodeMPath)
03547         return FALSE;
03548 
03549     // set the geometry using this new mould shape
03550     if(!pMouldParent->GetGeometry()->Define(&(pNodeMPath->InkPath), &OriginalBBox))
03551         return FALSE;
03552 
03553     // now create the mould group object
03554     NodeMouldGroup* pMouldGroup = pMouldParent->AddNewMouldGroup(NULL);
03555     if (!pMouldGroup)
03556         return FALSE;
03557 
03558     // and attach the node to the molder group
03559     (*N)->AttachNode((Node *) pMouldGroup, FIRSTCHILD, FALSE);
03560         
03561     // set the node to the converted one
03562     *N = pMouldParent;
03563 
03564     // delete any created paths
03565     if(Shape != P)
03566         delete Shape;
03567 
03568     return TRUE;
03569 }
03570 
03571 
03572 /********************************************************************************************
03573 
03574 >   BOOL CDRFilter::TransformConvertedObjectDoExtrude(NodeRenderable **N, cdrExtrudeInfo *Info,
03575             BOOL TranslateShapeForPage = FALSE);
03576 
03577     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
03578     Created:    08/01/96
03579     Inputs:     node to transform, extrude info
03580     Returns:    error flag
03581     Purpose:    performs a extrude transform
03582     SeeAlso:    CDRFilter
03583 
03584 ********************************************************************************************/
03585 
03586 BOOL CDRFilter::TransformConvertedObjectDoExtrude(NodeRenderable **N, cdrExtrudeInfo *Info, BOOL TranslateShapeForPage)
03587 {
03588     // the plan here is to create a new group, and slap the node onto it (it could possibly be
03589     // a group with lots of other stuff under it, but we won't worry about that for the moment)
03590     // Then, wander down the sub-tree attempting to convert all NodeRenderableInk object into
03591     // NodePaths. This will hopefully result in a load of object which can then be transformed
03592 
03593     // first, get one of them there group thingynesseses.
03594     NodeGroup *pTempGroup = new NodeGroup;
03595     if(pTempGroup == 0)
03596         return FALSE;       // no room, oh dear.
03597 
03598     // now attach the thing to it. It isn't attached to anything, so it's easy.
03599     (*N)->AttachNode(pTempGroup, FIRSTCHILD);
03600 
03601     // scan the tree converting non-NodePaths to NodePaths where possible
03602     BecomeA ParamBecomeA(BECOMEA_REPLACE, 
03603                              CC_RUNTIME_CLASS(NodePath),
03604                              NULL);
03605 
03606     // find the first node to think about
03607     Node* Current = (*N); 
03608     while (Current->FindFirstChild() != NULL && !(Current->FindFirstChild())->IsKindOf(CC_RUNTIME_CLASS(TextStory))) 
03609     {
03610         Current = Current->FindFirstChild(); 
03611     }  
03612 
03613     // check each renderable node for not being a path
03614     while(Current != 0)
03615     {
03616         if(Current->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)) && !Current->IsKindOf(CC_RUNTIME_CLASS(NodePath)))
03617         {
03618             if (Current->CanBecomeA(&ParamBecomeA))
03619             {
03620                 // is it a text story?
03621                 if (Current->IsKindOf(CC_RUNTIME_CLASS(TextStory)))
03622                 {
03623                     // give formatting it a go
03624                     ((TextStory *)Current)->FormatAndChildren();
03625                 }
03626                 
03627                 if (!(Current)->DoBecomeA(&ParamBecomeA))
03628                 {
03629                     return FALSE;
03630                 }
03631             }
03632         }
03633 
03634         // get the next one
03635         Current = Current->FindNextDepthFirst(*N);
03636     }
03637 
03638     // now wander through the tree doing the funky transform - find the first one again
03639     Current = pTempGroup; 
03640     while (Current->FindFirstChild() != NULL) 
03641     {
03642         Current = Current->FindFirstChild(); 
03643     }  
03644 
03645     // transform each NodePath
03646     while(Current != 0)
03647     {
03648         if(IS_A(Current, NodePath))
03649         {
03650             if(!TransformConvertedObjectDoExtrudeTransPath((NodePath *)Current, Info))
03651                 return FALSE;       // something very wrong happened
03652         }
03653 
03654         // get the next one
03655         Current = Current->FindNextDepthFirst(pTempGroup);
03656     }
03657 
03658     // update the *N pointer to the node
03659     (*N) = (NodeRenderable *)pTempGroup->FindFirstChild();
03660     ERROR2IF((*N) == 0, FALSE, "Oi! there that node just vanished");
03661     ERROR2IF(!(*N)->IsKindOf(CC_RUNTIME_CLASS(NodeRenderable)), FALSE, "Oh! Mr. Node changing into something non-renderable");
03662 
03663     // remove it from the group
03664     (*N)->UnlinkNodeFromTree();
03665 
03666     // finally, vape that temperary group
03667     delete pTempGroup;
03668     
03669     return TRUE;
03670 }
03671 
03672 /********************************************************************************************
03673 
03674 >   BOOL CDRFilter::TransformConvertedObjectDoExtrudeTransPath(NodePath *pPath, cdrExtrudeInfo *Info)
03675 
03676     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
03677     Created:    09/01/96
03678     Inputs:     path to transform, info about the transform
03679     Returns:    error flag
03680     Purpose:    does the extrude transform on a path
03681     SeeAlso:    CDRFilter
03682 
03683 ********************************************************************************************/
03684 
03685 BOOL CDRFilter::TransformConvertedObjectDoExtrudeTransPath(NodePath *pPath, cdrExtrudeInfo *Info)
03686 {
03687     // check the inputs
03688     ERROR2IF(pPath == 0 || Info == 0, FALSE, "Null something supplied where a raspberry is required");
03689     ERROR2IF(!IS_A(pPath, NodePath), FALSE, "Oi! I asked for a NodePath you silly person");
03690 
03691     // get some useful info about that there path
03692     DocCoord *Coords = pPath->InkPath.GetCoordArray();
03693     ERROR2IF(Coords == 0, FALSE, "Hmmm. I think that path is a bit of a dodgy one really");
03694     INT32 NCoords = pPath->InkPath.GetNumCoords();
03695 
03696     // mild sanity check...
03697     if(Info->Camera.z == 0)
03698         return TRUE;            // don't try this one at home, kiddies
03699 
03700     // prepare a few handy values
03701     FLOAT8 projA = - Info->Camera.x / Info->Camera.z;
03702     FLOAT8 projB = - Info->Camera.y / Info->Camera.z;
03703     FLOAT8 projC = - 1 / Info->Camera.z;
03704 
03705     // run through that path transforming all those lovely cheeky little coordinates
03706     for(INT32 c = 0; c < NCoords; c++)
03707     {
03708         FLOAT8 x = (FLOAT8)Coords[c].x, y = (FLOAT8)Coords[c].y;
03709 
03710         FLOAT8 alpha =  x * Info->Trans.cf11 + y * Info->Trans.cf21 + Info->Trans.cf41;
03711         FLOAT8 beta =   x * Info->Trans.cf12 + y * Info->Trans.cf22 + Info->Trans.cf42;
03712         FLOAT8 gamma =  x * Info->Trans.cf13 + y * Info->Trans.cf23 + Info->Trans.cf43;
03713 
03714         FLOAT8 norm =   gamma * projC + 1;
03715 
03716         Coords[c].x = (INT32)((alpha + gamma * projA) / norm);
03717         Coords[c].y = (INT32)((beta  + gamma * projB) / norm);
03718     }
03719 
03720     // well, wasn't that squishy?
03721     return TRUE;
03722 }
03723 
03724 /********************************************************************************************
03725 
03726 >   BOOL CDRTransformConvertor5::Init(ADDR Data, INT32 Size)
03727 
03728     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
03729     Created:    06/06/95
03730     Inputs:     pointer to trfl list and it's size
03731     Returns:    whether the contents are OK
03732     Purpose:    intialises this convertor
03733     SeeAlso:    CDRFilter
03734 
03735 ********************************************************************************************/
03736 
03737 BOOL CDRTransformConvertor5::Init(ADDR Data, INT32 Size)
03738 {
03739     List = Data;
03740     ListSize = Size;
03741  
03742     ADDR TransformData;
03743 
03744     if(!RIFFFile::FindChunkWithinListContents(List, ListSize, cdrT_trfd, 0, &TransformData, 0))
03745         return 0;
03746 
03747     Trans = (cdrfTransform *)TransformData;
03748  
03749     return TRUE;
03750  }
03751 
03752 
03753 /********************************************************************************************
03754 
03755 >   BOOL CDRTransformConvertor4::Init(ADDR Data, INT32 Size)
03756 
03757     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
03758     Created:    06/06/95
03759     Inputs:     pointer to trfl list and it's size
03760     Returns:    whether the contents are OK
03761     Purpose:    intialises this convertor
03762     SeeAlso:    CDRFilter
03763 
03764 ********************************************************************************************/
03765 
03766 BOOL CDRTransformConvertor4::Init(ADDR Data, INT32 Size)
03767 {
03768     List = Data;
03769     ListSize = Size;
03770  
03771     ADDR TransformData;
03772 
03773     if(!RIFFFile::FindChunkWithinListContents(List, ListSize, cdrT_trfd, 0, &TransformData, 0))
03774         return 0;
03775 
03776     Trans = (cdrfTransformV4 *)TransformData;
03777  
03778     return TRUE;
03779  }
03780 
03781 
03782 /********************************************************************************************
03783 
03784 >   CDRTransformType CDRTransformConvertor5::GetTransformType(UINT32 n)
03785 
03786     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
03787     Created:    26 03 95
03788     Inputs:     transform number
03789     Returns:    a transform type
03790     Purpose:    gets a transform type from an trfd chunk
03791     SeeAlso:    CDRFilter
03792 
03793 ********************************************************************************************/
03794 
03795 CDRTransformType CDRTransformConvertor5::GetTransformType(UINT32 n)
03796 {
03797     if(n >= CDRDATA_WORD(Trans->NTransforms))
03798         return CDRTRANSFORMTYPE_UNKNOWN;
03799 
03800     cdrfTransformHeader *Hdr = (cdrfTransformHeader *)(((ADDR)Trans) + CDRDATA_WORD(Trans->TransformOffsets[n]));
03801 
03802     switch(CDRDATA_WORD(Hdr->Type))
03803     {
03804         case cdrfTRANSFORMTYPE_MATRIX:
03805             return CDRTRANSFORMTYPE_MATRIX;
03806             break;
03807         
03808         case cdrfTRANSFORMTYPE_PERSPECTIVE:
03809             return CDRTRANSFORMTYPE_PERSPECTIVE;
03810             break;
03811         
03812 #ifdef CDR_DOEXTRUDE
03813         case cdrfTRANSFORMTYPE_EXTRUDE:
03814             return CDRTRANSFORMTYPE_EXTRUDE;
03815             break;
03816 #endif
03817 
03818         case cdrfTRANSFORMTYPE_ENVELOPE:
03819             return CDRTRANSFORMTYPE_ENVELOPE;
03820             break;
03821         
03822         default:
03823             TRACEUSER( "Ben", _T("[] Unknown v5 transform type\n"));
03824             break;
03825     }
03826 
03827     return CDRTRANSFORMTYPE_UNKNOWN;
03828 }
03829 
03830 
03831 /********************************************************************************************
03832 
03833 >   CDRTransformType CDRTransformConvertor4::GetTransformType(UINT32 n)
03834 
03835     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
03836     Created:    26 03 95
03837     Inputs:     transform number
03838     Returns:    a transform type
03839     Purpose:    gets a transform type from an trfd chunk
03840     SeeAlso:    CDRFilter
03841 
03842 ********************************************************************************************/
03843 
03844 CDRTransformType CDRTransformConvertor4::GetTransformType(UINT32 n)
03845 {
03846     if(n >= CDRDATA_WORD(Trans->NTransforms))
03847         return CDRTRANSFORMTYPE_UNKNOWN;
03848 
03849     WORD *Offsets = (WORD *)(((ADDR)Trans) + CDRDATA_WORD(Trans->OffsetsStart));
03850     cdrfTransformHeader *Hdr = (cdrfTransformHeader *)(((ADDR)Trans) + CDRDATA_WORD(Offsets[n]));
03851 
03852     switch(CDRDATA_WORD(Hdr->Type))
03853     {
03854         case cdrfTRANSFORMTYPE_MATRIX:
03855             return CDRTRANSFORMTYPE_MATRIX;
03856             break;
03857         
03858         case cdrfTRANSFORMTYPE_PERSPECTIVE:
03859             return CDRTRANSFORMTYPE_PERSPECTIVE;
03860             break;
03861         
03862 #ifdef CDR_DOEXTRUDE
03863         case cdrfTRANSFORMTYPE_EXTRUDE:
03864             return CDRTRANSFORMTYPE_EXTRUDE;
03865             break;
03866 #endif
03867 
03868         case cdrfTRANSFORMTYPE_ENVELOPE:
03869             return CDRTRANSFORMTYPE_ENVELOPE;
03870             break;
03871                     
03872         default:
03873             TRACEUSER( "Ben", _T("[] Unknown v4 transform type\n"));
03874             break;
03875     }
03876 
03877     return CDRTRANSFORMTYPE_UNKNOWN;
03878 }
03879 
03880 
03881 /********************************************************************************************
03882 
03883 >   BOOL CDRTransformConvertor5::GetMatrix(cdrMatrix *M, UINT32 n)
03884 
03885     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
03886     Created:    26 03 95
03887     Inputs:     matrix to convert into, transform number
03888     Returns:    a transform type
03889     Purpose:    converts a matrix from position N
03890     SeeAlso:    CDRFilter
03891 
03892 ********************************************************************************************/
03893 
03894 BOOL CDRTransformConvertor5::GetMatrix(cdrMatrix *M, UINT32 n)
03895 {
03896     if(n >= CDRDATA_WORD(Trans->NTransforms))
03897         return FALSE;
03898 
03899     cdrfTransformHeader *Hdr = (cdrfTransformHeader *)(((ADDR)Trans) + CDRDATA_WORD(Trans->TransformOffsets[n]));
03900 
03901     ERROR3IF(CDRDATA_WORD(Hdr->Type) != cdrfTRANSFORMTYPE_MATRIX, "GetMatrix called for a non matrix trfd entry");
03902     ERROR3IF((sizeof(FLOAT8) / 2) != sizeof(DWORD) || sizeof(DWORD) != 4, "Non valid sizeof assumptions");
03903 
03904     // OK, so apparently either PCs or Acorns store them the wrong way round. Oh well.
03905     FLOAT8 *TData = (FLOAT8 *)(Hdr + 1);
03906     FLOAT8 *Out = (FLOAT8 *)M;
03907 
03908     INT32 l;
03909     for(l = 0; l < 6; l++)
03910     {
03911         Out[l] = CDRDATA_FLOAT8(TData[l]);
03912     }
03913     
03914     // change the translation vector to be in millipoints
03915     M->c *= CDRCOORDS_TO_MILLIPOINTS;
03916     M->f *= CDRCOORDS_TO_MILLIPOINTS;
03917 
03918     return TRUE;
03919 }
03920 
03921 
03922 /********************************************************************************************
03923 
03924 >   BOOL CDRTransformConvertor::ConvertPerspective(cdrPerspective *P, cdrfPerspectiveTransform *Trans)
03925 
03926     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
03927     Created:    18/05/95
03928     Inputs:     perspective to convert into, transform number
03929     Returns:    a transform type
03930     Purpose:    converts corel perspective - used by all the convertors
03931     SeeAlso:    CDRFilter
03932 
03933 ********************************************************************************************/
03934 
03935 BOOL CDRTransformConvertor::ConvertPerspective(cdrPerspective *P, cdrfPerspectiveTransform *Tran)
03936 {
03937     // knock up the bbox
03938     INT32 x0, y0, y1, x1;
03939     x0 = CDRDATA_SWORD(Tran->Ox0) * CDRCOORDS_TO_MILLIPOINTS;
03940     y0 = CDRDATA_SWORD(Tran->Oy0) * CDRCOORDS_TO_MILLIPOINTS;
03941     x1 = CDRDATA_SWORD(Tran->Ox1) * CDRCOORDS_TO_MILLIPOINTS;
03942     y1 = CDRDATA_SWORD(Tran->Oy1) * CDRCOORDS_TO_MILLIPOINTS;
03943 
03944     if(x0 > x1)
03945     {
03946         INT32 t = x1;
03947         x1 = x0;
03948         x0 = t;
03949     }
03950     
03951     if(y0 > y1)
03952     {
03953         INT32 t = y1;
03954         y1 = y0;
03955         y0 = t;
03956     }
03957 
03958     P->OriginalBBox.lo.x = x0;
03959     P->OriginalBBox.lo.y = y0;
03960     P->OriginalBBox.hi.x = x1;
03961     P->OriginalBBox.hi.y = y1;
03962 
03963     // and the new corners
03964     for(INT32 l = 0; l < 4; l++)
03965     {
03966         P->NewCorners[l].x = CDRDATA_SWORD(Tran->NewCorners[l].X) * CDRCOORDS_TO_MILLIPOINTS;
03967         P->NewCorners[l].y = CDRDATA_SWORD(Tran->NewCorners[l].Y) * CDRCOORDS_TO_MILLIPOINTS;
03968     }
03969 
03970     return TRUE;
03971 }
03972 
03973 
03974 /********************************************************************************************
03975 
03976 >   BOOL CDRTransformConvertor5::GetPerspective(cdrPerspective *P, UINT32 n)
03977 
03978     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
03979     Created:    18/05/95
03980     Inputs:     perspective to convert into, transform number
03981     Returns:    a transform type
03982     Purpose:    converts a perspective from position N
03983     SeeAlso:    CDRFilter
03984 
03985 ********************************************************************************************/
03986 
03987 BOOL CDRTransformConvertor5::GetPerspective(cdrPerspective *P, UINT32 n)
03988 {
03989     if(n >= CDRDATA_WORD(Trans->NTransforms))
03990         return FALSE;
03991 
03992     cdrfTransformHeader *Hdr = (cdrfTransformHeader *)(((ADDR)Trans) + CDRDATA_WORD(Trans->TransformOffsets[n]));
03993 
03994     ERROR3IF(CDRDATA_WORD(Hdr->Type) != cdrfTRANSFORMTYPE_PERSPECTIVE, "GetPerspective called for a non matrix trfd entry");
03995 
03996     cdrfPerspectiveEntry *Per = (cdrfPerspectiveEntry *)Hdr;
03997 
03998     return ConvertPerspective(P, &Per->Trans);
03999 }
04000 
04001 
04002 /********************************************************************************************
04003 
04004 >   BOOL CDRTransformConvertor4::GetPerspective(cdrPerspective *P, UINT32 n)
04005 
04006     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04007     Created:    18/05/95
04008     Inputs:     perspective to convert into, transform number
04009     Returns:    a transform type
04010     Purpose:    converts a perspective from position N
04011     SeeAlso:    CDRFilter
04012 
04013 ********************************************************************************************/
04014 
04015 BOOL CDRTransformConvertor4::GetPerspective(cdrPerspective *P, UINT32 n)
04016 {
04017     if(n >= Trans->NTransforms)
04018         return FALSE;
04019 
04020     WORD *Offsets = (WORD *)(((ADDR)Trans) + Trans->OffsetsStart);
04021     cdrfTransformHeader *Hdr = (cdrfTransformHeader *)(((ADDR)Trans) + Offsets[n]);
04022 
04023     ERROR3IF(Hdr->Type != cdrfTRANSFORMTYPE_PERSPECTIVE, "GetPerspective called for a non matrix trfd entry");
04024 
04025     cdrfPerspectiveEntry *Per = (cdrfPerspectiveEntry *)Hdr;
04026 
04027     return ConvertPerspective(P, &  Per->Trans);
04028 }
04029 
04030 
04031 /********************************************************************************************
04032 
04033 >   CDRTransformType CDRTransformConvertor4::GetMatrix(cdrMatrix *M, UINT32 n)
04034 
04035     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04036     Created:    26 03 95
04037     Inputs:     matrix to convert into, transform number
04038     Returns:    a transform type
04039     Purpose:    converts a matrix from position N
04040     SeeAlso:    CDRFilter
04041 
04042 ********************************************************************************************/
04043 
04044 BOOL CDRTransformConvertor4::GetMatrix(cdrMatrix *M, UINT32 n)
04045 {
04046     if(n >= Trans->NTransforms)
04047         return FALSE;
04048 
04049     WORD *Offsets = (WORD *)(((ADDR)Trans) + Trans->OffsetsStart);
04050     cdrfTransformHeader *Hdr = (cdrfTransformHeader *)(((ADDR)Trans) + Offsets[n]);
04051 
04052     ERROR3IF(Hdr->Type != cdrfTRANSFORMTYPE_MATRIX, "GetMatrix called for a non matrix trfd entry");
04053 
04054     // unsigned word pointer
04055     WORD *TDataUS = (WORD *)(Hdr + 1);
04056     // signed word pointer
04057     SWORD *TDataS = (SWORD *)(Hdr + 1);
04058     // signed dword pointer
04059     SDWORD *TDDataS = (SDWORD *)(Hdr + 1);
04060 
04061     // convert the matrix - an interesting mix of 16.16 fixed point values and a
04062     // signed double word translation vector
04063     M->a = (FLOAT8)CDRDATA_SWORD(TDataS[1]) + ((FLOAT8)CDRDATA_WORD(TDataUS[0]) / 0xffff);
04064     M->b = (FLOAT8)CDRDATA_SWORD(TDataS[3]) + ((FLOAT8)CDRDATA_WORD(TDataUS[2]) / 0xffff);
04065     M->c = (FLOAT8)(CDRDATA_DSWORD(TDDataS[2]) * CDRCOORDS_TO_MILLIPOINTS);
04066     M->d = (FLOAT8)CDRDATA_SWORD(TDataS[7]) + ((FLOAT8)CDRDATA_WORD(TDataUS[6]) / 0xffff);
04067     M->e = (FLOAT8)CDRDATA_SWORD(TDataS[9]) + ((FLOAT8)CDRDATA_WORD(TDataUS[8]) / 0xffff);
04068     M->f = (FLOAT8)(CDRDATA_DSWORD(TDDataS[5]) * CDRCOORDS_TO_MILLIPOINTS);
04069 
04070     return TRUE;
04071 }
04072 
04073 
04074 /********************************************************************************************
04075 
04076 >   CDRTransformType CDRTransformConvertor3::GetTransformType(UINT32 n)
04077 
04078     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04079     Created:    03/04/95
04080     Inputs:     transform number
04081     Returns:    a transform type
04082     Purpose:    gets a transform type from an trfd chunk
04083     SeeAlso:    CDRFilter
04084 
04085 ********************************************************************************************/
04086 
04087 CDRTransformType CDRTransformConvertor3::GetTransformType(UINT32 n)
04088 {
04089     if(n >= CDRDATA_WORD(Trans->NTransforms))
04090         return CDRTRANSFORMTYPE_UNKNOWN;
04091 
04092     cdrfTransformEntryV3 *En = (cdrfTransformEntryV3 *)(Trans + 1);
04093 
04094     switch(CDRDATA_WORD(En[n].Type))
04095     {
04096         case cdrfTRANSFORMTYPE_MATRIX_V3:
04097             return CDRTRANSFORMTYPE_MATRIX;
04098             break;
04099         
04100         case cdrfTRANSFORMTYPE_PERSPECTIVE_V3:
04101             return CDRTRANSFORMTYPE_PERSPECTIVE;
04102             break;
04103         
04104         case cdrfTRANSFORMTYPE_ENVELOPE_V3:
04105             return CDRTRANSFORMTYPE_ENVELOPE;
04106             break;
04107         
04108 #ifdef CDR_DOEXTRUDE
04109         case cdrfTRANSFORMTYPE_EXTRUDE_V3:
04110             return CDRTRANSFORMTYPE_EXTRUDE;
04111             break;
04112 #endif
04113 
04114         default:
04115             TRACEUSER( "Ben", _T("[] Unknown v3 transform type %x\n"), En[n].Type);
04116             break;
04117     }
04118 
04119     return CDRTRANSFORMTYPE_UNKNOWN;
04120 }
04121 
04122 
04123 /********************************************************************************************
04124 
04125 >   BOOL CDRTransformConvertor3::GetExtrude(cdrExtrudeInfo *Info, UINT32 n);
04126 
04127     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04128     Created:    08/01/96
04129     Inputs:     extrude info to convert to, transform number
04130     Returns:    a transform type
04131     Purpose:    converts a matrix from position N
04132     SeeAlso:    CDRFilter
04133 
04134 ********************************************************************************************/
04135 
04136 BOOL CDRTransformConvertor3::GetExtrude(cdrExtrudeInfo *Info, UINT32 n)
04137 {
04138     if(n >= CDRDATA_WORD(Trans->NTransforms))
04139         return FALSE;
04140 
04141     cdrfTransformEntryV3 *En = (cdrfTransformEntryV3 *)(Trans + 1);
04142     cdrfTransformExtrudeV3 *Data = (cdrfTransformExtrudeV3 *)(((BYTE *)Trans) + En[n].Offset);
04143 
04144     Info->Trans.cf11 = (FLOAT8)CDRDATA_SWORD(Data->cf11b) + ((FLOAT8)CDRDATA_WORD(Data->cf11a) / 0xffff);
04145     Info->Trans.cf12 = (FLOAT8)CDRDATA_SWORD(Data->cf12b) + ((FLOAT8)CDRDATA_WORD(Data->cf12a) / 0xffff);
04146     Info->Trans.cf13 = (FLOAT8)CDRDATA_SWORD(Data->cf13b) + ((FLOAT8)CDRDATA_WORD(Data->cf13a) / 0xffff);
04147     Info->Trans.cf21 = (FLOAT8)CDRDATA_SWORD(Data->cf21b) + ((FLOAT8)CDRDATA_WORD(Data->cf21a) / 0xffff);
04148     Info->Trans.cf22 = (FLOAT8)CDRDATA_SWORD(Data->cf22b) + ((FLOAT8)CDRDATA_WORD(Data->cf22a) / 0xffff);
04149     Info->Trans.cf23 = (FLOAT8)CDRDATA_SWORD(Data->cf23b) + ((FLOAT8)CDRDATA_WORD(Data->cf23a) / 0xffff);
04150     Info->Trans.cf31 = (FLOAT8)CDRDATA_SWORD(Data->cf31b) + ((FLOAT8)CDRDATA_WORD(Data->cf31a) / 0xffff);
04151     Info->Trans.cf32 = (FLOAT8)CDRDATA_SWORD(Data->cf32b) + ((FLOAT8)CDRDATA_WORD(Data->cf32a) / 0xffff);
04152     Info->Trans.cf33 = (FLOAT8)CDRDATA_SWORD(Data->cf33b) + ((FLOAT8)CDRDATA_WORD(Data->cf33a) / 0xffff);
04153     Info->Trans.cf41 = (FLOAT8)CDRDATA_FLOAT4(Data->f41);
04154     Info->Trans.cf42 = (FLOAT8)CDRDATA_FLOAT4(Data->f42);
04155     Info->Trans.cf43 = (FLOAT8)CDRDATA_FLOAT4(Data->f43);
04156 
04157     Info->Camera.x = CDRDATA_SWORD(Data->Cx) * CDRCOORDS_TO_MILLIPOINTS;
04158     Info->Camera.y = CDRDATA_SWORD(Data->Cy) * CDRCOORDS_TO_MILLIPOINTS;
04159     Info->Camera.z = CDRDATA_DWORD(Data->Cz) * CDRCOORDS_TO_MILLIPOINTS;
04160 
04161     return TRUE;
04162 }
04163 
04164 
04165 /********************************************************************************************
04166 
04167 >   BOOL CDRTransformConvertor::ConvertExtrudeInfo(cdrfTransformExtrude *pTransform, cdrExtrudeInfo *pInfo)
04168 
04169     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04170     Created:    12/01/96
04171     Inputs:     pointer to transform from file, extrude info to convert to
04172     Returns:    error flag
04173     Purpose:    converts an extrude thingy from a v4,5,6 file
04174     SeeAlso:    CDRFilter
04175 
04176 ********************************************************************************************/
04177 
04178 BOOL CDRTransformConvertor::ConvertExtrudeInfo(cdrfTransformExtrude *pTransform, cdrExtrudeInfo *Info)
04179 {
04180     Info->Trans.cf11 = (FLOAT8)CDRDATA_SWORD(pTransform->cf11b) + ((FLOAT8)CDRDATA_WORD(pTransform->cf11a) / 0xffff);
04181     Info->Trans.cf12 = (FLOAT8)CDRDATA_SWORD(pTransform->cf12b) + ((FLOAT8)CDRDATA_WORD(pTransform->cf12a) / 0xffff);
04182     Info->Trans.cf13 = (FLOAT8)CDRDATA_SWORD(pTransform->cf13b) + ((FLOAT8)CDRDATA_WORD(pTransform->cf13a) / 0xffff);
04183     Info->Trans.cf21 = (FLOAT8)CDRDATA_SWORD(pTransform->cf21b) + ((FLOAT8)CDRDATA_WORD(pTransform->cf21a) / 0xffff);
04184     Info->Trans.cf22 = (FLOAT8)CDRDATA_SWORD(pTransform->cf22b) + ((FLOAT8)CDRDATA_WORD(pTransform->cf22a) / 0xffff);
04185     Info->Trans.cf23 = (FLOAT8)CDRDATA_SWORD(pTransform->cf23b) + ((FLOAT8)CDRDATA_WORD(pTransform->cf23a) / 0xffff);
04186     Info->Trans.cf31 = (FLOAT8)CDRDATA_SWORD(pTransform->cf31b) + ((FLOAT8)CDRDATA_WORD(pTransform->cf31a) / 0xffff);
04187     Info->Trans.cf32 = (FLOAT8)CDRDATA_SWORD(pTransform->cf32b) + ((FLOAT8)CDRDATA_WORD(pTransform->cf32a) / 0xffff);
04188     Info->Trans.cf33 = (FLOAT8)CDRDATA_SWORD(pTransform->cf33b) + ((FLOAT8)CDRDATA_WORD(pTransform->cf33a) / 0xffff);
04189     Info->Trans.cf41 = (FLOAT8)CDRDATA_DWORD(pTransform->f41);
04190     Info->Trans.cf42 = (FLOAT8)CDRDATA_DWORD(pTransform->f42);
04191     Info->Trans.cf43 = (FLOAT8)CDRDATA_DWORD(pTransform->f43);
04192 
04193     Info->Camera.x = CDRDATA_SWORD(pTransform->Cx) * CDRCOORDS_TO_MILLIPOINTS;
04194     Info->Camera.y = CDRDATA_SWORD(pTransform->Cy) * CDRCOORDS_TO_MILLIPOINTS;
04195     Info->Camera.z = CDRDATA_DWORD(pTransform->Cz) * CDRCOORDS_TO_MILLIPOINTS;
04196 
04197     return TRUE;
04198 }
04199 
04200 
04201 /********************************************************************************************
04202 
04203 >   BOOL CDRTransformConvertor4::GetExtrude(cdrExtrudeInfo *Info, UINT32 n);
04204 
04205     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04206     Created:    08/01/96
04207     Inputs:     extrude info to convert to, transform number
04208     Returns:    a transform type
04209     Purpose:    converts a matrix from position N
04210     SeeAlso:    CDRFilter
04211 
04212 ********************************************************************************************/
04213 
04214 BOOL CDRTransformConvertor4::GetExtrude(cdrExtrudeInfo *Info, UINT32 n)
04215 {
04216     if(n >= Trans->NTransforms)
04217         return FALSE;
04218 
04219     WORD *Offsets = (WORD *)(((ADDR)Trans) + Trans->OffsetsStart);
04220     cdrfTransformHeader *Hdr = (cdrfTransformHeader *)(((ADDR)Trans) + Offsets[n]);
04221 
04222     return ConvertExtrudeInfo((cdrfTransformExtrude *)Hdr, Info);
04223 }
04224 
04225 
04226 /********************************************************************************************
04227 
04228 >   BOOL CDRTransformConvertor5::GetExtrude(cdrExtrudeInfo *Info, UINT32 n);
04229 
04230     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04231     Created:    08/01/96
04232     Inputs:     extrude info to convert to, transform number
04233     Returns:    a transform type
04234     Purpose:    converts a matrix from position N
04235     SeeAlso:    CDRFilter
04236 
04237 ********************************************************************************************/
04238 
04239 BOOL CDRTransformConvertor5::GetExtrude(cdrExtrudeInfo *Info, UINT32 n)
04240 {
04241     if(n >= CDRDATA_WORD(Trans->NTransforms))
04242         return FALSE;
04243 
04244     cdrfTransformHeader *Hdr = (cdrfTransformHeader *)(((ADDR)Trans) + CDRDATA_WORD(Trans->TransformOffsets[n]));
04245 
04246     return ConvertExtrudeInfo((cdrfTransformExtrude *)Hdr, Info);
04247 }
04248 
04249 
04250 /********************************************************************************************
04251 
04252 >   CDRTransformType CDRTransformConvertor3::GetMatrix(cdrMatrix *M, UINT32 n)
04253 
04254     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04255     Created:    03/04/95
04256     Inputs:     matrix to convert into, transform number
04257     Returns:    a transform type
04258     Purpose:    converts a matrix from position N
04259     SeeAlso:    CDRFilter
04260 
04261 ********************************************************************************************/
04262 
04263 BOOL CDRTransformConvertor3::GetMatrix(cdrMatrix *M, UINT32 n)
04264 {
04265     if(n >= CDRDATA_WORD(Trans->NTransforms))
04266         return FALSE;
04267 
04268     cdrfTransformEntryV3 *En = (cdrfTransformEntryV3 *)(Trans + 1);
04269     BYTE *Data = ((BYTE *)Trans) + En[n].Offset;
04270 
04271     // unsigned word pointer
04272     WORD *TDataUS = (WORD *)Data;
04273     // signed word pointer
04274     SWORD *TDataS = (SWORD *)Data;
04275     // signed dword pointer
04276     SDWORD *TDDataS = (SDWORD *)Data;
04277 
04278     // convert the matrix - an interesting mix of 16.16 fixed point values and a
04279     // signed double word translation vector
04280     M->a = (FLOAT8)CDRDATA_SWORD(TDataS[1]) + ((FLOAT8)CDRDATA_WORD(TDataUS[0]) / 0xffff);
04281     M->b = (FLOAT8)CDRDATA_SWORD(TDataS[3]) + ((FLOAT8)CDRDATA_WORD(TDataUS[2]) / 0xffff);
04282     M->c = (FLOAT8)(CDRDATA_DSWORD(TDDataS[2]) * CDRCOORDS_TO_MILLIPOINTS);
04283     M->d = (FLOAT8)CDRDATA_SWORD(TDataS[7]) + ((FLOAT8)CDRDATA_WORD(TDataUS[6]) / 0xffff);
04284     M->e = (FLOAT8)CDRDATA_SWORD(TDataS[9]) + ((FLOAT8)CDRDATA_WORD(TDataUS[8]) / 0xffff);
04285     M->f = (FLOAT8)(CDRDATA_DSWORD(TDDataS[5]) * CDRCOORDS_TO_MILLIPOINTS);
04286 
04287     return TRUE;
04288 }
04289 
04290 
04291 /********************************************************************************************
04292 
04293 >   BOOL CDRTransformConvertor3::GetPerspective(cdrPerspective *P, UINT32 n)
04294 
04295     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04296     Created:    18/05/95
04297     Inputs:     perspective to convert into, transform number
04298     Returns:    a transform type
04299     Purpose:    converts a perspective from position N
04300     SeeAlso:    CDRFilter
04301 
04302 ********************************************************************************************/
04303 
04304 BOOL CDRTransformConvertor3::GetPerspective(cdrPerspective *P, UINT32 n)
04305 {
04306     if(n >= CDRDATA_WORD(Trans->NTransforms))
04307         return FALSE;
04308 
04309     cdrfTransformEntryV3 *En = (cdrfTransformEntryV3 *)(Trans + 1);
04310     BYTE *Data = ((BYTE *)Trans) + En[n].Offset;
04311 
04312     return ConvertPerspective(P, (cdrfPerspectiveTransform *)Data);
04313 }
04314 
04315 
04316 
04317 /********************************************************************************************
04318 
04319 >   BOOL CDRTransformConvertor::ConvertEnvelopeBBox(ADDR Entry, DocRect *BBox, INT32 *Corners)
04320 
04321     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04322     Created:    06/06/95
04323     Inputs:     Pointer to entry in transform chunk and an output DocRect
04324     Returns:    sucess
04325     Purpose:    converts a envelope original bounding box
04326     SeeAlso:    CDRFilter
04327 
04328 ********************************************************************************************/
04329 
04330 BOOL CDRTransformConvertor::ConvertEnvelopeBBox(ADDR Entry, DocRect *BBox, INT32 *Corners)
04331 {
04332     // get the bounding box;
04333     cdrfTransformEnvelope *En = (cdrfTransformEnvelope *)Entry;
04334 
04335     INT32 x0, y0, y1, x1;
04336     x0 = CDRDATA_SWORD(En->Ox0) * CDRCOORDS_TO_MILLIPOINTS;
04337     y0 = CDRDATA_SWORD(En->Oy0) * CDRCOORDS_TO_MILLIPOINTS;
04338     x1 = CDRDATA_SWORD(En->Ox1) * CDRCOORDS_TO_MILLIPOINTS;
04339     y1 = CDRDATA_SWORD(En->Oy1) * CDRCOORDS_TO_MILLIPOINTS;
04340 
04341     if(x0 > x1)
04342     {
04343         INT32 t = x1;
04344         x1 = x0;
04345         x0 = t;
04346     }
04347     
04348     if(y0 > y1)
04349     {
04350         INT32 t = y1;
04351         y1 = y0;
04352         y0 = t;
04353     }
04354 
04355     BBox->lo.x = x0;
04356     BBox->lo.y = y0;
04357     BBox->hi.x = x1;
04358     BBox->hi.y = y1;
04359 
04360     // fill in the corners
04361     for(INT32 l = 0; l < 4; l++)
04362     {
04363         Corners[l] = CDRDATA_WORD(En->Corners[l]);
04364     }
04365 
04366     return TRUE;
04367 }
04368 
04369 
04370 /********************************************************************************************
04371 
04372 >   BOOL CDRTransformConvertor::ConvertEnvelopePath(ADDR List, INT32 ListSize, INT32 Entry, Path **ppPath);
04373 
04374     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04375     Created:    06/06/95
04376     Inputs:     pointer to list, list size, entry number to get and a pointer to a path to fill in
04377     Returns:    sucess
04378     Purpose:    converts a envelope path
04379     SeeAlso:    CDRFilter
04380 
04381 ********************************************************************************************/
04382 
04383 BOOL CDRTransformConvertor::ConvertEnvelopePath(ADDR List, INT32 ListSize, INT32 Entry, Path **ppPath)
04384 {
04385     // find the envd chunk we're interested in
04386     ADDR Chunk;
04387     INT32 ChunkSize;
04388     if(!RIFFFile::FindChunkWithinListContents(List, ListSize, cdrT_envd, Entry, &Chunk, &ChunkSize))
04389         return FALSE;
04390 
04391     // right, got the thingy...
04392     cdrfOffsetHeader *Hdr = (cdrfOffsetHeader *)Chunk;
04393     INT32 NCoords = CDRDATA_WORD(Hdr->ObjectType);  // hold the number of coords...
04394 
04395     // find the things within the chunk
04396     ADDR Coords = CDRFilter::FindDataInObject(Hdr, cdrfENVELOPEOFFSETTYPE_COORDS);
04397     ADDR Types = CDRFilter::FindDataInObject(Hdr, cdrfENVELOPEOFFSETTYPE_TYPES);
04398 
04399     if(Coords == 0 || Types == 0)
04400         return FALSE;
04401 
04402     // make a path from this all...
04403     // knock up a path node
04404     Path *pPath = new Path;
04405     if(pPath == 0 || (!pPath->Initialise()))
04406     {
04407         delete pPath;
04408         return FALSE;           // no room to create it
04409     }
04410 
04411     // position the new elements at the beginning of the path
04412     pPath->FindStartOfPath();
04413 
04414     if(!CDRFilter::AddElementsToPath(pPath, NCoords, (cdrfCoord *)Coords, Types, 0))
04415         return FALSE;
04416 
04417     // check that the path is OK
04418     if(!pPath->EnsureValid())
04419     {
04420         // no, it's completely knackered
04421         delete pPath;
04422         return FALSE;
04423     }
04424 
04425     // return it...
04426     (*ppPath) = pPath;
04427     
04428     return TRUE;
04429 }
04430 
04431 
04432 /********************************************************************************************
04433 
04434 >   BOOL CDRTransformConvertor5::GetEnvelope(Path **P, DocRect *OriginalBBox, INT32 *Corners, UINT32 n)
04435 
04436     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04437     Created:    23/05/95
04438     Inputs:     pointer to a pointer to a nodepath to fill in, a docrect for the orignial BBox
04439                 and the position
04440     Returns:    a transform type
04441     Purpose:    converts a envelope from position N
04442     SeeAlso:    CDRFilter
04443 
04444 ********************************************************************************************/
04445 
04446 BOOL CDRTransformConvertor5::GetEnvelope(Path **P, DocRect *OriginalBBox, INT32 *Corners, UINT32 n)
04447 {
04448     if(n >= CDRDATA_WORD(Trans->NTransforms))
04449         return FALSE;
04450 
04451     cdrfTransformHeader *Hdr;
04452 
04453     // run through to this entry counting the number of entries before this one
04454     INT32 EnvelopesSoFar = 0;
04455     for(UINT32 l = 0; l <= n; l++)
04456     {
04457         Hdr = (cdrfTransformHeader *)(((ADDR)Trans) + CDRDATA_WORD(Trans->TransformOffsets[l]));
04458 
04459         // increment the number of envelopes so far...
04460         if(CDRDATA_WORD(Hdr->Type) == cdrfTRANSFORMTYPE_ENVELOPE)
04461             EnvelopesSoFar++;
04462     }
04463 
04464     ERROR2IF(EnvelopesSoFar <= 0, FALSE, "No envelopes found!");
04465     
04466     // OK, convert this entry...
04467     if(!ConvertEnvelopeBBox((ADDR)Hdr, OriginalBBox, Corners))
04468         return FALSE;
04469 
04470     if(!ConvertEnvelopePath(List, ListSize, EnvelopesSoFar - 1, P))
04471         return FALSE;
04472 
04473     return TRUE;
04474 }
04475 
04476 
04477 /********************************************************************************************
04478 
04479 >   BOOL CDRTransformConvertor4::GetEnvelope(Path **P, DocRect *OriginalBBox, INT32 *Corners, UINT32 n)
04480 
04481     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04482     Created:    23/05/95
04483     Inputs:     pointer to a pointer to a nodepath to fill in, a docrect for the orignial BBox
04484                 and the position
04485     Returns:    a transform type
04486     Purpose:    converts a envelope from position N
04487     SeeAlso:    CDRFilter
04488 
04489 ********************************************************************************************/
04490 
04491 BOOL CDRTransformConvertor4::GetEnvelope(Path **P, DocRect *OriginalBBox, INT32 *Corners, UINT32 n)
04492 {
04493     if(n >= CDRDATA_WORD(Trans->NTransforms))
04494         return FALSE;
04495 
04496     cdrfTransformHeader *Hdr;
04497     WORD *Offsets = (WORD *)(((ADDR)Trans) + Trans->OffsetsStart);
04498 
04499     // run through to this entry counting the number of entries before this one
04500     INT32 EnvelopesSoFar = 0;
04501     for(UINT32 l = 0; l <= n; l++)
04502     {
04503         Hdr = (cdrfTransformHeader *)(cdrfTransformHeader *)(((ADDR)Trans) + Offsets[l]);
04504 
04505         // increment the number of envelopes so far...
04506         if(CDRDATA_WORD(Hdr->Type) == cdrfTRANSFORMTYPE_ENVELOPE)
04507             EnvelopesSoFar++;
04508     }
04509 
04510     ERROR2IF(EnvelopesSoFar <= 0, FALSE, "No envelopes found!");
04511     
04512     // OK, convert this entry...
04513     if(!ConvertEnvelopeBBox((ADDR)Hdr, OriginalBBox, Corners))
04514         return FALSE;
04515 
04516     if(!ConvertEnvelopePath(List, ListSize, EnvelopesSoFar - 1, P))
04517         return FALSE;
04518 
04519     return TRUE;
04520 }
04521 
04522 
04523 /********************************************************************************************
04524 
04525 >   BOOL CDRTransformConvertor3::GetEnvelope(Path **P, DocRect *OriginalBBox, INT32 *Corners, UINT32 n)
04526 
04527     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04528     Created:    23/05/95
04529     Inputs:     pointer to a pointer to a nodepath to fill in, a docrect for the orignial BBox
04530                 and the position
04531     Returns:    a transform type
04532     Purpose:    converts a envelope from position N
04533     SeeAlso:    CDRFilter
04534 
04535 ********************************************************************************************/
04536 
04537 #define ENVV3_NCOORDS   25
04538 
04539 BOOL CDRTransformConvertor3::GetEnvelope(Path **P, DocRect *OriginalBBox, INT32 *Corners, UINT32 n)
04540 {
04541     if(n >= CDRDATA_WORD(Trans->NTransforms))
04542         return FALSE;
04543 
04544     cdrfTransformEntryV3 *En = (cdrfTransformEntryV3 *)(Trans + 1);
04545     BYTE *Data = ((BYTE *)Trans) + En[n].Offset;
04546 
04547     // make a pointer to the interesting data
04548     cdrfTransformEnvelopeV3 *Env = (cdrfTransformEnvelopeV3 *)Data;
04549 
04550     // convert the original bbox
04551     INT32 x0, y0, y1, x1;
04552     x0 = CDRDATA_SWORD(Env->Ox0) * CDRCOORDS_TO_MILLIPOINTS;
04553     y0 = CDRDATA_SWORD(Env->Oy0) * CDRCOORDS_TO_MILLIPOINTS;
04554     x1 = CDRDATA_SWORD(Env->Ox1) * CDRCOORDS_TO_MILLIPOINTS;
04555     y1 = CDRDATA_SWORD(Env->Oy1) * CDRCOORDS_TO_MILLIPOINTS;
04556 
04557     if(x0 > x1)
04558     {
04559         INT32 t = x1;
04560         x1 = x0;
04561         x0 = t;
04562     }
04563     
04564     if(y0 > y1)
04565     {
04566         INT32 t = y1;
04567         y1 = y0;
04568         y0 = t;
04569     }
04570 
04571     OriginalBBox->lo.x = x0;
04572     OriginalBBox->lo.y = y0;
04573     OriginalBBox->hi.x = x1;
04574     OriginalBBox->hi.y = y1;
04575 
04576     // get the coords
04577     DocCoord Co[ENVV3_NCOORDS];
04578     INT32 l;
04579     for(l = 0; l < ENVV3_NCOORDS; l++)
04580     {
04581         Co[l].x = CDRDATA_SWORD(Env->Coords[l].X) * CDRCOORDS_TO_MILLIPOINTS;
04582         Co[l].y = CDRDATA_SWORD(Env->Coords[l].Y) * CDRCOORDS_TO_MILLIPOINTS;
04583     }
04584 
04585     // create the path
04586     Path *pShape = new Path;
04587     if(pShape == 0 || (!pShape->Initialise()))
04588     {   
04589         delete pShape;
04590         return FALSE;
04591     }
04592 
04593     // position the new elements at the beginning of the path
04594     pShape->FindStartOfPath();
04595 
04596     // make a nice shape out of the corners
04597     if(!pShape->InsertMoveTo(Co[0]))
04598         return FALSE;
04599     for(INT32 c = 1; c < ENVV3_NCOORDS; c += 3)
04600     {                     
04601         if(!pShape->InsertCurveTo(Co[c], Co[c + 1], Co[c + 2]))
04602             return FALSE;
04603     }
04604     if(!pShape->CloseSubPath())
04605         return FALSE;
04606     
04607     *P = pShape;
04608 
04609     // fill in the corners
04610     Corners[0] = 0;
04611     Corners[1] = 6;
04612     Corners[2] = 12;
04613     Corners[3] = 18;
04614 
04615     return TRUE;
04616 }
04617 
04618 
04619 /********************************************************************************************
04620 
04621 >   BOOL CDRFilter::ClearUp(void)
04622 
04623     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04624     Created:    21 03 95
04625     Inputs:     
04626     Returns:    
04627     Purpose:    Clears up after an CDR file import
04628     SeeAlso:    Filter
04629 
04630 ********************************************************************************************/
04631 
04632 BOOL CDRFilter::ClearUp(void)
04633 {
04634     Version = CDRVERSION_NULL;
04635 
04636     if(SlowJobStarted == TRUE)
04637         EndSlowJob();
04638 
04639     if(Success == FALSE)
04640     {
04641         // get rid of the actions list
04642         while(!Actions.IsEmpty())
04643         {
04644             CDRActionListItem *Act = (CDRActionListItem *)Actions.GetTail();
04645 
04646             ERROR3IF(Act == 0, "Returned tail in a non-empty Action list is 0");
04647 
04648             Act->ImportFailure(this);
04649 
04650             delete Actions.RemoveItem(Act);
04651         }
04652 
04653         // get rid of the level's list of nodes
04654         DeleteNodeList(pLevelNodeList);
04655 
04656         // tell everyone about some new layers, if we were doing them
04657         if(UseLayers)
04658         {
04659             LayerSGallery::MakeTopLayerActive(pSpread);
04660             BROADCAST_TO_ALL(SpreadMsg(pSpread, SpreadMsg::LAYERCHANGES));
04661         }
04662     }
04663     
04664 TRACEUSER( "Ben", _T("At CDRFilter::ClearUp(), Fills has %d entries\n"), Fills.GetCount());
04665 TRACEUSER( "Ben", _T("At CDRFilter::ClearUp(), Outlines has %d entries\n"), Outlines.GetCount());
04666 TRACEUSER( "Ben", _T("At CDRFilter::ClearUp(), Styles has %d entries\n"), Styles.GetCount());
04667 TRACEUSER( "Ben", _T("At CDRFilter::ClearUp(), Fonts has %d entries\n"), Fonts.GetCount());
04668 TRACEUSER( "Ben", _T("At CDRFilter::ClearUp(), Arrowheads has %d entries\n"), Arrowheads.GetCount());
04669 TRACEUSER( "Ben", _T("At CDRFilter::ClearUp(), Patterns has %d entries\n"), Patterns.GetCount());
04670 TRACEUSER( "Ben", _T("At CDRFilter::ClearUp(), Bitmaps has %d entries\n"), Bitmaps.GetCount());
04671 TRACEUSER( "Ben", _T("At CDRFilter::ClearUp(), Vectors has %d entries\n"), Vectors.GetCount());
04672 TRACEUSER( "Ben", _T("At CDRFilter::ClearUp(), TextV4 has %d entries\n"), TextV4.GetCount());
04673 TRACEUSER( "Ben", _T("At CDRFilter::ClearUp(), Pages has %d entries\n"), Pages.GetCount());
04674 TRACEUSER( "Ben", _T("At CDRFilter::ClearUp(), Actions has %d entries\n"), Actions.GetCount());
04675 TRACEUSER( "Ben", _T("At CDRFilter::ClearUp(), TextBBoxes has %d entries\n"), TextBBoxes.GetCount());
04676 TRACEUSER( "Ben", _T("At CDRFilter::ClearUp(), TextOnPathLinks has %d entries\n"), TextOnPathLinks.GetCount());
04677 TRACEUSER( "Ben", _T("ObjectsConverted = %d\nObjectsFormatWrong = %d\nObjectsUnknown = %d\nEnvelopesApproximated = %d\n"), ObjectsConverted, ObjectsFormatWrong, ObjectsUnknown, EnvelopesApproximated);
04678 
04679     ERROR3IF(Success == TRUE && Actions.GetCount() != 0, "Not all actions used at the end of a successful CDR convert!");
04680     
04681     Fills.DeleteAll();
04682     Outlines.DeleteAll();
04683     Styles.DeleteAll();
04684     Fonts.DeleteAll();
04685     Arrowheads.DeleteAll();
04686     Patterns.DeleteAll();
04687     Bitmaps.DeleteAll();
04688     Vectors.DeleteAll();
04689     TextV4.DeleteAll();
04690     Pages.DeleteAll();
04691     Actions.DeleteAll();
04692     TextBBoxes.DeleteAll();
04693     TextOnPathLinks.DeleteAll();
04694 
04695     // avoid indexedcolour in uses
04696     ColourCMYK CNullCol;
04697     CNullCol.Cyan = 1;
04698     CNullCol.Magenta = 1;
04699     CNullCol.Yellow = 1;
04700     CNullCol.Key = 1;
04701     DocColour NullCol = DocColour(COLOURMODEL_CMYK, (ColourGeneric *)&CNullCol);
04702     SetLineColour(NullCol);
04703     SetFillColour(NullCol);
04704     
04705     // delete the current attributes
04706     DeleteCurrentAttrs();
04707 
04708     // free a few data blocks
04709     CCFree(ObjDataBlock);
04710     CCFree(FontTableV3);
04711     CCFree(FontStylesV3);
04712     CCFree(LinkTable);
04713 
04714 TRACEUSER( "Ben", _T("ClearUp finished - import of CDR over\n"));
04715     return Success;
04716 }
04717 
04718 
04719 /********************************************************************************************
04720 
04721 >   static void CDRFilter::DeleteNodeList(Node *Start)
04722 
04723     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04724     Created:    27 03 95
04725     Inputs:     
04726     Returns:    
04727     Purpose:    Deletes a linked list of nodes (forward direction only)
04728     SeeAlso:    Filter
04729 
04730 ********************************************************************************************/
04731 
04732 void CDRFilter::DeleteNodeList(Node *Start)
04733 {
04734     Node *This, *Next;
04735 
04736     This = Start;
04737 
04738     while(This != 0)
04739     {
04740         Next = This->FindNext();
04741 
04742         This->CascadeDelete();
04743 
04744         delete This;
04745 
04746         This = Next;
04747     }
04748 }
04749 
04750 
04751 /********************************************************************************************
04752 
04753 >   BOOL CDRFilter::DoExport(Operation*, CCLexFile*, PathName*, Document*);
04754 
04755     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04756     Created:    21 03 95
04757     Inputs:     As for the Filter class
04758     Returns:    As for the Filter class
04759     Purpose:    Refuses to export a Corel Palette file
04760     SeeAlso:    Filter
04761 
04762 ********************************************************************************************/
04763 
04764 BOOL CDRFilter::DoExport(Operation*, CCLexFile*, PathName*, Document*, BOOL)
04765 {
04766     // No exporting here
04767     return FALSE;
04768 }
04769 
04770 
04771 /********************************************************************************************
04772 
04773 >   BOOL CDRAttributeStore::AddChunkToStore(RIFFFile *RIFF)
04774 
04775     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04776     Created:    22 03 95
04777     Inputs:     A RIFFFile object
04778     Returns:    error flag
04779     Purpose:    Stores attibute chunks for the CDRFilter class
04780     SeeAlso:    CDRFilter
04781 
04782 ********************************************************************************************/
04783 
04784 BOOL CDRAttributeStore::AddChunkToStore(RIFFFile *RIFF)
04785 {
04786     if(RIFF->GetObjType() != RIFFOBJECTTYPE_CHUNK)
04787     {
04788         ERROR2(FALSE, "CDRAttributeStore::AddChunkToStore called without a chunk in the RIFFFile");
04789     }
04790 
04791     // get a new item obect
04792     CDRAttributeStoredItem *Item = new CDRAttributeStoredItem;
04793 
04794     if(Item == 0)
04795         return FALSE;
04796 
04797     // get the data of the RIFF chunk
04798     if(!Item->Aquire(RIFF))
04799     {
04800         delete Item;
04801         return FALSE;
04802     }
04803 
04804     Item->Size = RIFF->GetObjSize();
04805 
04806     // and add the new item to the list
04807     AddTail(Item);
04808 
04809     return TRUE;
04810 }
04811 
04812 
04813 /********************************************************************************************
04814 
04815 >   BOOL CDRAttributeStore::Find(DWORD Reference, INT32 *Size)
04816 
04817     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04818     Created:    22 03 95
04819     Inputs:     reference to the object (DWORD)
04820     Returns:    error flag
04821     Purpose:    Finds a chunk in the store of objects using the reference given
04822     SeeAlso:    CDRFilter
04823 
04824 ********************************************************************************************/
04825 
04826 ADDR CDRAttributeStore::Find(DWORD Reference, INT32 *Size)
04827 {
04828     CDRAttributeStoredItem *Item;
04829 
04830     if(IsEmpty())
04831         return 0;       // no items in the list
04832     
04833     Item = (CDRAttributeStoredItem *)GetHead();
04834 
04835     // scan though the list looking for the reference
04836     while(Item != 0)
04837     {
04838         if(CDRDATA_DWORD(*((DWORD *)(Item->Block))) == Reference)
04839         {
04840             *Size = Item->Size;
04841             return Item->Block;
04842         }
04843 
04844         Item = (CDRAttributeStoredItem *)GetNext(Item);
04845     }
04846 
04847     return 0;
04848 }
04849 
04850 
04851 /********************************************************************************************
04852 
04853 >   BOOL CDRAttributeStore::Find(WORD Reference, INT32 *Size)
04854 
04855     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04856     Created:    22 03 95
04857     Inputs:     reference to the object (WORD)
04858     Returns:    error flag
04859     Purpose:    Finds a chunk in the store of objects using the reference given
04860     SeeAlso:    CDRFilter
04861 
04862 ********************************************************************************************/
04863 
04864 ADDR CDRAttributeStore::Find(WORD Reference, INT32 *Size)
04865 {
04866     CDRAttributeStoredItem *Item;
04867 
04868     if(IsEmpty())
04869         return 0;       // no items in the list
04870     
04871     Item = (CDRAttributeStoredItem *)GetHead();
04872 
04873     // scan though the list looking for the reference
04874     while(Item != 0)
04875     {
04876         if(CDRDATA_WORD(*((WORD *)(Item->Block))) == Reference)
04877         {
04878             *Size = Item->Size;
04879             return Item->Block;
04880         }
04881 
04882         Item = (CDRAttributeStoredItem *)GetNext(Item);
04883     }
04884 
04885     return 0;
04886 }
04887 
04888 
04889 /********************************************************************************************
04890 
04891 >   CDRAttributeStoredItem::CDRAttributeStoredItem(void)
04892 
04893     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04894     Created:    22 03 95
04895     Inputs:     
04896     Returns:    
04897     Purpose:    Constructor
04898     SeeAlso:    CDRAttributeStore
04899 
04900 ********************************************************************************************/
04901 
04902 CDRAttributeStoredItem::CDRAttributeStoredItem(void)
04903 {
04904     Block = 0;
04905 }
04906 
04907 
04908 /********************************************************************************************
04909 
04910 >   CDRAttributeStoredItem::~CDRAttributeStoredItem(void)
04911 
04912     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04913     Created:    22 03 95
04914     Inputs:     
04915     Returns:    
04916     Purpose:    Destructor
04917     SeeAlso:    CDRAttributeStore
04918 
04919 ********************************************************************************************/
04920 
04921 CDRAttributeStoredItem::~CDRAttributeStoredItem(void)
04922 {
04923     CCFree(Block);
04924 }
04925 
04926 
04927 /********************************************************************************************
04928 
04929 >   BOOL CDRAttributeStoredItem::~CDRAttributeStoredItem(void)
04930 
04931     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04932     Created:    22 03 95
04933     Inputs:     
04934     Returns:    
04935     Purpose:    Destructor
04936     SeeAlso:    CDRAttributeStore
04937 
04938 ********************************************************************************************/
04939 
04940 BOOL CDRAttributeStoredItem::Aquire(RIFFFile *RIFF)
04941 {
04942     ERROR3IF(Block != 0, "CDRAttributeStoredItem already has data");
04943 
04944     Size = RIFF->GetObjSize();
04945     
04946     // get a block of memory
04947     if((Block = (ADDR)CCMalloc(Size)) == 0)
04948         return FALSE;
04949 
04950     // get the data of the object into it
04951     if(!RIFF->GetChunkData(Block, Size))
04952         return FALSE;
04953 
04954     // bye
04955     return TRUE;
04956 }
04957 
04958 
04959 /********************************************************************************************
04960              
04961 >   CDRLayerListItem::CDRLayerListItem()
04962 
04963     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04964     Created:    24 03 95
04965     Inputs:     
04966     Returns:    
04967     Purpose:    Constructor
04968     SeeAlso:    CDRLayerList
04969 
04970 ********************************************************************************************/
04971 
04972 CDRLayerListItem::CDRLayerListItem()
04973 {
04974     Objects = 0;
04975     LayerInDocument = FALSE;
04976     IsVisible = TRUE;
04977     IsLocked = FALSE;
04978 }
04979 
04980 
04981 /********************************************************************************************
04982              
04983 >   CDRLayerListItem::~CDRLayerListItem()
04984 
04985     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
04986     Created:    24 03 95
04987     Inputs:     
04988     Returns:    
04989     Purpose:    Destructor
04990     SeeAlso:    CDRLayerList
04991 
04992 ********************************************************************************************/
04993 
04994 CDRLayerListItem::~CDRLayerListItem()
04995 {
04996     Node *Previous;
04997     Node *This;
04998 
04999     This = Objects;
05000 
05001     if(LayerInDocument == FALSE)
05002     {   
05003         // delete the tree if it hasn't been used in the document
05004         while(This != 0)
05005         {
05006             // check that the node we're about to delete hasn't got a next pointer
05007             // as it jolly well shouldn't have one as we create the tree backwards
05008             ERROR3IF(This->FindNext() != 0, "Node in layer has next pointer during deletion");
05009             
05010             // find the previous node
05011             Previous = This->FindPrevious();
05012             
05013             // delete the current one's children
05014             This->CascadeDelete();
05015 
05016             // and delete the current one
05017             delete This;
05018 
05019             // shuffle backwards
05020             This = Previous;
05021         }
05022         Objects = 0;
05023     }
05024 }
05025 
05026 
05027 /********************************************************************************************
05028              
05029 >   CDRLayerList::CDRLayerList()
05030 
05031     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
05032     Created:    24 03 95
05033     Inputs:     
05034     Returns:    
05035     Purpose:    Constructor
05036     SeeAlso:    CDRLayerList
05037 
05038 ********************************************************************************************/
05039 
05040 CDRLayerList::CDRLayerList()
05041 {
05042 }
05043 
05044 
05045 /********************************************************************************************
05046              
05047 >   CDRLayerList::~CDRLayerList()
05048 
05049     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
05050     Created:    24 03 95
05051     Inputs:     
05052     Returns:    
05053     Purpose:    Destructor so we can delete all the pages with one DeleteAll call
05054     SeeAlso:    CDRLayerList
05055 
05056 ********************************************************************************************/
05057 
05058 CDRLayerList::~CDRLayerList()
05059 {
05060     DeleteAll();
05061 }
05062 
05063 
05064 /********************************************************************************************
05065              
05066 >   CDRPageList::CDRPageList()
05067 
05068     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
05069     Created:    24 03 95
05070     Inputs:     
05071     Returns:    
05072     Purpose:    Constructor
05073     SeeAlso:    CDRLayerList
05074 
05075 ********************************************************************************************/
05076 
05077 CDRPageList::CDRPageList()
05078 {
05079 }
05080 
05081 
05082 /********************************************************************************************
05083              
05084 >   CDRPageList::~CDRPageList()
05085 
05086     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
05087     Created:    24 03 95
05088     Inputs:     
05089     Returns:    
05090     Purpose:    Destructor
05091     SeeAlso:    CDRLayerList
05092 
05093 ********************************************************************************************/
05094 
05095 CDRPageList::~CDRPageList()
05096 {
05097 }
05098 
05099 
05100 /********************************************************************************************
05101              
05102 >   CDRPageListItem::CDRPageListItem()
05103 
05104     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
05105     Created:    24 03 95
05106     Inputs:     
05107     Returns:    
05108     Purpose:    Constructor
05109     SeeAlso:    CDRLayerList
05110 
05111 ********************************************************************************************/
05112 
05113 CDRPageListItem::CDRPageListItem()
05114 {
05115 }
05116 
05117 
05118 /********************************************************************************************
05119              
05120 >   CDRPageListItem::~CDRPageListItem()
05121 
05122     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
05123     Created:    24 03 95
05124     Inputs:     
05125     Returns:    
05126     Purpose:    Destructor
05127     SeeAlso:    CDRLayerList
05128 
05129 ********************************************************************************************/
05130 
05131 CDRPageListItem::~CDRPageListItem()
05132 {
05133 }
05134 
05135 
05136 
05137 
05138 
05139 /********************************************************************************************
05140              
05141 >   static BOOL CDRFilter::HasCDRFileGotCMXFile(PathName *FileName, CCDiskFile *pFile = NULL)
05142 
05143     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
05144     Created:    20/08/96
05145     Inputs:     pathname of file to check, or pointer to disk file
05146     Returns:    whether it has got a cmx file embedded in it
05147     Purpose:    to find out whether a CDR file has got a CMX file in it, and therefore
05148                 whether the CMX filter should grab it instead of this one
05149 
05150 ********************************************************************************************/
05151 
05152 BOOL CDRFilter::HasCDRFileGotCMXFile(PathName *FileName, CCLexFile *pFile)
05153 {
05154     CCDiskFile oTheFile;
05155     CCLexFile *pTheFile;
05156     INT32 pos;
05157 
05158     if(pFile == NULL)
05159     {
05160         if (!(oTheFile.open(*FileName, ios::in | ios::binary)))
05161         {
05162             TRACEUSER( "Ben", _T("couldn't open file to check it for CMX\n"));
05163             return FALSE;
05164         }
05165         pTheFile = &oTheFile;
05166     }
05167     else
05168     {
05169         pTheFile = pFile;
05170         pos = pFile->tellIn();
05171     }
05172 
05173     // read in the file header, and check it's a riff file
05174     RIFFFile_Header Hdr;
05175     pTheFile->read(&Hdr, sizeof(Hdr));
05176 
05177     if(Hdr.CK.ckID != RIFFTYPE_RIFF)
05178         return FALSE;           // file is not a riff form
05179 
05180     UINT32 loc = sizeof(Hdr);
05181 
05182     // run through the thingys
05183     BOOL Found = FALSE;
05184     while(loc < Hdr.CK.ckSize)
05185     {
05186         RIFFck ck;
05187         pTheFile->read(&ck, sizeof(ck));
05188         loc += sizeof(ck);
05189         if(ck.ckID == cdrT_cmx1)
05190         {
05191             // found the cmx section
05192             Found = TRUE;
05193             break;  // we can stop now
05194         }
05195 
05196         // skip to start of next chunk
05197         loc += ck.ckSize;
05198         pTheFile->seekIn(loc);
05199     }
05200 
05201     // close it or clear up...
05202     if(pFile == NULL)
05203     {
05204         oTheFile.close();
05205     }
05206     else
05207     {
05208         pFile->seekIn(pos);
05209     }
05210     
05211     return Found;
05212 }
05213 
05214 

Generated on Sat Nov 10 03:44:41 2007 for Camelot by  doxygen 1.4.4