cmxexdc.cpp

Go to the documentation of this file.
00001 // $Id: cmxexdc.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 // CMX export device context
00099 
00100 #include <math.h>
00101 #include "camtypes.h"
00102 //#include "ccfile.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00103 #include "cmxexdc.h"
00104 #include "cmxform.h"
00105 #include "riffform.h"
00106 //#include "docrect.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 #include "colormgr.h"
00108 //#include "colmodel.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 #include "camelot.h"
00110 #include "cversion.h"
00111 #include "prvwflt.h"
00112 //#include "extfilts.h"
00113 #include "product.h"
00114 #include "hardwaremanager.h"
00115 using namespace oilHardwareManager;
00116 
00117 CC_IMPLEMENT_DYNAMIC(CMXFutureUpdater, CCObject);
00118 CC_IMPLEMENT_DYNAMIC(CMXFutureLength, CMXFutureUpdater);
00119 CC_IMPLEMENT_DYNAMIC(CMXFutureNumber, CMXFutureUpdater);
00120 CC_IMPLEMENT_DYNAMIC(CMXFutureIndex, CMXFutureUpdater);
00121 CC_IMPLEMENT_DYNAMIC(CMXReferListItem, ListItem);
00122 CC_IMPLEMENT_DYNAMIC(CMXReferListItemOffset, CMXReferListItem);
00123 CC_IMPLEMENT_DYNAMIC(CMXReferLayer, CMXReferListItemOffset);
00124 CC_IMPLEMENT_DYNAMIC(CMXReferMasterIndex, CMXReferListItemOffset);
00125 CC_IMPLEMENT_DYNAMIC(CMXReferPage, CMXReferListItemOffset);
00126 CC_IMPLEMENT_DYNAMIC(CMXReferMasterLayer, CMXReferListItemOffset);
00127 CC_IMPLEMENT_DYNAMIC(CMXReferColour, CMXReferListItem);
00128 CC_IMPLEMENT_DYNAMIC(CMXReferDefaultScreen, CMXReferListItem);
00129 CC_IMPLEMENT_DYNAMIC(CMXReferDefaultDotDash, CMXReferDotDash);
00130 CC_IMPLEMENT_DYNAMIC(CMXReferPen, CMXReferListItem);
00131 CC_IMPLEMENT_DYNAMIC(CMXReferArrowheads, CMXReferListItem);
00132 CC_IMPLEMENT_DYNAMIC(CMXReferArrow, CMXReferListItem);
00133 CC_IMPLEMENT_DYNAMIC(CMXReferLens, CMXReferListItem);
00134 CC_IMPLEMENT_DYNAMIC(CMXReferLineStyle, CMXReferListItem);
00135 CC_IMPLEMENT_DYNAMIC(CMXReferOutline, CMXReferListItem);
00136 CC_IMPLEMENT_DYNAMIC(CMXReferBitmap, CMXReferListItem);
00137 CC_IMPLEMENT_DYNAMIC(CMXReferBitmapFill, CMXReferListItem);
00138 CC_IMPLEMENT_DYNAMIC(CMXReferDotDash, CMXReferListItem);
00139 CC_IMPLEMENT_DYNAMIC(CMXGroupRecord, ListItem);
00140 CC_IMPLEMENT_DYNAMIC(CMXNestedTagRecord, ListItem);
00141 CC_IMPLEMENT_DYNAMIC(CMXLensBBox, ListItem);
00142 
00143 /********************************************************************************************
00144 
00145 >   CMXFutureUpdater::CMXFutureUpdater()
00146 
00147     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00148     Created:    21/06/96
00149     Inputs:     none
00150     Returns:    none
00151     Purpose:    constructor
00152     SeeAlso:    
00153 
00154 ********************************************************************************************/
00155 
00156 CMXFutureUpdater::CMXFutureUpdater()
00157 {
00158     AbsPosition = -1;
00159     DataSize = 0;
00160 }
00161 
00162 
00163 /********************************************************************************************
00164 
00165 >   CMXFutureUpdater::CMXFutureUpdater()
00166 
00167     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00168     Created:    21/06/96
00169     Inputs:     none
00170     Returns:    none
00171     Purpose:    destructor
00172     SeeAlso:    
00173 
00174 ********************************************************************************************/
00175 
00176 CMXFutureUpdater::~CMXFutureUpdater()
00177 {
00178     if(AbsPosition >= 0)
00179         TRACEUSER( "Ben", _T("AWWOOOOGA! CMXFutureUpdated deleted, but not written\n\n"));
00180 }
00181 
00182 
00183 /********************************************************************************************
00184 
00185 >   BOOL CMXFutureUpdater::Init(CMXExportDC *pDC, INT32 RelativePos, UINT32 DataSize)
00186 
00187     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00188     Created:    21/06/96
00189     Inputs:     export dc, relative position (+ve = forwards in file), size of data
00190     Returns:    none
00191     Purpose:    initialises a updater object
00192     SeeAlso:    
00193 
00194 ********************************************************************************************/
00195 
00196 BOOL CMXFutureUpdater::Init(CMXExportDC *pDC, INT32 RelativePos, UINT32 tDataSize)
00197 {
00198     ERROR2IF(AbsPosition >= 0, FALSE, "Updater already initialised");
00199     ERROR2IF(pDC == 0, FALSE, "No pDC, chaps");
00200     ERROR2IF(DataSize < 0 || DataSize > 4, FALSE, "Bit of a data size problem really");
00201 
00202     INT32 CurrentPos = pDC->GetFilePosition();
00203     ERROR2IF(CurrentPos < 0, FALSE, "Whoops -- negative file position here");
00204     AbsPosition = CurrentPos + RelativePos;
00205     ERROR2IF(AbsPosition < 0, FALSE, "Serious Bummer -- expected to update a position before the start of the file");
00206     DataSize = tDataSize;
00207 
00208     return TRUE;
00209 }
00210 
00211 /********************************************************************************************
00212 
00213 >   BOOL CMXFutureUpdater::WriteValue(CMXExportDC *pDC, INT32 Value)
00214 
00215     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00216     Created:    21/06/96
00217     Inputs:     export dc, value
00218     Returns:    none
00219     Purpose:    writes a value to the file
00220     SeeAlso:    
00221 
00222 ********************************************************************************************/
00223 
00224 BOOL CMXFutureUpdater::WriteValue(CMXExportDC *pDC, INT32 Value)
00225 {
00226     ERROR2IF(pDC == 0, FALSE, "No pDC, chaps");
00227 
00228     // write the number
00229     if(!pDC->WriteNumber(AbsPosition, DataSize, Value))
00230         return FALSE;
00231 
00232     // reset everything for the next run, should we want one.
00233     AbsPosition = -1;
00234     DataSize = 0;
00235     Reset();            // get the derivedness to reset itself too.
00236 
00237     return TRUE;
00238 }
00239 
00240 
00241 /********************************************************************************************
00242 
00243 >   CMXFutureLength::CMXFutureLength()
00244 
00245     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00246     Created:    21/06/96
00247     Inputs:     none
00248     Returns:    none
00249     Purpose:    constructor
00250     SeeAlso:    
00251 
00252 ********************************************************************************************/
00253 
00254 CMXFutureLength::CMXFutureLength()
00255 {
00256     StartPos = -1;
00257 }
00258 
00259 /********************************************************************************************
00260 
00261 >   BOOL CMXFutureLength::SetLengthStartPos(CMXExportDC *pDC, INT32 RelativePos);
00262 
00263     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00264     Created:    21/06/96
00265     Inputs:     export dc, relative position from current position (+ve is forwards)
00266     Returns:    none
00267     Purpose:    sets the start position of the length which is to be written
00268     SeeAlso:    
00269 
00270 ********************************************************************************************/
00271 
00272 BOOL CMXFutureLength::SetLengthStartPos(CMXExportDC *pDC, INT32 RelativePos)
00273 {
00274     ERROR2IF(StartPos >= 0, FALSE, "Start position already set");
00275     ERROR2IF(pDC == 0, FALSE, "No dc");
00276     StartPos = pDC->GetFilePosition() + RelativePos;
00277 
00278     return TRUE;
00279 }
00280 
00281 
00282 /********************************************************************************************
00283 
00284 >   void CMXFutureLength::Reset(void)
00285 
00286     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00287     Created:    21/06/96
00288     Inputs:     export dc, relative position from current position (+ve is forwards)
00289     Returns:    none
00290     Purpose:    resets the future updater object after a write
00291     SeeAlso:    
00292 
00293 ********************************************************************************************/
00294 
00295 void CMXFutureLength::Reset(void)
00296 {
00297     StartPos = -1;
00298 }
00299 
00300 
00301 /********************************************************************************************
00302 
00303 >   BOOL CMXFutureLength::Write(CMXExportDC *pDC)
00304 
00305     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00306     Created:    21/06/96
00307     Inputs:     export dc
00308     Returns:    none
00309     Purpose:    writes the length to the file. The length is the (+ve) value from the
00310                 start position set earlier to the current position in the file.
00311     SeeAlso:    
00312 
00313 ********************************************************************************************/
00314 
00315 BOOL CMXFutureLength::Write(CMXExportDC *pDC)
00316 {
00317     ERROR2IF(pDC == 0, FALSE, "No dc");
00318     ERROR2IF(StartPos < 0, FALSE, "StartPos is negative... has this length been initialised properly?");
00319 
00320     INT32 len = pDC->GetFilePosition() - StartPos;
00321 
00322     ERROR2IF(len < 0, FALSE, "We're talking negative lengths here? I don't think so");
00323     
00324     return WriteValue(pDC, len);
00325 }
00326 
00327 /********************************************************************************************
00328 
00329 >   BOOL CMXFutureIndex::Write(CMXExportDC *pDC)
00330 
00331     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00332     Created:    21/06/96
00333     Inputs:     export dc
00334     Returns:    none
00335     Purpose:    writes the index to the file. The index is the current file position.
00336     SeeAlso:    
00337 
00338 ********************************************************************************************/
00339 
00340 BOOL CMXFutureIndex::Write(CMXExportDC *pDC)
00341 {
00342     ERROR2IF(pDC == 0, FALSE, "No dc");
00343 
00344     return WriteValue(pDC, pDC->GetFilePosition());
00345 }
00346 
00347 
00348 /********************************************************************************************
00349 
00350 >   BOOL CMXFutureIndex::Write(CMXExportDC *pDC)
00351 
00352     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00353     Created:    21/06/96
00354     Inputs:     export dc
00355     Returns:    none
00356     Purpose:    writes the number to the file
00357     SeeAlso:    
00358 
00359 ********************************************************************************************/
00360 
00361 BOOL CMXFutureNumber::Write(CMXExportDC *pDC)
00362 {
00363     ERROR2IF(pDC == 0, FALSE, "No dc");
00364 
00365     return WriteValue(pDC, Number);
00366 }
00367 
00368 /********************************************************************************************
00369 
00370 >   CMXReferListItemOffset::CMXReferListItemOffset(CMXExportDC *pDC)
00371 
00372     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00373     Created:    21/06/96
00374     Inputs:     export dc
00375     Returns:    none
00376     Purpose:    constructs the refer list item by getting the offset
00377     SeeAlso:    
00378 
00379 ********************************************************************************************/
00380 
00381 CMXReferListItemOffset::CMXReferListItemOffset(CMXExportDC *pDC)
00382     : CMXReferListItem(pDC)
00383 {
00384     Offset = pDC->GetFilePosition();        // will throw an exception if it goes wrong
00385 }
00386 
00387 
00388 /********************************************************************************************
00389 
00390 >   void CMXReferLayer::SetLayerDetails(WORD Number, String_256 *tName)
00391 
00392     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00393     Created:    26/06/96
00394     Inputs:     layer number, name
00395     Returns:    none
00396     Purpose:    sets the layer details
00397     SeeAlso:    
00398 
00399 ********************************************************************************************/
00400 
00401 void CMXReferLayer::SetLayerDetails(WORD Number, String_256 *tName)
00402 {
00403     LayerNumber = Number;
00404     Name = *tName;
00405 }
00406 
00407 
00408 /********************************************************************************************
00409 
00410 >   BOOL CMXReferLayer::WriteInReferenceList(CMXExportDC *pDC)
00411 
00412     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00413     Created:    26/06/96
00414     Inputs:     export dc
00415     Returns:    sucess
00416     Purpose:    writes the relevant entry in the reference list of the file
00417     SeeAlso:    
00418 
00419 ********************************************************************************************/
00420 
00421 BOOL CMXReferLayer::WriteInReferenceList(CMXExportDC *pDC)
00422 {
00423     ERROR2IF(pDC == 0, FALSE, "no DC");
00424 
00425     // write the entry
00426     cmxRefListEntryRef en;
00427     memset(&en, '\0', sizeof(en));
00428 
00429     en.Association = cmxREFLISTEN_DESC_COMPONENT;
00430     en.Type = cmxREFLISTEN_TYPE_LAYER;
00431     en.ReferenceNumber = LayerNumber;
00432 
00433     pDC->WriteData(&en, sizeof(en));
00434 
00435     return TRUE;
00436 }
00437 
00438 
00439 /********************************************************************************************
00440 
00441 >   INT32 CMXReferLayer::IndexEntrySize(CMXExportDC *pDC)
00442 
00443     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00444     Created:    26/06/96
00445     Inputs:     none
00446     Returns:    length of entry we'll write
00447     Purpose:    gets the length of the entry we'll write in the index
00448     SeeAlso:    
00449 
00450 ********************************************************************************************/
00451 
00452 INT32 CMXReferLayer::IndexEntrySize(CMXExportDC *pDC)
00453 {
00454     ERROR2IF(pDC == NULL, 0, "no dc");
00455     
00456     INT32 StrLen = Name.Length();
00457 
00458     return StrLen + sizeof(WORD) + sizeof(DWORD) * 2 + ((pDC->IsThirtyTwoBit())?sizeof(WORD):0);
00459 }
00460 
00461 
00462 /********************************************************************************************
00463 
00464 >   BOOL CMXReferLayer::WriteInIndex(CMXExportDC *pDC)
00465 
00466     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00467     Created:    26/06/96
00468     Inputs:     export dc
00469     Returns:    none
00470     Purpose:    writes the layer details in the layer list
00471     SeeAlso:    
00472 
00473 ********************************************************************************************/
00474 
00475 BOOL CMXReferLayer::WriteInIndex(CMXExportDC *pDC)
00476 {
00477     // write size in file
00478     pDC->WriteSizeInFile(Name.Length() + sizeof(DWORD) * 2);
00479 
00480     DWORD tOffset = Offset;
00481     pDC->WriteData(&tOffset, sizeof(tOffset));
00482 
00483     pDC->WriteString(&Name);
00484 
00485     SDWORD RefList = -1;
00486     pDC->WriteData(&RefList, sizeof(RefList));
00487 
00488     return TRUE;
00489 }
00490 
00491 
00492 /********************************************************************************************
00493 
00494 >   BOOL CMXReferPage::WriteInIndex(CMXExportDC *pDC)
00495 
00496     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00497     Created:    26/06/96
00498     Inputs:     export dc
00499     Returns:    none
00500     Purpose:    writes the page details in the layer list
00501     SeeAlso:    
00502 
00503 ********************************************************************************************/
00504 
00505 BOOL CMXReferPage::WriteInIndex(CMXExportDC *pDC)
00506 {
00507 
00508     // write the entry
00509     cmxPageIndexEntry pe;
00510 
00511     // write size in file
00512     pDC->WriteSizeInFile(sizeof(pe));
00513 
00514     pe.PageOffset = Offset;
00515     pe.LayerTableOffset = LayerTableOffset;
00516     pe.ThumbnailOffset = 0;
00517     pe.RefListOffset = RefListOffset;
00518 
00519     if(!pDC->WriteData(&pe, sizeof(pe)))
00520         return FALSE;
00521 
00522     return TRUE;
00523 }
00524 
00525 
00526 /********************************************************************************************
00527 
00528 >   BOOL CMXReferDefaultScreen::WriteInDesc(CMXExportDC *pDC)
00529 
00530     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00531     Created:    26/06/96
00532     Inputs:     export dc
00533     Returns:    none
00534     Purpose:    writes the default screen list entry -- same as the default one corel writes
00535     SeeAlso:    
00536 
00537 ********************************************************************************************/
00538 
00539 BOOL CMXReferDefaultScreen::WriteInDesc(CMXExportDC *pDC)
00540 {
00541     if(pDC->IsThirtyTwoBit())
00542     {
00543         cmxScreenDef32 scrdef = {0,0,0,0,0};
00544 
00545         if(!pDC->WriteTag(cmxTAG_DescrSection_Screen_Basic, &scrdef, sizeof(scrdef))
00546             || !pDC->WriteMinEndTag())
00547             return FALSE;
00548     }
00549     else
00550     {
00551         cmxScreenDef16 scrdef = {0,0,0,0};
00552 
00553         if(!pDC->WriteData(&scrdef, sizeof(scrdef)))
00554             return FALSE;
00555     }
00556 
00557     return TRUE;
00558 }
00559 
00560 
00561 /********************************************************************************************
00562 
00563 >   BOOL CMXReferDefaultDotDash::WriteInDesc(CMXExportDC *pDC)
00564 
00565     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00566     Created:    26/06/96
00567     Inputs:     export dc
00568     Returns:    none
00569     Purpose:    writes the default dot dash list entry
00570     SeeAlso:    
00571 
00572 ********************************************************************************************/
00573 
00574 BOOL CMXReferDefaultDotDash::WriteInDesc(CMXExportDC *pDC)
00575 {
00576     WORD DotCount = 0;
00577 
00578     if(!pDC->WriteTag(cmxTAG_DescrSection_Dash, &DotCount, sizeof(DotCount))
00579         || !pDC->WriteMinEndTag())
00580         return FALSE;
00581 
00582     return TRUE;
00583 }
00584 
00585 
00586 /********************************************************************************************
00587 
00588 >   BOOL CMXReferColour::WriteInDesc(CMXExportDC *pDC)
00589 
00590     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00591     Created:    26/06/96
00592     Inputs:     export dc
00593     Returns:    none
00594     Purpose:    writes the colour to the DC in a description list
00595     SeeAlso:    
00596 
00597 ********************************************************************************************/
00598 
00599 BOOL CMXReferColour::WriteInDesc(CMXExportDC *pDC)
00600 {
00601     ColourModel OutputModel;
00602     struct {
00603         BYTE ColType;
00604         BYTE Palette;
00605     } ColH;
00606     ColH.Palette = 5;       // user palette
00607 
00608     // Work out which CMX colour type we will export as, and therefore which internal
00609     // colour model we should convert the colour to.
00610     switch (Colour.GetColourModel())
00611     {
00612         case COLOURMODEL_HSVT:
00613             OutputModel = COLOURMODEL_HSVT;
00614             ColH.ColType = cmxCOLMODEL_HSB;
00615             break;
00616 
00617         case COLOURMODEL_CMYK:
00618             OutputModel = COLOURMODEL_CMYK;
00619             ColH.ColType = cmxCOLMODEL_CMYK255;
00620             break;
00621 
00622         case COLOURMODEL_GREYT:
00623             OutputModel = COLOURMODEL_GREYT;
00624             ColH.ColType = cmxCOLMODEL_GREY;
00625             break;
00626         
00627         case COLOURMODEL_RGBT:
00628         default:
00629             // It's RGB, or we don't know the model, so we'll output it as RGB
00630             OutputModel = COLOURMODEL_RGBT;
00631             ColH.ColType = cmxCOLMODEL_RGB;
00632             break;
00633     }
00634 
00635     // write the header tag
00636     if(!pDC->WriteTag(cmxTAG_DescrSection_Color_Base, &ColH, sizeof(ColH)))
00637         return FALSE;
00638 
00639     // Find an appropriate colour context to convert the colour for output
00640     ColourContext *OutputCC = ColourManager::GetColourContext(OutputModel);
00641     ERROR3IF(OutputCC == NULL, "Can't find a colour context");
00642 
00643     // Convert the colour into a packed format
00644     ColourPacked Result;
00645     OutputCC->ConvertColour(&Colour, &Result);
00646 
00647     // start the tag
00648     if(!pDC->StartTag(cmxTAG_DescrSection_Color_ColorDescr))
00649         return FALSE;
00650 
00651     // Pull the converted colour out and export it to the CMX file
00652     switch (OutputModel)
00653     {
00654         case COLOURMODEL_HSVT:
00655             {
00656 /*TRACEUSER( "Ben", _T("HSV colour: hue %d, sat %d, val %d\n"), Result.HSVT.Hue, Result.HSVT.Saturation, Result.HSVT.Value);
00657             WORD Hue = Result.HSVT.Hue;
00658             pDC->WriteData(&Hue, sizeof(Hue));
00659             pDC->WriteByte(Result.HSVT.Saturation);
00660             pDC->WriteByte(Result.HSVT.Value); */
00661 
00662                 // BODGE because the colour system can't convert HSVT properly yet
00663             ColourHSVT GResult;
00664             OutputCC->ConvertColour(&Colour, (ColourGeneric *)&GResult);
00665 
00666             WORD Hue = (WORD)(360.0 * GResult.Hue.MakeDouble());
00667             pDC->WriteData(&Hue, sizeof(Hue));
00668             pDC->WriteByte((BYTE)(255.0 * GResult.Saturation.MakeDouble()));
00669             pDC->WriteByte((BYTE)(255.0 * GResult.Value.MakeDouble()));
00670             }
00671             break;
00672 
00673         case COLOURMODEL_CMYK:
00674 TRACEUSER( "Ben", _T("CMYK colour: cyan %d mag %d yel %d key %d\n"), Result.CMYK.Cyan, Result.CMYK.Magenta, Result.CMYK.Yellow, Result.CMYK.Key);
00675             pDC->WriteByte(Result.CMYK.Cyan);
00676             pDC->WriteByte(Result.CMYK.Magenta);
00677             pDC->WriteByte(Result.CMYK.Yellow);
00678             pDC->WriteByte(Result.CMYK.Key);
00679             break;
00680 
00681         case COLOURMODEL_GREYT:
00682 TRACEUSER( "Ben", _T("grey colour: grey %d\n"), Result.GreyT.Intensity);
00683             pDC->WriteByte(Result.GreyT.Intensity);
00684             break;
00685 
00686         case COLOURMODEL_RGBT:
00687         default:
00688 TRACEUSER( "Ben", _T("RGB colour: red %d green %d blue %d\n"), Result.RGBT.Red, Result.RGBT.Green, Result.RGBT.Blue);
00689             pDC->WriteByte(Result.RGBT.Red);
00690             pDC->WriteByte(Result.RGBT.Green);
00691             pDC->WriteByte(Result.RGBT.Blue);
00692             break;
00693     }
00694 
00695     // end the tag
00696     if(!pDC->EndTag())
00697         return FALSE;
00698 
00699     // write the end tag
00700     if(!pDC->WriteMinEndTag())
00701         return FALSE;
00702 
00703     return TRUE;
00704 }
00705 
00706 
00707 /********************************************************************************************
00708 
00709 >   BOOL CMXReferMasterIndex::WriteInIndex(CMXExportDC *pDC)
00710 
00711     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00712     Created:    26/06/96
00713     Inputs:     export dc
00714     Returns:    none
00715     Purpose:    writes the index details in the master index
00716     SeeAlso:    
00717 
00718 ********************************************************************************************/
00719 
00720 BOOL CMXReferMasterIndex::WriteInIndex(CMXExportDC *pDC)
00721 {
00722     // write the entry
00723     cmxMasterIndexEntry me;
00724 
00725     me.Type = Type;
00726     me.Offset = Offset;
00727 
00728 TRACEUSER( "Ben", _T("Writing entry in master index, type = %d, offset = %x = %d, size = %d\n"), Type, Offset, Offset, sizeof(me));
00729 
00730     if(!pDC->WriteData(&me, sizeof(me)))
00731         return FALSE;
00732 
00733     return TRUE;
00734 }
00735 
00736 
00737 /********************************************************************************************
00738 
00739 >   BOOL CMXReferMasterIndex::WriteInIndex(CMXExportDC *pDC)
00740 
00741     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00742     Created:    26/06/96
00743     Inputs:     export dc
00744     Returns:    none
00745     Purpose:    writes the index details in the master index
00746     SeeAlso:    
00747 
00748 ********************************************************************************************/
00749 
00750 BOOL CMXReferMasterLayer::WriteInIndex(CMXExportDC *pDC)
00751 {
00752     // write the entry
00753     if(pDC->IsThirtyTwoBit())
00754     {
00755         cmxMasterLayerEntry32 le;       // note that this is the entire table, not an entry
00756 
00757         le.TableType = cmxMASTERIN_MASTERLAYER;     // quite why we need this is another matter
00758         le.SizeInFile = sizeof(DWORD);
00759         le.ID = 1;                  // first page, I presume
00760         le.Offset = Offset;         // offset...
00761 
00762         if(!pDC->WriteData(&le, sizeof(le)))
00763             return FALSE;
00764     }
00765     else
00766     {
00767         cmxMasterLayerEntry16 le;       // note that this is the entire table, not an entry
00768 
00769         le.TableType = cmxMASTERIN_MASTERLAYER;     // quite why we need this is another matter
00770         le.ID = 1;                  // first page, I presume
00771         le.Offset = Offset;         // offset...
00772 
00773         if(!pDC->WriteData(&le, sizeof(le)))
00774             return FALSE;
00775     }
00776 
00777     return TRUE;
00778 }
00779 
00780 
00781 /********************************************************************************************
00782 
00783 >   CMXExportDC::CMXExportDC(Filter *Parent)
00784 
00785     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00786     Created:    18/6/96
00787     Inputs:     The filter object associated with this export DC.
00788     Purpose:    Initialise a DC for exporting EPS.
00789 
00790 ********************************************************************************************/
00791 
00792 CMXExportDC::CMXExportDC(Filter *Parent) : ExportDC(Parent)
00793 {
00794 }
00795 
00796 
00797 
00798 /********************************************************************************************
00799 
00800 >   BOOL CMXExportDC::Init(CCLexFile* pFile, CMXRenderRegion *pReg, BOOL bThirtyTwoBit)
00801 
00802     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00803     Created:    18/6/96
00804     Inputs:     pFile - The file to attach to the DC
00805     Returns:    TRUE if all went well, FALSE if not
00806     Purpose:    Calls the base class Init function and then sets up the DC to throw exceptions
00807                 when it gets errors as that is how the EPS stuff expects errors to be reported.
00808     SeeAlso:    ExportDC::Init
00809 
00810 ********************************************************************************************/
00811 
00812 BOOL CMXExportDC::Init(CCLexFile* pFile, CMXRenderRegion *pReg, BOOL bThirtyTwoBit, BOOL ClipboardExport)
00813 {
00814     // First get the base class to do its thing
00815     if (!ExportDC::Init(pFile)) return FALSE;
00816 
00817     // now do what I want done.
00818     // We want export files to throw exceptions, and not report errors.
00819     ExportFile->SetThrowExceptions(TRUE);
00820     ExportFile->SetReportErrors(FALSE);
00821 
00822     // set the bitness of the file
00823     ThirtyTwoBit = bThirtyTwoBit;
00824 
00825     // mark the fact that we've not actually doing a section at all
00826     CurrentSection = CMXSECTION_NONE;
00827 
00828     // set up a few more variables
00829     DoingCommand = FALSE;
00830     DoingPage = FALSE;
00831     DoingLayer = FALSE;
00832     PageRefer = NULL;
00833     DoingTag = FALSE;
00834     pMatrix = NULL;
00835     NestedTagLevel = 0;
00836     CurrentInstrFilePosition = -1;
00837     pRenderRegion = pReg;
00838     DoingRIFFList = FALSE;
00839     NumberOfEntriesUsedInCache = 0;
00840 
00841     // overlapped lenses flag
00842     if(!ClipboardExport)
00843     {
00844         // normal ask the user mode
00845         AreIgnoreingOverlappedLenses = FALSE;
00846         OverlappedLensesHaveBeenIgnored = FALSE;
00847         HaveAskedUserAboutLenses = FALSE;
00848     }
00849     else
00850     {
00851         // don't ask the user
00852         AreIgnoreingOverlappedLenses = TRUE;
00853         OverlappedLensesHaveBeenIgnored = FALSE;
00854         HaveAskedUserAboutLenses = TRUE;
00855     }
00856 
00857     for(INT32 i = 0 ; i < CMXFUTUREVALUECACHESIZE ; i++)
00858     {
00859         //  init the write-cache 
00860         FutureDataCache[i].Location = INT32_MAX;
00861         FutureDataCache[i].Data     = 0;
00862         FutureDataCache[i].DataSize = 0;
00863     }
00864 
00865     // pop in the default screen thingy
00866     CMXReferDefaultScreen *pDefScreen = new CMXReferDefaultScreen(this);
00867     if(pDefScreen == NULL) return FALSE;
00868 
00869     // and add it to the list
00870     ReferList.AddTail(pDefScreen);
00871 
00872     // pop in the default dot dash thingy
00873     CMXReferDefaultDotDash *pDefdd = new CMXReferDefaultDotDash(this);
00874     if(pDefdd == NULL) return FALSE;
00875 
00876     // and add it to the list
00877     ReferList.AddTail(pDefdd);
00878     return TRUE;
00879 }
00880 
00881 /********************************************************************************************
00882 
00883 >   void CMXExportDC::CleanUp(void)
00884 
00885     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00886     Created:    26/06/96
00887     Inputs:     none
00888     Returns:    none
00889     Purpose:    Cleans up after writing to a file
00890     SeeAlso:    
00891 
00892 ********************************************************************************************/
00893 
00894 void CMXExportDC::CleanUp(void)
00895 {
00896     WriteFutureDataCache();
00897     ReferList.DeleteAll();
00898     LensBBoxes.DeleteAll();
00899 }
00900 
00901 
00902 /********************************************************************************************
00903 
00904 >   BOOL CMXExportDC::StartSection(CMXSectionType Type)
00905 
00906     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00907     Created:    18/6/96
00908     Inputs:     The type of section to start
00909     Returns:    success
00910     Purpose:    Start writing a section to a CMX file
00911     SeeAlso:    
00912 
00913 ********************************************************************************************/
00914 
00915 BOOL CMXExportDC::StartSection(CMXSectionType Type)
00916 {
00917     ERROR2IF(CurrentSection != CMXSECTION_NONE, FALSE, "Tried to start a section without ending the previous one");
00918 
00919     // write the riff file header
00920     // first, decide what riff chunck id we want
00921     DWORD id;
00922     BOOL IsAList = FALSE;           // whether in fact it's a list
00923     switch(Type)
00924     {
00925     case CMXSECTION_NONE:
00926         ERROR2(FALSE, "Tried to start a section of type none. Oh dear");
00927         break;
00928     case CMXSECTION_HEADER:     id = cmxRIFFCI_Header;          break;
00929     case CMXSECTION_PAGE:       id = cmxRIFFCI_Page;            break;
00930     case CMXSECTION_REFLIST:    id = cmxRIFFCI_ReferenceList;   break;
00931     case CMXSECTION_INDEX:      id = cmxRIFFLIST_Index; IsAList=TRUE;   break;
00932     case CMXSECTION_TRAILER:    id = cmxRIFFLIST_Trail; IsAList=TRUE;   break;
00933     case CMXSECTION_ARROW:      id = cmxRIFFCI_Desc_Arrow;      break;
00934     case CMXSECTION_ARROWHEADS: id = cmxRIFFCI_Desc_Arrowheads; break;
00935     case CMXSECTION_COLOUR:     id = cmxRIFFCI_Desc_Colour;     break;
00936     case CMXSECTION_DOTDASH:    id = cmxRIFFCI_Desc_DotDash;    break;
00937     case CMXSECTION_FONT:       id = cmxRIFFCI_Desc_Font;       break;
00938     case CMXSECTION_OUTLINE:    id = cmxRIFFCI_Desc_Outline;    break;
00939     case CMXSECTION_LINESTYLE:  id = cmxRIFFCI_Desc_LineStyle;  break;
00940     case CMXSECTION_PEN:        id = cmxRIFFCI_Desc_Pen;        break;
00941     case CMXSECTION_LENS:       id = cmxRIFFCI_Desc_Lens;       break;
00942     case CMXSECTION_SCREEN:     id = cmxRIFFCI_Desc_Screen;     break;
00943     case CMXSECTION_IMAGINFO:   id = cmxRIFFCI_ImageInfo;       break;
00944     case CMXSECTION_IMAGDATA:   id = cmxRIFFCI_ImageData;       break;
00945     case CMXSECTION_PROCBITFILL:id = cmxRIFFCI_Procedure;       break;
00946     case CMXSECTION_PREVIEWBITMAP: id = cmxRIFFCI_Thumbnail;    break;
00947     default:
00948         ERROR2(FALSE, "Unknown section type");
00949         break;
00950     }
00951 
00952     // OK, write the RIFF header
00953     RIFFck chdr;
00954     chdr.ckID = IsAList?RIFFTYPE_LIST:id;
00955     chdr.ckSize = 0;
00956     ExportFile->write(&chdr, sizeof(chdr));
00957 
00958     // set the future length
00959     SectionLengthFuture.Init(this, FUTURE_BACKLOC(&chdr, ckSize), sizeof(chdr.ckSize));
00960     SectionLengthFuture.SetLengthStartPos(this, 0 /* - (INT32)sizeof(chdr)*/);
00961 
00962     // write the list type, if we're doing a list
00963     if(IsAList)
00964         ExportFile->write(&id, sizeof(id));
00965 
00966     // note which section type we just did
00967     CurrentSection = Type;
00968     
00969     return TRUE;
00970 }
00971 
00972 
00973 /********************************************************************************************
00974 
00975 >   BOOL CMXExportDC::EndSection(void)
00976 
00977     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00978     Created:    24/06/96
00979     Inputs:     none
00980     Returns:    success
00981     Purpose:    Finish off writing a section to a CMX file
00982     SeeAlso:    
00983 
00984 ********************************************************************************************/
00985 
00986 BOOL CMXExportDC::EndSection(void)
00987 {
00988     ERROR2IF(CurrentSection == CMXSECTION_NONE, FALSE, "Tried to end a section which didn't exist");
00989 
00990     // write the length
00991     SectionLengthFuture.Write(this);
00992 
00993     // set the section type to none
00994     CurrentSection = CMXSECTION_NONE;
00995 
00996     // word align the file
00997     if((GetFilePosition() & 1) != 0)
00998     {
00999         // put an extra byte in the file
01000         ExportFile->put('\0');
01001     }
01002 
01003     return TRUE;
01004 }
01005 
01006 
01007 /********************************************************************************************
01008 
01009 >   BOOL CMXExportDC::StartRIFFList(INT32 Type)
01010 
01011     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01012     Created:    16/07/96
01013     Inputs:     The type of section to start
01014     Returns:    success
01015     Purpose:    Start writing a section to a CMX file
01016     SeeAlso:    
01017 
01018 ********************************************************************************************/
01019 
01020 BOOL CMXExportDC::StartRIFFList(INT32 Type)
01021 {
01022     ERROR2IF(DoingRIFFList, FALSE, "Tried to start a riff list without ending the previous one");
01023 
01024     // write the riff list header
01025     RIFFck chdr;
01026     chdr.ckID = RIFFTYPE_LIST;
01027     chdr.ckSize = 0;
01028     ExportFile->write(&chdr, sizeof(chdr));
01029 
01030     // set the future length
01031     RIFFListLengthFuture.Init(this, FUTURE_BACKLOC(&chdr, ckSize), sizeof(chdr.ckSize));
01032     RIFFListLengthFuture.SetLengthStartPos(this, 0);
01033 
01034     // write the list type, if we're doing a list
01035     DWORD id = Type;
01036     ExportFile->write(&id, sizeof(id));
01037 
01038     // flag...
01039     DoingRIFFList = TRUE;
01040     
01041     return TRUE;
01042 }
01043 
01044 
01045 /********************************************************************************************
01046 
01047 >   BOOL CMXExportDC::EndRIFFList(void)
01048 
01049     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01050     Created:    16/07/96
01051     Inputs:     none
01052     Returns:    success
01053     Purpose:    Finish off writing a section to a CMX file
01054     SeeAlso:    
01055 
01056 ********************************************************************************************/
01057 
01058 BOOL CMXExportDC::EndRIFFList(void)
01059 {
01060     ERROR2IF(!DoingRIFFList, FALSE, "Tried to end a riff list which didn't exist");
01061 
01062     // write the length
01063     RIFFListLengthFuture.Write(this);
01064 
01065     // word align the file
01066     if((GetFilePosition() & 1) != 0)
01067     {
01068         // put an extra byte in the file
01069         ExportFile->put('\0');
01070     }
01071 
01072     // flag
01073     DoingRIFFList = FALSE;
01074 
01075     return TRUE;
01076 }
01077 
01078 
01079 /********************************************************************************************
01080 
01081 >   BOOL CMXExportDC::StartTag(INT32 Tag)
01082 
01083     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01084     Created:    27/06/96
01085     Inputs:     Tag for the command
01086     Returns:    success
01087     Purpose:    starts writing a tag to the file
01088     SeeAlso:    
01089 
01090 ********************************************************************************************/
01091 
01092 BOOL CMXExportDC::StartTag(INT32 Tag)
01093 {
01094     if(!ThirtyTwoBit)
01095         return TRUE;        // 16 bit files don't have tags
01096 
01097     ERROR2IF(DoingTag == TRUE, FALSE, "already doing a tag");
01098 
01099     // write the tag header
01100     cmxTagHdr hdr;
01101     hdr.ID = (BYTE)Tag;
01102     hdr.Size = 0;
01103     ExportFile->write(&hdr, sizeof(hdr));
01104 
01105     // initialise the future value
01106     TagLengthFuture.Init(this, FUTURE_BACKLOC(&hdr, Size), sizeof(hdr.Size));
01107     TagLengthFuture.SetLengthStartPos(this, 0-(INT32)sizeof(hdr));
01108 
01109     // flag
01110     DoingTag = TRUE;
01111 
01112     return TRUE;
01113 }
01114 
01115     
01116 /********************************************************************************************
01117 
01118 >   BOOL CMXExportDC::EndTag(void)
01119 
01120     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01121     Created:    27/06/96
01122     Inputs:     none
01123     Returns:    success
01124     Purpose:    ends a tag
01125     SeeAlso:    
01126 
01127 ********************************************************************************************/
01128 
01129 BOOL CMXExportDC::EndTag(void)
01130 {
01131     if(!ThirtyTwoBit)
01132         return TRUE;        // 16 bit files don't have tags
01133 
01134     ERROR2IF(DoingTag == FALSE, FALSE, "not doing a tag");
01135     ERROR2IF(NestedTagLevel != 0, FALSE, "tried to end a main tag when nested tags are active");
01136 
01137     // write the length
01138     TagLengthFuture.Write(this);
01139 
01140     // flag
01141     DoingTag = FALSE;
01142 
01143     return TRUE;
01144 }
01145 
01146 
01147 /********************************************************************************************
01148 
01149 >   BOOL CMXExportDC::StartNestedTag(INT32 Tag)
01150 
01151     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01152     Created:    27/06/96
01153     Inputs:     Tag for the command
01154     Returns:    success
01155     Purpose:    starts writing a nested tag to the file
01156     SeeAlso:    
01157 
01158 ********************************************************************************************/
01159 
01160 BOOL CMXExportDC::StartNestedTag(INT32 Tag)
01161 {
01162     if(!ThirtyTwoBit)
01163         return TRUE;        // 16 bit files don't have tags
01164 
01165     ERROR2IF(DoingTag == FALSE, FALSE, "tried to start a nested tag outside a tag");
01166 
01167     // write the tag header
01168     cmxTagHdr hdr;
01169     hdr.ID = (BYTE)Tag;
01170     hdr.Size = 0;
01171     ExportFile->write(&hdr, sizeof(hdr));
01172 
01173     // get one of those nested tag record things
01174     CMXNestedTagRecord *pRec = new CMXNestedTagRecord;
01175     if(pRec == NULL)
01176         return FALSE;
01177 
01178     // initialise the future value
01179     pRec->LengthFuture.Init(this, FUTURE_BACKLOC(&hdr, Size), sizeof(hdr.Size));
01180     pRec->LengthFuture.SetLengthStartPos(this, 0-(INT32)sizeof(hdr));
01181 
01182     // add the record to the list
01183     NestedTagList.AddTail(pRec);
01184 
01185     // flag
01186     NestedTagLevel++;
01187 
01188     return TRUE;
01189 }
01190 
01191     
01192 /********************************************************************************************
01193 
01194 >   BOOL CMXExportDC::EndNestedTag(void)
01195 
01196     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01197     Created:    04/07/96
01198     Inputs:     none
01199     Returns:    success
01200     Purpose:    ends a nested tag
01201     SeeAlso:    
01202 
01203 ********************************************************************************************/
01204 
01205 BOOL CMXExportDC::EndNestedTag(void)
01206 {
01207     if(!ThirtyTwoBit)
01208         return TRUE;        // 16 bit files don't have tags
01209 
01210     ERROR2IF(DoingTag == FALSE, FALSE, "not doing a tag");
01211     ERROR2IF(NestedTagLevel <= 0, FALSE, "not doing a nested tag");
01212 
01213     // get the last tag record
01214     CMXNestedTagRecord *pRec = (CMXNestedTagRecord *)NestedTagList.GetTail();
01215 
01216     // check it's OK
01217     ERROR2IF(!IS_A(pRec, CMXNestedTagRecord), FALSE, "tag record not a tag record");
01218 
01219     // write the length
01220     pRec->LengthFuture.Write(this);
01221 
01222     // delete the record
01223     delete NestedTagList.RemoveTail();
01224 
01225     // flag
01226     NestedTagLevel--;
01227 
01228     return TRUE;
01229 }
01230 
01231 
01232 /********************************************************************************************
01233 
01234 >   BOOL CMXExportDC::DoWriteTag(INT32 Tag, void *Data = 0, UINT32 Size = 0, BOOL Nested = FALSE)
01235 
01236     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01237     Created:    27/06/96
01238     Inputs:     none
01239     Returns:    success
01240     Purpose:    writes a tag in one go
01241     SeeAlso:    
01242 
01243 ********************************************************************************************/
01244 
01245 BOOL CMXExportDC::DoWriteTag(INT32 Tag, void *Data, UINT32 Size, BOOL Nested)
01246 {
01247     if(!Nested)
01248     {
01249         ERROR2IF(DoingTag == TRUE, FALSE, "already doing a tag");
01250     }
01251 
01252     // if we're not doing a 32 bit file, we just want to export the data
01253     if(ThirtyTwoBit)
01254     {
01255         // write the tag header
01256         cmxTagHdr hdr;
01257         hdr.ID = (BYTE)Tag;
01258         hdr.Size = sizeof(hdr)+Size;
01259         ExportFile->write(&hdr, sizeof(hdr));
01260     }
01261 
01262     // write the data, if required
01263     if(Size != 0)
01264         ExportFile->write(Data, Size);
01265 
01266     return TRUE;
01267 }
01268 
01269 
01270 /********************************************************************************************
01271 
01272 >   BOOL CMXExportDC::WriteCommand(UINT32 Tag, void *Data, UINT32 Size)
01273 
01274     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01275     Created:    18/6/96
01276     Inputs:     Tag for the command, the data, and the size
01277     Returns:    success
01278     Purpose:    Write a command to the file -- one off operation, writes command
01279                 and data in one go. Use default params for a no-data command.
01280     SeeAlso:    
01281 
01282 ********************************************************************************************/
01283 
01284 BOOL CMXExportDC::WriteCommand(UINT32 Tag, void *Data, UINT32 Size)
01285 {
01286     ERROR2IF(DoingCommand != FALSE, FALSE, "Already writing a command");
01287     
01288     // write the header
01289     cmxInstrHdr hdr = {Size + sizeof(hdr), ThirtyTwoBit?Tag:(0 - (SWORD)Tag)};
01290 
01291     // word align the size
01292     if((hdr.Size & 1) != 0)
01293         hdr.Size++;
01294 
01295     ExportFile->write(&hdr, sizeof(hdr));
01296 
01297     if(Size != 0)
01298     {
01299         ERROR2IF(Data == 0, FALSE, "didn't get some data");
01300 
01301         // write the command
01302         ExportFile->write(Data, Size);
01303     }
01304 
01305     Tally++;
01306     PageInstructionCount++;
01307     LayerInstructionCount++;
01308 
01309     // word align the file
01310     if((/*GetFilePosition()*/ Size & 1) != 0)
01311     {
01312         // put an extra byte in the file
01313         ExportFile->put('\0');
01314     }
01315 
01316     return TRUE;
01317 }
01318 
01319 
01320 /********************************************************************************************
01321 
01322 >   BOOL CMXExportDC::StartCommand(UINT32 Tag)
01323 
01324     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01325     Created:    21/06/96
01326     Inputs:     none
01327     Returns:    success
01328     Purpose:    starts writing a command for a command where the data is of indetermant
01329                 size. Use EndCommand to finish it off
01330     SeeAlso:    WriteCommand -- use for one off commands
01331 
01332 ********************************************************************************************/
01333 
01334 BOOL CMXExportDC::StartCommand(UINT32 Tag)
01335 {
01336     ERROR2IF(DoingCommand != FALSE, FALSE, "Already writing a command");
01337 
01338     // record the start of the file
01339     CurrentInstrFilePosition = GetFilePosition();
01340 
01341     // write the header
01342     cmxInstrHdr hdr = {0, ThirtyTwoBit?Tag:(0 - (SWORD)Tag)};
01343     ExportFile->write(&hdr, sizeof(hdr));
01344 
01345     Tally++;
01346     PageInstructionCount++;
01347     LayerInstructionCount++;
01348 
01349     // set the future length
01350     CommandLengthFuture.Init(this, FUTURE_BACKLOC(&hdr, Size), sizeof(hdr.Size));
01351     CommandLengthFuture.SetLengthStartPos(this, 0 - (INT32)sizeof(hdr));
01352 
01353     // set whether we're doing a command
01354     DoingCommand = TRUE;
01355 
01356     return TRUE;
01357 }
01358 
01359 
01360 /********************************************************************************************
01361 
01362 >   BOOL CMXExportDC::EndCommand(void)
01363 
01364     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01365     Created:    21/06/96
01366     Inputs:     none
01367     Returns:    success
01368     Purpose:    ends a command
01369     SeeAlso:    
01370 
01371 ********************************************************************************************/
01372 
01373 BOOL CMXExportDC::EndCommand(void)
01374 {
01375     ERROR2IF(DoingCommand != TRUE, FALSE, "Already writing a command");
01376 
01377     // word align the file
01378     if((GetFilePosition() & 1) != 0)
01379     {
01380         // put an extra byte in the file
01381         ExportFile->put('\0');
01382     }
01383 
01384     CommandLengthFuture.Write(this);
01385 
01386     DoingCommand = FALSE;
01387 
01388     CurrentInstrFilePosition = -1;
01389 
01390     return TRUE;
01391 }
01392 
01393 
01394 /********************************************************************************************
01395 
01396 >   BOOL CMXExportDC::CreateHeader(DocRect *pFileBBox)
01397 
01398     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01399     Created:    21/06/96
01400     Inputs:     bounding box of file
01401     Returns:    success
01402     Purpose:    Write the file's header, and name notes of the location of things
01403                 like the relevant sizes and indices and other stuff which can only
01404                 be written after the export.
01405 
01406                 This fn is called Create rather than Write because it's not finished
01407                 off properly until the end of the file.
01408     SeeAlso:    
01409 
01410 ********************************************************************************************/
01411 
01412 BOOL CMXExportDC::CreateHeader(DocRect *pFileBBox)
01413 {
01414     ERROR2IF(pMatrix == NULL, FALSE, "No matrix yet");
01415 
01416     // first of all, think about the riff file header
01417     RIFFFile_Header rhdr;
01418     rhdr.CK.ckID = RIFFTYPE_RIFF;
01419     rhdr.CK.ckSize = 0;
01420     rhdr.FormType = cmxRIFFFORMTYPE_CMX;
01421 
01422     ExportFile->write(&rhdr, sizeof(rhdr));
01423 
01424     // set up the future length object
01425     FileLengthFuture.Init(this, FUTURE_BACKLOC(&rhdr, CK.ckSize), sizeof(rhdr.CK.ckSize));
01426     FileLengthFuture.SetLengthStartPos(this, /*-((INT32)sizeof(rhdr))*/ -(INT32)sizeof(DWORD));
01427 
01428     // start the CMX header section
01429     if(!StartSection(CMXSECTION_HEADER))
01430         return FALSE;
01431 
01432     // write the CMX header
01433     cmxHeader fhdr;
01434     memset(&fhdr, 0, sizeof(fhdr));         // set everything to zero
01435     camStrcpy((char *)fhdr.Id, cmxID);
01436     camStrcpy((char *)fhdr.OS, cmxOS);
01437     fhdr.ByteOrder = cmxBYTEORDER_INTEL | 0x30;
01438     if(ThirtyTwoBit)
01439     {
01440         fhdr.CoordSize = cmxCOORDSIZE_32 | 0x30;
01441         fhdr.Major = cmxMAJOR_32 | 0x30;
01442         fhdr.Factor = cmxFACTOR_32;
01443         fhdr.Unit = cmxUNIT_MILLIMETER;
01444     }
01445     else
01446     {
01447         fhdr.CoordSize = cmxCOORDSIZE_16 | 0x30;
01448         fhdr.Major = cmxMAJOR_16 | 0x30;
01449         fhdr.Factor = cmxFACTOR_16;
01450         fhdr.Unit = cmxUNIT_INCH;
01451     }
01452     fhdr.Minor = cmxMINOR | 0x30;
01453 
01454     // bounding box
01455     DocRect bb = *pFileBBox;
01456     pMatrix->TransformBounds(&bb);
01457 
01458     fhdr.IBBLeft    = bb.lo.x;
01459     fhdr.IBBTop     = bb.hi.y;
01460     fhdr.IBBRight   = bb.hi.x;
01461     fhdr.IBBBottom  = bb.lo.y;
01462     fhdr.IThumbnail = -1;
01463 
01464     ExportFile->write(&fhdr, sizeof(fhdr));
01465 
01466     // set up it's future value objects
01467     Tally.Init(this, FUTURE_BACKLOC(&fhdr, ITally), sizeof(fhdr.ITally));
01468     Tally = 0;
01469     IndexSectionFuture.Init(this, FUTURE_BACKLOC(&fhdr, IIndexSection), sizeof(fhdr.IIndexSection));
01470     TrailerIndexFuture.Init(this, FUTURE_BACKLOC(&fhdr, IInfoSection), sizeof(fhdr.IInfoSection));
01471     ThumbnailIndexFuture.Init(this, FUTURE_BACKLOC(&fhdr, IThumbnail), sizeof(fhdr.IThumbnail));
01472 
01473     // end the CMX header section
01474     if(!EndSection())
01475         return FALSE;
01476 
01477     return TRUE;
01478 }
01479 
01480 
01481 /********************************************************************************************
01482 
01483 >   BOOL CMXExportDC::PolishOffThatFile()
01484 
01485     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01486     Created:    21/06/96
01487     Inputs:     none
01488     Returns:    success
01489     Purpose:    Finish off the file, update indexes and all that
01490     SeeAlso:    
01491 
01492 ********************************************************************************************/
01493 
01494 BOOL CMXExportDC::PolishOffThatFile()
01495 {
01496     ERROR2IF(CurrentSection != CMXSECTION_NONE, FALSE, "Didn't end the section before ending the file");
01497 
01498 
01499     // write some future values
01500     if(!Tally.Write(this))
01501         return FALSE;
01502 
01503     // write the info section
01504     if(!TrailerIndexFuture.Write(this))
01505         return FALSE;
01506     if(!StartSection(CMXSECTION_TRAILER))
01507         return FALSE;
01508     if(!EndSection())
01509         return FALSE;
01510 
01511     // and pop the length in
01512     if(!FileLengthFuture.Write(this))
01513         return FALSE;
01514     
01515 
01516     WriteFutureDataCache(); 
01517 
01518 
01519     return TRUE;
01520 }
01521 
01522 /********************************************************************************************
01523 
01524 >   INT32 CMXExportDC::GetFilePosition();
01525 
01526     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01527     Created:    21/06/96
01528     Inputs:     none
01529     Returns:    success
01530     Purpose:    returns the position of the current file pointer in the export file
01531     SeeAlso:    
01532 
01533 ********************************************************************************************/
01534 
01535 INT32 CMXExportDC::GetFilePosition()
01536 {
01537     return ExportFile->tell();
01538 }
01539 
01540 /********************************************************************************************
01541 
01542 >   BOOL CMXExportDC::WriteBBox(DocRect *BBox, BOOL Transform = TRUE)
01543 
01544     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01545     Created:    21/06/96
01546     Inputs:     none
01547     Returns:    success
01548     Purpose:    Write a bounding box to the file
01549     SeeAlso:    
01550 
01551 ********************************************************************************************/
01552 
01553 BOOL CMXExportDC::WriteBBox(DocRect *BBox, BOOL Transform)
01554 {
01555     ERROR2IF(pMatrix == NULL, FALSE, "No matrix");
01556 
01557     if(ThirtyTwoBit)
01558     {
01559         DocRect bb = *BBox;
01560         if(Transform)
01561             pMatrix->TransformBounds(&bb);
01562         
01563         cmxBBox32 b = {bb.lo.x, bb.hi.y, bb.hi.x, bb.lo.y};
01564 
01565         ExportFile->write(&b, sizeof(b));
01566     }
01567     else
01568     {
01569         DocRect bb = *BBox;
01570         if(Transform)
01571             pMatrix->TransformBounds(&bb);
01572         
01573         cmxBBox16 b = {(SWORD)bb.lo.x, (SWORD)bb.hi.y, (SWORD)bb.hi.x, (SWORD)bb.lo.y};
01574 
01575         ExportFile->write(&b, sizeof(b));
01576     }
01577 
01578     return TRUE;
01579 }
01580 
01581 
01582 /********************************************************************************************
01583 
01584 >   void CMXExportDC::WriteAngle(double theta)
01585 
01586     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01587     Created:    10/07/96
01588     Inputs:     angle, in radians
01589     Returns:    -
01590     Purpose:    writes an angle to the file
01591     SeeAlso:    
01592 
01593 ********************************************************************************************/
01594 
01595 void CMXExportDC::WriteAngle ( double theta )
01596 {
01597     // Convert theta to be measured in degrees.
01598     theta = ( theta * 360.0 ) / ( 2.0 * PI );
01599 
01600     // 32-bit export uses a larger scale factor.
01601     if(ThirtyTwoBit)
01602     {
01603         INT32   Angle32 = ( INT32 ) ( theta * 1000000.0 );
01604         ExportFile->write ( &Angle32, sizeof ( Angle32 ) );
01605     }
01606     else
01607     {
01608         short   Angle16 = ( short ) ( theta * 10.0);
01609         ExportFile->write ( &Angle16, sizeof ( Angle16 ) );
01610     }
01611 }
01612 
01613 /********************************************************************************************
01614 
01615 >   BOOL CMXExportDC::WriteString(StringBase *Str)
01616 
01617     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01618     Created:    25/06/96
01619     Inputs:     none
01620     Returns:    success
01621     Purpose:    Write a bounding box to the file
01622     SeeAlso:    
01623 
01624 ********************************************************************************************/
01625 
01626 BOOL CMXExportDC::WriteString(StringBase *Str)
01627 {
01628     INT32 StrLen = Str->Length();
01629 
01630     cmxString h;
01631     h.Length = (WORD)StrLen;
01632     ExportFile->write(&h, sizeof(h));
01633 
01634     ExportFile->write((TCHAR *)(*Str), StrLen);
01635 
01636     return TRUE;
01637 }
01638 
01639 /********************************************************************************************
01640 
01641 >   BOOL CMXExportDC::WriteMatrix(Matrix *pMatrix = NULL)
01642 
01643     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01644     Created:    27/06/96
01645     Inputs:     matrix to write, NULL for identity matrix
01646     Returns:    success
01647     Purpose:    writes a matrix to the file
01648     SeeAlso:    
01649 
01650 ********************************************************************************************/
01651 
01652 BOOL CMXExportDC::WriteMatrix(Matrix *pMatrix)
01653 {
01654     if(pMatrix == NULL)
01655     {
01656         // write an identity matrix
01657         WORD MatrixType = cmxMATRIXTYPE_IDENTITY;
01658         ExportFile->write(&MatrixType, sizeof(MatrixType));
01659     }
01660     else
01661     {
01662         // write the matrix
01663         cmxMatrix Thingy;
01664         FIXED16 abcd[4];
01665         INT32 ef[2];
01666         pMatrix->GetComponents((FIXED16 *)(&abcd), (INT32 *)(&ef));
01667         Thingy.Type = cmxMATRIXTYPE_GENERAL;
01668         Thingy.a = abcd[0].MakeDouble();
01669         Thingy.b = abcd[1].MakeDouble();
01670         Thingy.c = abcd[2].MakeDouble();
01671         Thingy.d = abcd[3].MakeDouble();
01672         Thingy.e = (DOUBLE)ef[0];
01673         Thingy.f = (DOUBLE)ef[1];
01674 
01675         ExportFile->write(&Thingy, sizeof(Thingy));
01676     }
01677 
01678     return TRUE;
01679 }
01680 
01681 /********************************************************************************************
01682 
01683 >   BOOL CMXExportDC::WriteNumber(INT32 Position, UINT32 DataSize, INT32 Value);
01684 
01685     Author:     Claude_Quemerais (Xara Group Ltd) <camelotdev@xara.com>
01686     Created:    21/06/96
01687     Inputs:     none
01688     Returns:    success
01689     Purpose:    Finish off the file, update indexes and all that
01690 
01691                 Fixed by Ben so it doesn't write over the end of the array and
01692                 screw up the other variables in the class and cause nasty AVs in
01693                 retail builds which annoy Charles and take me ages to find.
01694 
01695 ********************************************************************************************/
01696 
01697 BOOL CMXExportDC::WriteNumber(INT32 Position, UINT32 DataSize, INT32 Value)
01698 {
01699 TRACEUSER( "Claude", _T("Writing number %x at %d, size %d\n"), Value, Position, DataSize);
01700 
01701     //  When cache full => Flush it to the file.
01702     if(NumberOfEntriesUsedInCache >= (CMXFUTUREVALUECACHESIZE - 1))
01703         WriteFutureDataCache();
01704 
01705     //  Variable used to find out what entry is to be used
01706     INT32 theEntryInCache = 0;
01707     
01708     //  Search for the right place in the cache, i.e. sort the cache as
01709     //  it's generated
01710     while((theEntryInCache < NumberOfEntriesUsedInCache) && (Position > FutureDataCache[theEntryInCache].Location))
01711         theEntryInCache++;
01712     
01713     TRACEUSER( "Claude", _T("Writing entry %d"), theEntryInCache);
01714     
01715     if(theEntryInCache < NumberOfEntriesUsedInCache)
01716     {   //  If the entry to use is before the last entry already used in the cache
01717         //  Push all entries used from the one we want onward.
01718         
01719         //  Variable used to determine which entry is to be pushed
01720         //  Starting from the end.
01721         
01722         for(INT32 entrySorting = NumberOfEntriesUsedInCache;
01723             entrySorting >= theEntryInCache; entrySorting--)
01724         {
01725             //  Copy the entry onto the next one
01726             FutureDataCache[entrySorting+1] = FutureDataCache[entrySorting];
01727         }
01728     }
01729     
01730     //  Copy the information into the cache
01731     FutureDataCache[theEntryInCache].Location   =   Position;
01732     FutureDataCache[theEntryInCache].Data       =   Value;
01733     FutureDataCache[theEntryInCache].DataSize   =   DataSize;
01734     
01735     TRACEUSER( "Claude", _T("Writing number %x at %d, size %d\n"),
01736                     FutureDataCache[theEntryInCache].Data,
01737                     FutureDataCache[theEntryInCache].Location, 
01738                     FutureDataCache[theEntryInCache].DataSize);
01739     //  Put the entry to use on the next one.
01740     NumberOfEntriesUsedInCache++;
01741     
01742     return TRUE;
01743 }
01744 
01745 /*******************************************************************************************
01746 
01747 >   BOOL CMXExportDC::WriteFutureDataCache()
01748 
01749     Author:     Claude_Quemerais (Xara Group Ltd) <camelotdev@xara.com>
01750     Created:    15/07/96
01751     Inputs:     none
01752     Returns:    Success
01753     Purpose:    Write the Numbers from the cache to the file
01754     See also:
01755 
01756 *******************************************************************************************/
01757 
01758 BOOL CMXExportDC::WriteFutureDataCache()
01759 {
01760     //  Find out the current position in the file
01761     INT32 here = ExportFile->tell();
01762 
01763     for(INT32 i = 0 ; i < NumberOfEntriesUsedInCache ; i++)
01764     {   // write the numbers to file
01765         
01766         TRACEUSER( "Claude", _T("Writing cache %x at %d, size %d\n"),
01767                         FutureDataCache[i].Data,
01768                         FutureDataCache[i].Location, 
01769                         FutureDataCache[i].DataSize);
01770 
01771         //  Get the location where to put the info in the file
01772         ExportFile->seek(FutureDataCache[i].Location);
01773         
01774         if(FutureDataCache[i].DataSize != 0)
01775         {   //  If there is something flush it (there should always be something)
01776             
01777             switch(FutureDataCache[i].DataSize)
01778             {
01779                 case sizeof(BYTE):
01780                 {   //  If it's a BYTE, write a BYTE
01781                     BYTE Num = (BYTE)FutureDataCache[i].Data;
01782                     ExportFile->write(&Num, sizeof(Num));
01783                 }
01784                 break;
01785         
01786                 case sizeof(WORD):
01787                 {   //  If it's a WORD, write a WORD
01788                     WORD Num = (WORD)FutureDataCache[i].Data;
01789                     ExportFile->write(&Num, sizeof(Num));
01790                 }
01791                 break;
01792 
01793                 case sizeof(INT32):
01794                 {   //  If it's a INT32, write a INT32
01795                     INT32 Num = FutureDataCache[i].Data;
01796                     ExportFile->write(&Num, sizeof(Num));
01797                 }
01798                 break;
01799     
01800                 default:
01801                     //  If it's anything else, something went wrong
01802                     ERROR3("OOOKK! Non supported data size");
01803                 break;
01804             }
01805             //  Empty that entry of the cache, putting the Location to the maximum possible
01806             FutureDataCache[i].Location =   INT32_MAX;
01807             FutureDataCache[i].Data     =   0;
01808             FutureDataCache[i].DataSize =   0;
01809         }
01810     }   
01811     //  Put the file back to wherever it was before we used it
01812     ExportFile->seek(here);
01813 
01814     // reset the cache count thingy
01815     NumberOfEntriesUsedInCache = 0;
01816 
01817     return TRUE;
01818 }
01819 
01820 /********************************************************************************************
01821 
01822 >   BOOL CMXExportDC::StartPage(Rect *BBox, BOOL IsProcedure = FALSE)
01823 
01824     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01825     Created:    25/06/96
01826     Inputs:     none
01827     Returns:    success
01828     Purpose:    starts a Page
01829     SeeAlso:    
01830 
01831 ********************************************************************************************/
01832 
01833 BOOL CMXExportDC::StartPage(DocRect *BBox, BOOL IsProcedure)
01834 {
01835     ERROR2IF(DoingPage == TRUE, FALSE, "Already doing a page");
01836 
01837     if(!IsProcedure)
01838     {
01840 
01841         // make the page reference object
01842         PageRefer = new CMXReferPage(this);
01843         if(PageRefer == NULL)
01844             return FALSE;
01845         ReferList.AddTail(PageRefer);
01846 
01847         // start the section
01848         StartSection(CMXSECTION_PAGE);
01849 
01850         // write the page start
01851         StartCommand(cmxINSTR_BeginPage);
01852 
01853         // tag this bit
01854         if(!StartTag(cmxTAG_BeginPage_PageSpecification))
01855             return FALSE;
01856 
01857         cmxInstrPage1 phdr1;
01858         phdr1.PageNumber = 1;
01859         phdr1.Flags = 0;
01860         ExportFile->write(&phdr1, sizeof(phdr1));
01861 
01862         // set the future flags value
01863         PageFlags.Init(this, FUTURE_BACKLOC(&phdr1, Flags), sizeof(phdr1.Flags));
01864         PageFlags = 0;
01865 
01866         // write the bbox, transforming the thing of course
01867         WriteBBox(BBox);
01868 
01869         // write the rest of the page command
01870         cmxInstrPage2 phdr2;
01871         phdr2.EndPageOffset = 0;
01872         phdr2.GroupCount = 0;
01873         phdr2.InstructionCount = 0;
01874         ExportFile->write(&phdr2, sizeof(phdr2));
01875 
01876         // set up some future values
01877         PageEndIndexFuture.Init(this, FUTURE_BACKLOC(&phdr2, EndPageOffset), sizeof(phdr2.EndPageOffset));
01878         PageGroupCount.Init(this, FUTURE_BACKLOC(&phdr2, GroupCount), sizeof(phdr2.GroupCount));
01879         PageGroupCount = 0;
01880         PageInstructionCount.Init(this, FUTURE_BACKLOC(&phdr2, InstructionCount), sizeof(phdr2.InstructionCount));
01881         PageInstructionCount = 1; // to include this instr
01882 
01883         // end the tag
01884         if(!EndTag())
01885             return FALSE;
01886 
01887         // matrix tag...
01888         if(!StartTag(cmxTAG_BeginPage_Matrix))
01889             return FALSE;
01890 
01891         // write the matrix
01892         if(!WriteMatrix())
01893             return FALSE;
01894 
01895         // end the tag
01896         if(!EndTag())
01897             return FALSE;
01898 
01899         // mapping mode...
01900         BYTE MapMode = 0;
01901         if(!WriteTag(cmxTAG_BeginPage_MappingMode, &MapMode, sizeof(MapMode)))
01902             return FALSE;
01903 
01904         // end tag
01905         if(!WriteMinEndTag())
01906             return FALSE;
01907 
01908         // end the command
01909         EndCommand();
01910 
01911         // flag
01912         PageIsProc = FALSE;
01913     }
01914     else
01915     {
01917 
01918         // write the procedure start
01919         StartCommand(cmxINSTR_BeginProcedure);
01920 
01921         // tag this bit
01922         if(!StartTag(cmxTAG_BeginProcedure_ProcedureSpecification))
01923             return FALSE;
01924 
01925         cmxInstrProc1 phdr1;
01926         phdr1.Flags = 0;
01927         ExportFile->write(&phdr1, sizeof(phdr1));
01928 
01929         // set the future flags value
01930         PageFlags.Init(this, FUTURE_BACKLOC(&phdr1, Flags), sizeof(phdr1.Flags));
01931         PageFlags = 0;
01932 
01933         // write the bbox, not transforming it as we've already done that
01934         WriteBBox(BBox, FALSE);
01935 
01936         // write the rest of the page command
01937         cmxInstrProc2 phdr2;
01938         phdr2.EndPageOffset = 0;
01939         phdr2.GroupCount = 0;
01940         phdr2.InstructionCount = 0;
01941         ExportFile->write(&phdr2, sizeof(phdr2));
01942 
01943         // set up some future values
01944         PageEndIndexFuture.Init(this, FUTURE_BACKLOC(&phdr2, EndPageOffset), sizeof(phdr2.EndPageOffset));
01945         PageGroupCount.Init(this, FUTURE_BACKLOC(&phdr2, GroupCount), sizeof(phdr2.GroupCount));
01946         PageGroupCount = 0;
01947         PageInstructionCount.Init(this, FUTURE_BACKLOC(&phdr2, InstructionCount), sizeof(phdr2.InstructionCount));
01948         PageInstructionCount = 1; // to include this instr
01949 
01950         // end the tag
01951         if(!EndTag())
01952             return FALSE;
01953 
01954         // end tag
01955         if(!WriteMinEndTag())
01956             return FALSE;
01957 
01958         // end the command
01959         EndCommand();
01960 
01961         // flag
01962         PageIsProc = TRUE;
01963     }
01964 
01965     DoingPage = TRUE;
01966     LayerNumber = 0;
01967 
01968     // record the location of the first instruction in the file, which will follow immediately
01969     if(!IsProcedure)
01970         FirstInstrFilePosition = GetFilePosition();
01971 
01972     // write a comment to say where this file came from
01973     // return WriteCamComment();
01974     return TRUE;                // Graeme (10-2-00) replaced above return with return TRUE.
01975 }
01976 
01977 
01978 /********************************************************************************************
01979 
01980 >   BOOL CMXExportDC::EndPage(void)
01981 
01982     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01983     Created:    25/06/96
01984     Inputs:     none
01985     Returns:    success
01986     Purpose:    ends a Page
01987     SeeAlso:    
01988 
01989 ********************************************************************************************/
01990 
01991 BOOL CMXExportDC::EndPage(void)
01992 {
01993     ERROR2IF(DoingPage == FALSE, FALSE, "Not doing a page");
01994 
01995     // write the index of the end page command
01996     PageEndIndexFuture.Write(this);
01997 
01998     // write the end page command
01999     if(!PageIsProc)
02000         WriteCommand(cmxINSTR_EndPage);
02001     else
02002         WriteCommand(cmxINSTR_EndSection);
02003 
02004     // write future values
02005     PageFlags.Write(this);
02006     PageInstructionCount.Write(this);
02007     PageGroupCount.Write(this);
02008 
02009     // finish the section
02010     if(!PageIsProc)
02011         EndSection();
02012 
02013     DoingPage = FALSE;
02014 
02015     return TRUE;
02016 }
02017 
02018 
02019 /********************************************************************************************
02020 
02021 >   BOOL CMXExportDC::StartLayer(String_256 &Name)
02022 
02023     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02024     Created:    25/06/96
02025     Inputs:     layer name
02026     Returns:    success
02027     Purpose:    starts a layer
02028     SeeAlso:    
02029 
02030 ********************************************************************************************/
02031 
02032 BOOL CMXExportDC::StartLayer(String_256 &Name)
02033 {
02034     ERROR2IF(DoingPage == FALSE, FALSE, "Layers should be in pages");
02035     ERROR2IF(DoingLayer == TRUE, FALSE, "Already doing a layer");
02036 
02037     LayerNumber++;
02038 
02039     // get a entry for this thingy in the reference list
02040     CMXReferLayer *pRL = new CMXReferLayer(this);
02041     if(pRL == NULL)
02042         return FALSE;
02043     pRL->SetLayerDetails(LayerNumber, &Name);
02044     ReferList.AddTail(pRL);             // add it to the list
02045 
02046     // start the command
02047     StartCommand(cmxINSTR_BeginLayer);
02048 
02049     // tag
02050     if(!StartTag(cmxTAG_BeginLayer_LayerSpecification))
02051         return FALSE;
02052 
02053     // write the first bit of the instruction
02054     cmxInstrLayer1 chdr1;
02055     chdr1.PageNumber = 1;
02056     chdr1.LayerNumber = (WORD)LayerNumber;
02057     chdr1.LayerFlags = 0;
02058     chdr1.InstructionCount = 0;
02059     ExportFile->write(&chdr1, sizeof(chdr1));
02060 
02061     // set up the instruciton count future
02062     LayerInstructionCount.Init(this, FUTURE_BACKLOC(&chdr1, InstructionCount), sizeof(chdr1.InstructionCount));
02063     LayerFlags.Init(this, FUTURE_BACKLOC(&chdr1, LayerFlags), sizeof(chdr1.LayerFlags));
02064     LayerFlags = 0;
02065 
02066     // write it's name out
02067     WriteString(&Name);
02068 
02069     // end the tag
02070     if(!EndTag())
02071         return FALSE;
02072 
02073     // write the second bit of the thingy
02074     if(!StartTag(cmxTAG_BeginLayer_Matrix))
02075         return FALSE;
02076     if(!WriteMatrix())
02077         return FALSE;
02078     if(!EndTag())
02079         return FALSE;
02080 
02081     // mapping mode...
02082     BYTE MapMode = 0;
02083     if(!WriteTag(cmxTAG_BeginLayer_MappingMode, &MapMode, sizeof(MapMode)))
02084         return FALSE;
02085     
02086     // end tag
02087     if(!WriteMinEndTag())
02088         return FALSE;
02089 
02090     // end the command
02091     EndCommand();
02092 
02093     LayerInstructionCount = 1;      // to include this one
02094 
02095     DoingLayer = TRUE;
02096 
02097     return TRUE;
02098 }
02099 
02100 
02101 /********************************************************************************************
02102 
02103 >   BOOL CMXExportDC::EndLayer(void)
02104 
02105     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02106     Created:    25/06/96
02107     Inputs:     none
02108     Returns:    success
02109     Purpose:    ends a layer
02110     SeeAlso:    
02111 
02112 ********************************************************************************************/
02113 
02114 BOOL CMXExportDC::EndLayer(void)
02115 {
02116     ERROR2IF(DoingLayer == FALSE, FALSE, "Already doing a layer");
02117 
02118     // write the end layer command
02119     WriteCommand(cmxINSTR_EndLayer);
02120 
02121     // write the count of instructions in the layer
02122     LayerInstructionCount.Write(this);
02123     LayerFlags.Write(this);
02124 
02125     DoingLayer = FALSE;
02126 
02127     return TRUE;
02128 }
02129 
02130 
02131 
02132 /********************************************************************************************
02133 
02134 >   BOOL CMXExportDC::StartGroup(DocRect *BBox)
02135 
02136     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02137     Created:    25/06/96
02138     Inputs:     none
02139     Returns:    success
02140     Purpose:    starts a group
02141     SeeAlso:    
02142 
02143 ********************************************************************************************/
02144 
02145 BOOL CMXExportDC::StartGroup(DocRect *BBox, BOOL TransformBBox)
02146 {
02147     ERROR2IF(DoingLayer == FALSE && !PageIsProc, FALSE, "Groups should be in layers");
02148     
02149     // increment the group count
02150     PageGroupCount++;
02151 
02152     // start the command
02153     if(!StartCommand(cmxINSTR_BeginGroup))
02154         return FALSE;
02155 
02156     // start the tag
02157     if(!StartTag(cmxTAG_BeginGroup_GroupSpecification))
02158         return FALSE;
02159 
02160     // write the bounding box
02161     if(!WriteBBox(BBox, TransformBBox))
02162         return FALSE;
02163 
02164     // get a group record object
02165     CMXGroupRecord *pGRec = new CMXGroupRecord(this);
02166     if(pGRec == NULL)
02167         return FALSE;
02168 
02169     // add the group record object to the list
02170     GroupList.AddTail(pGRec);
02171 
02172     // write a place holder data chunk
02173     cmxGroupInfo gi = {0,0,0};
02174     ExportFile->write(&gi, sizeof(gi));
02175 
02176     if(!EndTag())
02177         return FALSE;
02178 
02179     if(!WriteMinEndTag())
02180         return FALSE;
02181 
02182     // end the command
02183     if(!EndCommand())
02184         return FALSE;
02185 
02186     return TRUE;
02187 }
02188 
02189 
02190 /********************************************************************************************
02191 
02192 >   BOOL CMXExportDC::EndGroup(void)
02193 
02194     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02195     Created:    25/06/96
02196     Inputs:     none
02197     Returns:    success
02198     Purpose:    ends a group
02199     SeeAlso:    
02200 
02201 ********************************************************************************************/
02202 
02203 BOOL CMXExportDC::EndGroup(void)
02204 {
02205     // get the last entry off the group list
02206     CMXGroupRecord *pGRec = (CMXGroupRecord *)GroupList.GetTail();
02207 
02208     // get it to write itself
02209     if(!pGRec->Write(this))
02210         return FALSE;
02211 
02212     // delete the group record
02213     delete GroupList.RemoveTail();
02214 
02215     // write the end group command
02216     if(!WriteCommand(cmxINSTR_EndGroup))
02217         return FALSE;
02218 
02219     return TRUE;
02220 }
02221 
02222 
02223 /********************************************************************************************
02224 
02225 >   CMXGroupRecord::CMXGroupRecord(CMXExportDC *pDC)
02226 
02227     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02228     Created:    26/06/96
02229     Inputs:     a CMXExportDC
02230     Returns:    none
02231     Purpose:    initialises the group record
02232     SeeAlso:    
02233 
02234 ********************************************************************************************/
02235 
02236 CMXGroupRecord::CMXGroupRecord(CMXExportDC *pDC)
02237 {
02238     Offset = pDC->GetFilePosition();
02239     TallyAtStart = pDC->GetInstructionTally();
02240     GroupCountAtStart = pDC->GetGroupCount();
02241 }
02242 
02243 
02244 /********************************************************************************************
02245 
02246 >   CMXGroupRecord::CMXGroupRecord(CMXExportDC *pDC)
02247 
02248     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02249     Created:    26/06/96
02250     Inputs:     a CMXExportDC
02251     Returns:    sucess
02252     Purpose:    writes the info in the start of the group command
02253     SeeAlso:    
02254 
02255 ********************************************************************************************/
02256 
02257 BOOL CMXGroupRecord::Write(CMXExportDC *pDC)
02258 {
02259     // write the group count
02260     if(!pDC->WriteNumber(Offset, sizeof(WORD), pDC->GetGroupCount() - GroupCountAtStart))
02261         return FALSE;
02262     // write the instruction count
02263     if(!pDC->WriteNumber(Offset + sizeof(WORD), sizeof(DWORD), pDC->GetInstructionTally() - TallyAtStart))
02264         return FALSE;
02265     // write the group end location
02266     if(!pDC->WriteNumber(Offset + sizeof(WORD) + sizeof(DWORD), sizeof(DWORD), pDC->GetFilePosition()))
02267         return FALSE;
02268 
02269     return TRUE;
02270 }
02271 
02272 
02273 /********************************************************************************************
02274 
02275 >   BOOL CMXExportDC::WriteReferenceList(void)
02276 
02277     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02278     Created:    25/06/96
02279     Inputs:     none
02280     Returns:    success
02281     Purpose:    writes the reference list for the page we've just done
02282     SeeAlso:    
02283 
02284 ********************************************************************************************/
02285 
02286 BOOL CMXExportDC::WriteReferenceList(void)
02287 {
02288     // first, find the number of entries in this list
02289     WORD RefListEntries = 0;
02290     CMXReferListItem *pEn = (CMXReferListItem *)ReferList.GetHead();
02291     while(pEn != 0)
02292     {
02293         ERROR3IF(!pEn->IsKindOf(CC_RUNTIME_CLASS(CMXReferListItem)), "Entry in the refer list isn't a correct list item");
02294 
02295         if(pEn->IsInReferenceList())
02296             RefListEntries++;
02297 
02298         pEn = (CMXReferListItem *)ReferList.GetNext(pEn);
02299     }
02300 
02301     // set the location in the page reference item
02302     ERROR2IF(PageRefer == NULL, FALSE, "no page reference item");
02303     PageRefer->SetRefListOffset(GetFilePosition());
02304     RefListOffset = GetFilePosition();
02305 
02306     // start the section
02307     if(!StartSection(CMXSECTION_REFLIST))
02308         return FALSE;
02309 
02310     // write the number of entries in the list
02311     ExportFile->write(&RefListEntries, sizeof(RefListEntries));
02312 
02313     // write the entries
02314     pEn = (CMXReferListItem *)ReferList.GetHead();
02315     while(pEn != 0)
02316     {
02317         ERROR3IF(!pEn->IsKindOf(CC_RUNTIME_CLASS(CMXReferListItem)), "Entry in the refer list isn't a correct list item");
02318 
02319         if(!pEn->WriteInReferenceList(this))
02320             return FALSE;
02321 
02322         pEn = (CMXReferListItem *)ReferList.GetNext(pEn);
02323     }
02324 
02325     // end the section
02326     if(!EndSection())
02327         return FALSE;
02328 
02329     return TRUE;
02330 }
02331 
02332 
02333 /********************************************************************************************
02334 
02335 >   BOOL CMXExportDC::WriteIndex(void)
02336 
02337     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02338     Created:    25/06/96
02339     Inputs:     none
02340     Returns:    success
02341     Purpose:    writes the index for the file
02342     SeeAlso:    
02343 
02344 ********************************************************************************************/
02345 
02346 BOOL CMXExportDC::WriteIndex(void)
02347 {
02348     // start the section
02349     if(!StartSection(CMXSECTION_INDEX))
02350         return FALSE;
02351 
02352     // write the layer index
02353     if(!WriteAnIndex(cmxINDEX_LAYER))
02354         return FALSE;
02355 
02356     // write the master layer index
02357     if(!WriteAnIndex(cmxINDEX_MASTERLAYER))
02358         return FALSE;
02359 
02360     // write the page index
02361     if(!WriteAnIndex(cmxINDEX_PAGE))
02362         return FALSE;
02363 
02364     // write the procedure index
02365     if(!WriteAnIndex(cmxINDEX_PROCEDURE))
02366         return FALSE;
02367 
02368     // write the embedded file index
02369     if(!WriteAnIndex(cmxINDEX_EMBEDFILE))
02370         return FALSE;
02371 
02372     // write the embedded file index
02373     if(!WriteAnIndex(cmxINDEX_ARROW))
02374         return FALSE;
02375 
02376     // write the master index
02377     if(!WriteAnIndex(cmxINDEX_MASTERINDEX))
02378         return FALSE;
02379 
02380     // end the section
02381     if(!EndSection())
02382         return FALSE;
02383 
02384     return TRUE;
02385 }
02386 
02387 
02388 /********************************************************************************************
02389 
02390 >   BOOL CMXExportDC::WriteCamComment(void)
02391 
02392     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02393     Created:    01/08/96
02394     Inputs:     none
02395     Returns:    success
02396     Purpose:    writes a helpful comment so we can see where dodgy cam cmx files come from
02397     SeeAlso:    
02398 
02399 ********************************************************************************************/
02400 
02401 BOOL CMXExportDC::WriteCamComment(void)
02402 {
02403     if(PageIsProc)
02404         return TRUE;            // only write comments in pages
02405 
02406     CCamApp*    Application;
02407     String_64   Text;
02408     String_256  TheText = String_256("saved from " PRODUCT_NAME " "); // WEBSTER - markn 26/11/96
02409 
02410     // munge an info string together
02411     Application = (CCamApp*) AfxGetApp();           // Find our main application object
02412 
02413     Application->GetCamelotVersion(&Text);
02414     Text += TEXT("(v");
02415     Text += TEXT(PRODUCT_VERSION_NO);
02416     Text += TEXT(")");
02417     TheText += Text;
02418 
02419 //  Text.MakeMsg(_R(IDS_CAMVERSION), &Text1);
02420 
02421     Text._MakeMsg(TEXT(" (#1%d) "), (INT32) CAMELOT_VERSION_MINOR);
02422     TheText += Text;
02423 
02424     Application->GetCamelotType(&Text);
02425     TheText += Text;
02426     
02427     TheText += " on ";
02428     Application->GetHostOSName(&Text);              // ... plonk info from it into the dlog
02429     TheText += Text;
02430 
02431     TRACEUSER( "Ben", _T("setting comment = %s\n"), (TCHAR *)TheText);
02432 
02433     // now start a command and a tag
02434     if(!StartCommand(cmxINSTR_Comment) || !StartTag(cmxTAG_Comment_CommentSpecification))
02435         return FALSE;
02436 
02437     WORD Size = TheText.Length();
02438 
02439     ExportFile->write(&Size, sizeof(Size));
02440 
02441     ExportFile->write((TCHAR *)TheText, Size);
02442 
02443     // end the command
02444     if(!EndTag() || !WriteMinEndTag() || !EndCommand())
02445         return FALSE;
02446 
02447     return TRUE;    
02448 }
02449 
02450 
02451 /********************************************************************************************
02452 
02453 >   BOOL CMXExportDC::WriteReferSections(void)
02454 
02455     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02456     Created:    12/07/96
02457     Inputs:     none
02458     Returns:    success
02459     Purpose:    gets all refer list items which are sections to write themselves
02460     SeeAlso:    
02461 
02462 ********************************************************************************************/
02463 
02464 BOOL CMXExportDC::WriteReferSections(void)
02465 {
02466     // wander through the list
02467     CMXReferListItem *pEn = (CMXReferListItem *)ReferList.GetHead();
02468     while(pEn != 0)
02469     {
02470         ERROR3IF(!pEn->IsKindOf(CC_RUNTIME_CLASS(CMXReferListItem)), "unexpected type of entry in refer list");
02471 
02472         if(pEn->IsASection())
02473         {
02474             if(!pEn->WriteSection(this))
02475                 return FALSE;
02476         }
02477 
02478         pEn = (CMXReferListItem *)ReferList.GetNext(pEn);
02479     }
02480 
02481     return TRUE;
02482 }
02483 
02484 
02485 /********************************************************************************************
02486 
02487 >   BOOL CMXExportDC::WriteAnIndex(INT32 Which)
02488 
02489     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02490     Created:    25/06/96
02491     Inputs:     none
02492     Returns:    success
02493     Purpose:    writes the a particular index to the file
02494     SeeAlso:    
02495 
02496 ********************************************************************************************/
02497 
02498 BOOL CMXExportDC::WriteAnIndex(INT32 Which)
02499 {
02500     // size of the table -- special actions may add some stuff to it
02501     INT32 TableSize = sizeof(WORD); // for record count
02502 
02503     // get some types and sort out the master index entry for this table
02504     // and do any special actions for certain index types
02505     INT32 id;
02506     CMXReferMasterIndex *pMIE = new CMXReferMasterIndex(this);
02507     if(pMIE == NULL)
02508         return FALSE;
02509     BOOL NoMIE = FALSE;
02510     switch(Which)
02511     {
02512     case cmxINDEX_LAYER:
02513         {
02514             ERROR2IF(PageRefer == NULL, FALSE, "no page refer set up");
02515             PageRefer->SetLayerTableOffset(GetFilePosition());
02516 
02517             id = cmxRIFFCI_LayerIndex;
02518             NoMIE = TRUE;
02519             TableSize += sizeof(WORD);          // for page number
02520 
02521             // add an entry for the master layer table
02522             CMXReferMasterLayer *pML = new CMXReferMasterLayer(this);
02523             if(pML == NULL)
02524                 return FALSE;
02525             ReferList.AddTail(pML);             // add it -- nothing else to set
02526         }
02527         break;
02528 
02529     case cmxINDEX_PAGE:
02530         id = cmxRIFFCI_PageIndex;
02531         pMIE->SetType(cmxMASTERIN_PAGE);
02532         break;
02533 
02534     case cmxINDEX_MASTERINDEX:
02535         // note the start of the index section in the file header
02536         IndexSectionFuture.Write(this);
02537 
02538         TableSize += sizeof(cmxMasterIndexHeader);
02539         id = cmxRIFFCI_MasterIndex;
02540         pMIE->SetType(cmxMASTERIN_MASTERIN);
02541         break;
02542 
02543     case cmxINDEX_MASTERLAYER:              // remember this is single entry table and is fudged
02544         id = cmxRIFFCI_MasterLayerIndex;    // in the refer list object
02545         pMIE->SetType(cmxMASTERIN_MASTERLAYER);
02546         break;
02547 
02548     case cmxINDEX_PROCEDURE:
02549         id = cmxRIFFCI_ProcIndex;
02550         pMIE->SetType(cmxMASTERIN_PROCEDURE);
02551         break;
02552 
02553     case cmxINDEX_EMBEDFILE:
02554         id = cmxRIFFCI_EmbeddedFileIndex;
02555         pMIE->SetType(cmxMASTERIN_EMBEDFILE);
02556         break;
02557 
02558     case cmxINDEX_ARROW:
02559         id = cmxRIFFCI_ArrowIndex;
02560         pMIE->SetType(cmxMASTERIN_ARROW);
02561         TableSize += sizeof(cmxArrowIndexHeader) + (ThirtyTwoBit?sizeof(WORD):0);
02562         break;
02563 
02564     default:
02565         ERROR3("Don't know what type of index to write!");
02566     }
02567 
02568     if(NoMIE)
02569     {
02570         delete pMIE;        // don't need this
02571     }
02572     else
02573     {
02574         ReferList.AddTail(pMIE);
02575     }
02576 
02577     // scan the refer list and see how many entries we've got, and how long they are
02578     WORD Entries = 0;
02579     CMXReferListItem *pEn = (CMXReferListItem *)ReferList.GetHead();
02580     while(pEn != 0)
02581     {
02582         ERROR3IF(!pEn->IsKindOf(CC_RUNTIME_CLASS(CMXReferListItem)), "unexpected type of entry in refer list");
02583 
02584         if(pEn->IsInWhichIndex() == Which)
02585         {
02586             Entries++;
02587             TableSize += pEn->IndexEntrySize(this);
02588         }
02589 
02590         pEn = (CMXReferListItem *)ReferList.GetNext(pEn);
02591     }
02592 
02593     if(Entries == 0)
02594     {
02595         // nothing to write -- go away now after removing the entry from the master index
02596         delete ReferList.RemoveItem(pMIE);
02597         return TRUE;
02598     }
02599 
02600     // write the header
02601     RIFFck ck;
02602     ck.ckID = id;
02603     ck.ckSize = TableSize;
02604     ExportFile->write(&ck, sizeof(ck));
02605 
02606     if(Which == cmxINDEX_MASTERINDEX)
02607     {
02608         // write it's special header
02609         cmxMasterIndexHeader mih = {cmxMASTERIN_MASTERIN, ThirtyTwoBit?0xfff:0x18};
02610         ExportFile->write(&mih, sizeof(mih));
02611     }
02612 
02613     ExportFile->write(&Entries, sizeof(Entries));       // write record count
02614 
02615     // do specials
02616     switch(Which)
02617     {
02618     case cmxINDEX_LAYER:
02619         {
02620             WORD PageNumber = 1;
02621             ExportFile->write(&PageNumber, sizeof(PageNumber));
02622         }
02623         break;
02624 
02625     case cmxINDEX_ARROW:
02626         {
02627             cmxArrowIndexHeader aih;
02628             WriteSizeInFile(sizeof(cmxArrowIndexEntry));
02629             aih.Type = cmxARROWINDEXTYPE;
02630             ExportFile->write(&aih, sizeof(aih));
02631         }
02632         break;
02633 
02634     default:
02635         break;
02636     }
02637 
02638     // write the entries
02639     pEn = (CMXReferListItem *)ReferList.GetHead();
02640     while(pEn != 0)
02641     {
02642         ERROR3IF(!pEn->IsKindOf(CC_RUNTIME_CLASS(CMXReferListItem)), "unexpected type of entry in refer list");
02643 
02644         if(pEn->IsInWhichIndex() == Which)
02645         {
02646             if(!pEn->WriteInIndex(this))
02647                 return FALSE;
02648         }
02649 
02650         pEn = (CMXReferListItem *)ReferList.GetNext(pEn);
02651     }
02652 
02653     // if necessary, word align the thingy
02654     if((GetFilePosition() & 1) != 0)
02655     {
02656         // put an extra byte in the file
02657         ExportFile->put('\0');
02658     }
02659 
02660     // done
02661     return TRUE;
02662 }
02663 
02664 /********************************************************************************************
02665 
02666 >   void CMXExportDC::SetCMXFlag(INT32 flag)
02667 
02668     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02669     Created:    25/07/96
02670     Inputs:     none
02671     Returns:    none
02672     Purpose:    sets a flag for pages, layers
02673     SeeAlso:    
02674 
02675 ********************************************************************************************/
02676 
02677 void CMXExportDC::SetCMXFlag(INT32 flag)
02678 {
02679     PageFlags = ((INT32)PageFlags) | flag;
02680     LayerFlags = ((INT32)LayerFlags) | flag;
02681 }
02682 
02683 
02684 /********************************************************************************************
02685 
02686 >   BOOL CMXExportDC::WriteDescriptionSections(void)
02687 
02688     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02689     Created:    27/06/96
02690     Inputs:     none
02691     Returns:    success
02692     Purpose:    writes the descption sections
02693     SeeAlso:    
02694 
02695 ********************************************************************************************/
02696 
02697 #define WRITEDESC(h) if(!WriteADesc(h)) return FALSE;
02698 
02699 BOOL CMXExportDC::WriteDescriptionSections(void)
02700 {
02701     WRITEDESC(cmxDESC_ARROW)
02702     WRITEDESC(cmxDESC_ARROWHEADS)
02703     WRITEDESC(cmxDESC_DOTDASH)
02704     WRITEDESC(cmxDESC_FONT)
02705     WRITEDESC(cmxDESC_OUTLINE)
02706     WRITEDESC(cmxDESC_LINESTYLE)
02707     WRITEDESC(cmxDESC_PEN)
02708     WRITEDESC(cmxDESC_SCREEN)
02709     WRITEDESC(cmxDESC_COLOUR)
02710 
02711     return TRUE;
02712 }
02713 
02714 
02715 /********************************************************************************************
02716 
02717 >   BOOL CMXExportDC::WriteADesc(INT32 Which)
02718 
02719     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02720     Created:    25/06/96
02721     Inputs:     none
02722     Returns:    success
02723     Purpose:    writes the a particular index to the file
02724     SeeAlso:    
02725 
02726 ********************************************************************************************/
02727 
02728 BOOL CMXExportDC::WriteADesc(INT32 Which)
02729 {
02730     // get some types and sort out the master index entry for this table
02731     // and do any special actions for certain index types
02732     INT32 Section;
02733     CMXReferMasterIndex *pMIE = new CMXReferMasterIndex(this);
02734     if(pMIE == NULL)
02735         return FALSE;
02736     BOOL NoMIE = FALSE;
02737     BOOL HasRecordCount = TRUE;
02738     BOOL CanOmit = FALSE;
02739     switch(Which)
02740     {
02741     case cmxDESC_ARROW:
02742         Section = CMXSECTION_ARROW;
02743         CanOmit = TRUE;
02744         pMIE->SetType(cmxMASTERIN_ARROW);
02745         HasRecordCount = FALSE;
02746         break;
02747 
02748     case cmxDESC_ARROWHEADS:
02749         Section = CMXSECTION_ARROWHEADS;
02750         pMIE->SetType(cmxMASTERIN_ARROWHEADS);
02751         break;
02752 
02753     case cmxDESC_COLOUR:
02754         Section = CMXSECTION_COLOUR;
02755         pMIE->SetType(cmxMASTERIN_COLOUR);
02756         break;
02757 
02758     case cmxDESC_DOTDASH:
02759         Section = CMXSECTION_DOTDASH;
02760         pMIE->SetType(cmxMASTERIN_DOTDASH);
02761         break;
02762 
02763     case cmxDESC_FONT:
02764         Section = CMXSECTION_FONT;
02765         pMIE->SetType(cmxMASTERIN_FONT);
02766         CanOmit = TRUE;
02767         HasRecordCount = FALSE;
02768         break;
02769 
02770 /*  case cmxDESC_IMAGE:
02771         Section = CMXSECTION_IMAGE;
02772         pMIE->SetType(cmxMASTERIN_IMAGE);
02773         CanOmit = TRUE;
02774         HasRecordCount = FALSE;
02775         break;
02776 */
02777     case cmxDESC_OUTLINE:
02778         Section = CMXSECTION_OUTLINE;
02779         pMIE->SetType(cmxMASTERIN_OUTLINE);
02780         break;
02781 
02782     case cmxDESC_LINESTYLE:
02783         Section = CMXSECTION_LINESTYLE;
02784         pMIE->SetType(cmxMASTERIN_LINESTYLE);
02785         break;
02786 
02787     case cmxDESC_PEN:
02788         Section = CMXSECTION_PEN;
02789         pMIE->SetType(cmxMASTERIN_PEN);
02790         break;
02791 
02792     case cmxDESC_SCREEN:
02793         Section = CMXSECTION_SCREEN;
02794         pMIE->SetType(cmxMASTERIN_SCREEN);
02795         break;
02796     
02797     default:
02798         ERROR3("Don't know what type of desc to write!");
02799     }
02800 
02801     // scan the refer list and see how many entries we've got, and how long they are
02802     WORD Entries = 0;
02803     CMXReferListItem *pEn = (CMXReferListItem *)ReferList.GetHead();
02804     while(pEn != 0)
02805     {
02806         ERROR3IF(!pEn->IsKindOf(CC_RUNTIME_CLASS(CMXReferListItem)), "unexpected type of entry in refer list");
02807 
02808         if(pEn->IsInWhichDesc() == Which)
02809         {
02810             Entries++;
02811         }
02812 
02813         pEn = (CMXReferListItem *)ReferList.GetNext(pEn);
02814     }
02815 
02816     // do we need to save this section?
02817     if(Entries == 0 && CanOmit)
02818     {
02819         delete pMIE;        // delete the record
02820         return TRUE;        // don't do anything
02821     }
02822 
02823     // add this section to the master entry list
02824     if(NoMIE)
02825     {
02826         delete pMIE;        // don't need this
02827     }
02828     else
02829     {
02830         ReferList.AddTail(pMIE);
02831     }
02832 
02833     // start the section, and maybe write a record count
02834     if(!StartSection((CMXExportDC::CMXSectionType)Section))
02835         return FALSE;
02836     if(HasRecordCount)
02837         ExportFile->write(&Entries, sizeof(Entries));       // write record count
02838 
02839     // write the entries
02840     pEn = (CMXReferListItem *)ReferList.GetHead();
02841     while(pEn != 0)
02842     {
02843         ERROR3IF(!pEn->IsKindOf(CC_RUNTIME_CLASS(CMXReferListItem)), "unexpected type of entry in refer list");
02844 
02845         if(pEn->IsInWhichDesc() == Which)
02846         {
02847             if(!pEn->WriteInDesc(this))
02848                 return FALSE;
02849         }
02850 
02851         pEn = (CMXReferListItem *)ReferList.GetNext(pEn);
02852     }
02853 
02854     // end the section
02855     if(!EndSection())
02856         return FALSE;
02857 
02858     // done
02859     return TRUE;
02860 }
02861 
02862 
02863 /********************************************************************************************
02864 
02865 >   BOOL CMXReferDotDash::WriteInDesc(CMXExportDC *pDC)
02866 
02867     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02868     Created:    25/07/96
02869     Inputs:     none
02870     Returns:    success
02871     Purpose:    writes a dot dash pattern to the description section
02872     SeeAlso:    
02873 
02874 ********************************************************************************************/
02875 
02876 BOOL CMXReferDotDash::WriteInDesc(CMXExportDC *pDC)
02877 {
02878     pDash->CheckAndFix();           // just in case
02879 
02880     // start the tag
02881     if(!pDC->StartTag(cmxTAG_DescrSection_Dash))
02882         return FALSE;
02883 
02884     // dot count
02885     WORD DotCount = (WORD)pDash->Elements;
02886     if(!pDC->WriteData(&DotCount, sizeof(DotCount)))
02887         return FALSE;
02888 
02889     // write the elements
02890     for(INT32 l = 0; l < pDash->Elements; l++)
02891     {
02892         WORD Element = (WORD)((pDash->ElementData[l] + 4) / pDash->LineWidth);
02893         if(Element <= 0) Element = 1;
02894         Element *= 4;
02895         if(!pDC->WriteData(&Element, sizeof(Element)))
02896             return FALSE;
02897     }
02898 
02899     // end the tag and write the end tag
02900     if(!pDC->EndTag() || !pDC->WriteMinEndTag())
02901         return FALSE;
02902 
02903     return TRUE;
02904 }
02905 
02906 
02907 /********************************************************************************************
02908 
02909 >   BOOL CMXReferArrow::WriteInDesc(CMXExportDC *pDC)
02910 
02911     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02912     Created:    25/07/96
02913     Inputs:     none
02914     Returns:    success
02915     Purpose:    writes a arrowhead definition to the description section
02916     SeeAlso:    
02917 
02918 ********************************************************************************************/
02919 
02920 BOOL CMXReferArrow::WriteInDesc(CMXExportDC *pDC)
02921 {
02922     // store the position of this thingy
02923     ArrowFilePosition = pDC->GetFilePosition();
02924 
02925     // start a tag
02926     if(!pDC->StartTag(cmxTAG_DescrSection_Arrow))
02927         return FALSE;
02928 
02929     // get some details about the path of the arrowhead
02930     Path *pPath = pArrow->GetArrowPath();
02931     ERROR2IF(pPath == NULL, FALSE, "no arrow path");
02932     INT32 NumCoords = pPath->GetNumCoords();
02933     DocCoord *Coords = pPath->GetCoordArray();
02934     PathVerb *Verbs = pPath->GetVerbArray();
02935     DocRect ArrowBBox;
02936     pDC->CalcCorelBBox(Coords, NumCoords, &ArrowBBox);
02937 
02938     // work out a matrix for transforming the arrowhead path
02939     DocCoord ArrowCentre = pArrow->GetArrowCentre();
02940     // this bounding box needs to be scaled so that it's in the required range
02941     INT32 dl = abs(ArrowCentre.x - ArrowBBox.lo.x);
02942     INT32 dr = abs(ArrowBBox.hi.x - ArrowCentre.x);
02943     INT32 db = abs(ArrowCentre.y - ArrowBBox.lo.y);
02944     INT32 dt = abs(ArrowBBox.hi.y - ArrowCentre.y);
02945     INT32 maxdist = (dl > dr)?dl:dr;
02946     maxdist = (maxdist > db)?maxdist:db;
02947     maxdist = (maxdist > dt)?maxdist:dt;
02948     // maxdist is the greatest distance from the centre point -- this is
02949     // the distance which determines the scaling factor
02950     double ScaleFactor =
02951         ((double)(pDC->IsThirtyTwoBit()?cmxARROWDEF_MAXCOORD32:cmxARROWDEF_MAXCOORD16))
02952         / ((double)maxdist);
02953     Matrix Mat((FIXED16)ScaleFactor, 0, 0, (FIXED16)ScaleFactor, - ArrowCentre.x, - ArrowCentre.y);
02954 
02955     // export the path, transforming each coordinate as we go along
02956 
02957     // do we need to add an extra point?
02958     BOOL BungInExtraPoint = FALSE;
02959     if(Coords[0] != Coords[NumCoords - 1])
02960         BungInExtraPoint = TRUE;
02961 
02962     // write the point count
02963     WORD Count = (WORD)NumCoords + (BungInExtraPoint?1:0);
02964     pDC->WriteData(&Count, sizeof(Count));
02965 
02966     // run through the coords writing and transforming
02967     INT32 l;
02968     for(l = 0; l < NumCoords; l++)
02969     {
02970         DocCoord Coord = Coords[l];
02971         Mat.transform(&Coord);
02972 
02973         // write it...
02974         if(pDC->IsThirtyTwoBit())
02975         {
02976             cmxPoint32 p = {Coord.x, Coord.y};
02977             pDC->WriteData(&p, sizeof(p));
02978         }
02979         else
02980         {
02981             cmxPoint16 p = {(SWORD)Coord.x, (SWORD)Coord.y};
02982             pDC->WriteData(&p, sizeof(p));
02983         }
02984     }
02985 
02986     if(BungInExtraPoint)
02987     {
02988         DocCoord Coord = Coords[0];
02989         Mat.transform(&Coord);
02990 
02991         // write it...
02992         if(pDC->IsThirtyTwoBit())
02993         {
02994             cmxPoint32 p = {Coord.x, Coord.y};
02995             pDC->WriteData(&p, sizeof(p));
02996         }
02997         else
02998         {
02999             cmxPoint16 p = {(SWORD)Coord.x, (SWORD)Coord.y};
03000             pDC->WriteData(&p, sizeof(p));
03001         }
03002     }
03003 
03004     // run through the verbs writing point types
03005     INT32 BezCount = 0;     // for counting Bez
03006     for(l = 0; l < NumCoords; l++)
03007     {
03008         BYTE Type;
03009 
03010         switch(Verbs[l] & (PT_LINETO | PT_MOVETO | PT_BEZIERTO))
03011         {
03012         case PT_MOVETO:
03013             {
03014                 Type = CMXNODETYPE_TYPE_MOVE | CMXNODETYPE_USER;
03015             
03016                 // wibble forwards through the verbs to see if the correspondingness is closed
03017                 for(INT32 lp = l + 1; lp < NumCoords; lp++)
03018                 {
03019                     // OK, is this a move?
03020                     if((Verbs[lp] & (PT_LINETO | PT_MOVETO | PT_BEZIERTO)) == PT_MOVETO)
03021                         break;
03022 
03023                     // is closefigure set?
03024                     if((Verbs[lp] & PT_CLOSEFIGURE) != 0)
03025                     {
03026                         Type |= CMXNODETYPE_CLOSED;
03027                         break;
03028                     }
03029                 }
03030             }
03031             BezCount = 0;
03032             break;
03033 
03034         case PT_LINETO:
03035             Type = CMXNODETYPE_TYPE_LINE | CMXNODETYPE_USER;
03036             BezCount = 0;
03037             break;
03038 
03039         case PT_BEZIERTO:
03040             // in CMX, the control points have type ARC, and the end points
03041             // have type CURVE. This code does the trickery.
03042             if(BezCount == 2)
03043             {
03044                 Type = CMXNODETYPE_TYPE_CURVE | CMXNODETYPE_USER;
03045             }
03046             else
03047             {
03048                 Type = CMXNODETYPE_TYPE_ARC;
03049             }
03050             BezCount++;
03051             if(BezCount > 2)
03052                 BezCount = 0;       // so that only the end points of beziers get user flag
03053             break;
03054 
03055         default:
03056             ERROR3("Unknown node type");
03057             break;
03058         }
03059 
03060         if((Verbs[l] & PT_CLOSEFIGURE) != 0)
03061         {
03062             if(!BungInExtraPoint || l != (NumCoords - 1))
03063                 Type |= CMXNODETYPE_CLOSED;
03064         }
03065 
03066         if(l == (NumCoords - 1) && !BungInExtraPoint)
03067             Type |= CMXNODETYPE_CLOSED;
03068 
03069         pDC->WriteData(&Type, sizeof(Type));
03070     }
03071 
03072     if(BungInExtraPoint)
03073     {
03074         BYTE Type = CMXNODETYPE_TYPE_LINE | CMXNODETYPE_USER | CMXNODETYPE_CLOSED;
03075         pDC->WriteData(&Type, sizeof(Type));
03076     }
03077 
03078     // write the line offset
03079     DWORD LineOffset = 0;
03080     if(!pDC->WriteData(&LineOffset, sizeof(LineOffset)))
03081         return FALSE;
03082 
03083     // end the tag
03084     if(!pDC->EndTag() || !pDC->WriteMinEndTag())
03085         return FALSE;
03086 
03087     return TRUE;
03088 }
03089 
03090 
03091 /********************************************************************************************
03092 
03093 >   BOOL CMXReferArrow::WriteInDesc(CMXExportDC *pDC)
03094 
03095     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
03096     Created:    25/07/96
03097     Inputs:     none
03098     Returns:    success
03099     Purpose:    writes the index entry for the arrowhead
03100     SeeAlso:    
03101 
03102 ********************************************************************************************/
03103 
03104 BOOL CMXReferArrow::WriteInIndex(CMXExportDC *pDC)
03105 {
03106     // make the entry
03107     cmxArrowIndexEntry En;
03108     En.FilePosition = ArrowFilePosition;
03109 
03110     // write it...
03111     return pDC->WriteData(&En, sizeof(En));
03112 }
03113 
03114 
03115 /********************************************************************************************
03116 
03117 >   BOOL CMXExportDC::WritePreviewBitmap(void)
03118 
03119     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
03120     Created:    29/08/96
03121     Inputs:     none
03122     Returns:    success
03123     Purpose:    writes a preview bitmap type thing
03124     SeeAlso:    
03125 
03126 ********************************************************************************************/
03127 
03128 BOOL CMXExportDC::WritePreviewBitmap(void)
03129 {
03130     Filter* pFilter = NULL;
03131     pFilter = Filter::GetFirst();
03132     while ((pFilter != NULL) && (pFilter->FilterID != FILTERID_PREVIEW_BMP))
03133     {
03134         // Try the next filter
03135         pFilter = Filter::GetNext(pFilter);
03136     }
03137 
03138     // Make sure that we found the preview bitmap filter
03139     if ((pFilter != NULL) && (pFilter->IS_KIND_OF(BaseBitmapFilter)))
03140     {
03141         // write the index of this thumbnail section
03142         ThumbnailIndexFuture.Write(this);
03143 
03144         // start the section
03145         if(!StartSection(CMXSECTION_PREVIEWBITMAP))
03146             return FALSE;
03147 
03148         // write a number
03149         DWORD Eight = 8;
03150         Eight = NativetoLE(Eight);
03151         ExportFile->write(&Eight, sizeof(Eight));
03152 
03153         // fudge things a bit
03154         INT32 Start = ExportFile->tell();
03155         BITMAPFILEHEADER hdr;
03156         ExportFile->seek(Start - sizeof(hdr));
03157         ExportFile->read(&hdr, sizeof(hdr));
03158         ExportFile->seek(Start - sizeof(hdr));
03159 
03160         //WEBSTER-Martin-03/01/97
03161         // force the Preview to a fixed size
03162         INT32 OldPreviewSize = PreviewFilter::PreviewBitmapSize;
03163         // Set the Preview to be just over an inch accross
03164         PreviewFilter::PreviewBitmapSize = 96000;
03165 
03166         // Get as Bitmap Filter and set it up
03167         BaseBitmapFilter* pBitmapFilter = (BaseBitmapFilter*) pFilter;
03168         pBitmapFilter->SetPreviewBitmap(TRUE);
03169 
03170         // Export the Preview to the file
03171         BOOL ok = pFilter->DoExport(pOp, ExportFile, pPath, TheDocument);
03172         // If the Preview bitmap failed to export then we still need to clean up
03173 
03174         // Set it back
03175         pBitmapFilter->SetPreviewBitmap(FALSE);
03176         // Set the Preview back to its default setting
03177         PreviewFilter::PreviewBitmapSize = OldPreviewSize;
03178 
03179         // replace the data which was overwritten
03180         INT32 Here = ExportFile->tell();
03181         ExportFile->seek(Start - sizeof(hdr));
03182         ExportFile->write(&hdr, sizeof(hdr));
03183         ExportFile->seek(Here);
03184 
03185         // finish the section
03186         if(!EndSection())
03187             return FALSE;
03188 
03189         return ok;
03190     }
03191 
03192     return TRUE;
03193 }
03194 
03195 /********************************************************************************************
03196 
03197 >   static double CMXExportDC::Round ( double ToRound )
03198 
03199     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
03200     Created:    8/5/00
03201     Inputs:     ToRound - The value to be rounded up.
03202     Returns:    double  - The rounded value.
03203     Purpose:    Rounds a value up or down to the nearest integer.
03204 
03205 ********************************************************************************************/
03206 
03207 double CMXExportDC::Round ( double ToRound )
03208 {
03209     // Add 0.5 to the value, and floor it. This will return the nearest integer.
03210     return floor ( ToRound + 0.5 );
03211 }

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