// $Id: cxfrec.cpp 1688 2006-08-10 12:05:20Z gerry $ // Implementation of the record class of the v2 file format /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE ================================XARAHEADERSTART=========================== Xara LX, a vector drawing and manipulation program. Copyright (C) 1993-2006 Xara Group Ltd. Copyright on certain contributions may be held in joint with their respective authors. See AUTHORS file for details. LICENSE TO USE AND MODIFY SOFTWARE ---------------------------------- This file is part of Xara LX. Xara LX is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. Xara LX and its component source files are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Xara LX (see the file GPL in the root directory of the distribution); if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ADDITIONAL RIGHTS ----------------- Conditional upon your continuing compliance with the GNU General Public License described above, Xara Group Ltd grants to you certain additional rights. The additional rights are to use, modify, and distribute the software together with the wxWidgets library, the wxXtra library, and the "CDraw" library and any other such library that any version of Xara LX relased by Xara Group Ltd requires in order to compile and execute, including the static linking of that library to XaraLX. In the case of the "CDraw" library, you may satisfy obligation under the GNU General Public License to provide source code by providing a binary copy of the library concerned and a copy of the license accompanying it. Nothing in this section restricts any of the rights you have under the GNU General Public License. SCOPE OF LICENSE ---------------- This license applies to this program (XaraLX) and its constituent source files only, and does not necessarily apply to other Xara products which may in part share the same code base, and are subject to their own licensing terms. This license does not apply to files in the wxXtra directory, which are built into a separate library, and are subject to the wxWindows license contained within that directory in the file "WXXTRA-LICENSE". This license does not apply to the binary libraries (if any) within the "libs" directory, which are subject to a separate license contained within that directory in the file "LIBS-LICENSE". ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS ---------------------------------------------- Subject to the terms of the GNU Public License (see above), you are free to do whatever you like with your modifications. However, you may (at your option) wish contribute them to Xara's source tree. You can find details of how to do this at: http://www.xaraxtreme.org/developers/ Prior to contributing your modifications, you will need to complete our contributor agreement. This can be found at: http://www.xaraxtreme.org/developers/contribute/ Please note that Xara will not accept modifications which modify any of the text between the start and end of this header (marked XARAHEADERSTART and XARAHEADEREND). MARKS ----- Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara designs are registered or unregistered trademarks, design-marks, and/or service marks of Xara Group Ltd. All rights in these marks are reserved. Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. http://www.xara.com/ =================================XARAHEADEREND============================ */ #include "camtypes.h" //#include "cxfrec.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "cxfile.h" //#include "cxfdefs.h" - in camtypes.h [AUTOMATICALLY REMOVED] #if !defined(EXCLUDE_FROM_XARLIB) //#include "camfiltr.h" - in camtypes.h [AUTOMATICALLY REMOVED] #endif //#include "ccpanose.h" //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "paths.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "unicdman.h" #include "fttyplis.h" #include "hardwaremanager.h" using namespace oilHardwareManager; // This define has different meaning under Linux #if !defined(__WXMSW__) #undef UNICODE #endif CC_IMPLEMENT_DYNAMIC(CXaraFileRecord,CCObject); CC_IMPLEMENT_DYNAMIC(CamelotFileRecord,CXaraFileRecord); // This will get Camelot to display the filename and linenumber of any memory allocations // that are not released at program exit // Declare smart memory handling in Debug builds #define new CAM_DEBUG_NEW #define RELPATHINTERLEAVE #ifndef SIZEOF_XAR_UTF16 // Unicode characters in the XAR file format are always 16-bit UTF16 #define SIZEOF_XAR_UTF16 2 // UTF16 characters are only 2 byte #endif //------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------- /******************************************************************************************** > CXaraFileRecord::CXaraFileRecord(UINT32 Tag,INT32 Size) Author: Mark_Neves (Xara Group Ltd) Created: 21/5/96 Inputs: Tag - Tag value for the record Size- The exact size of the record in bytes, or CXF_UNKNOWN_SIZE Purpose: Creates a record object. These are used by CXaraFile for reading and writing records. Errors: - SeeAlso: - ********************************************************************************************/ CXaraFileRecord::CXaraFileRecord(UINT32 Tag,INT32 Size) { SetUpVars(Tag,Size); } /******************************************************************************************** > void CXaraFileRecord::SetUpVars(UINT32 ThisTag,INT32 Size) Author: Mark_Neves (Xara Group Ltd) Created: 21/5/96 Inputs: ThisTag - Tag value for the record Size - The exact size of the record in bytes, or CXF_UNKNOWN_SIZE Returns: - Purpose: Sets up the member vars for this record Errors: - SeeAlso: - ********************************************************************************************/ void CXaraFileRecord::SetUpVars(UINT32 ThisTag,INT32 Size) { Tag = ThisTag; KnownSize = Size; SizeIsKnown = (Size != CXF_UNKNOWN_SIZE); RecordNumber= 0; pBuffer = NULL; BufferSize = 0; CurrentPos = 0; Overflow = FALSE; m_pTypeList = NULL; Initialised = FALSE; } /******************************************************************************************** > CXaraFileRecord::~CXaraFileRecord() Author: Mark_Neves (Xara Group Ltd) Created: 21/5/96 Purpose: Default destructor Errors: - SeeAlso: - ********************************************************************************************/ CXaraFileRecord::~CXaraFileRecord() { FreeBuffer(); } /******************************************************************************************** > BOOL CXaraFileRecord::Init(BOOL ZeroMemBlock = FALSE) Author: Mark_Neves (Xara Group Ltd) Created: 21/5/96 Inputs: ZeroMemBlock = If TRUE, any memory allocated for the record is filled with zeros Returns: TRUE if initialised OK FALSE otherwise Purpose: You must call this function before use use any of the Write functions. It initialises the record ready for writing data to (i.e. allocates a buffer) Errors: - SeeAlso: - ********************************************************************************************/ BOOL CXaraFileRecord::Init(BOOL ZeroMemBlock) { if (!Initialised) { ERROR2IF(SizeIsKnown && KnownSize < 0,FALSE,"A -ve size has been given"); ERROR3IF(pBuffer != NULL,"Initialising the record, yet it already has a buffer"); if (SizeIsKnown) Initialised = AllocBuffer(KnownSize); else Initialised = AllocBuffer(CXF_RECORD_CHUNK); } if (Initialised && ZeroMemBlock) { BYTE* pBuf = GetBuffer(); if (pBuf != NULL) { for (UINT32 i=0;i void CXaraFileRecord::DumpTypes(void) Author: Gerry_Iles (Xara Group Ltd) Created: 12/07/97 Purpose: Dumps the type list to TRACE ********************************************************************************************/ void CXaraFileRecord::DumpTypes(void) { TRACEUSER( "Gerry", _T("Tag:% 5d Size:% 6d Data:"), Tag, GetSize()); if (m_pTypeList == NULL || m_pTypeList->GetCount() == 0) { TRACEUSER( "Gerry", _T(" None\n")); return; } BYTE* pPtr = m_pTypeList->GetBuffer(); DWORD Count = m_pTypeList->GetCount(); DWORD Index; for (Index = 0; Index < Count; Index++) { PTSTR pType = NULL; DWORD len = 0; switch (pPtr[Index]) { case FTT_BYTE: pType = _T(" Byte"); break; case FTT_UINT32: pType = _T(" ULong"); break; case FTT_INT32: pType = _T(" Long"); break; case FTT_UINT16: pType = _T(" UInt16"); break; case FTT_INT16: pType = _T(" Int16"); break; case FTT_FLOAT: pType = _T(" Float"); break; case FTT_DOUBLE: pType = _T(" Double"); break; case FTT_WCHAR: pType = _T(" WChar"); break; case FTT_ASCII: pType = _T(" Ascii"); break; case FTT_UNICODE: pType = _T(" Unicode"); break; case FTT_COORD: pType = _T(" Coord"); break; case FTT_INTCOORD: pType = _T(" IntCoord"); break; case FTT_BINHEX: { pType = _T(" Buffer"); len = *((DWORD*)(pPtr+Index+1)); // Get the length (BYTE pointer arithmetic) Index += 4; // and skip it break; } default: pType = _T(" "); break; } if (pType) TRACEUSER("Gerry", pType); if (len != 0) TRACEUSER( "Gerry", _T("(%d)"), len); } TRACEUSER( "Gerry", _T("\n")); } /******************************************************************************************** > BOOL CXaraFileRecord::Reinit(UINT32 ThisTag,INT32 ThisSize) Author: Mark_Neves (Xara Group Ltd) Created: 31/5/96 Inputs: ThisTag = tag for the record ThisSize= The exact size of the record in bytes, or CXF_UNKNOWN_SIZE Returns: TRUE if initialised OK FALSE otherwise Purpose: Allows you to reinit the record with a different record tag & size Errors: - SeeAlso: - ********************************************************************************************/ BOOL CXaraFileRecord::Reinit(UINT32 ThisTag,INT32 ThisSize) { FreeBuffer(); SetUpVars(ThisTag,ThisSize); return Init(); } /******************************************************************************************** > CXaraFileRecord* CXaraFileRecord::GetCopy() Author: Mark_Neves (Xara Group Ltd) Created: 7/6/96 Inputs: - Returns: ptr to a CXaraFileRecord, which is an exact copy Purpose: Copy function Errors: - SeeAlso: - ********************************************************************************************/ CXaraFileRecord* CXaraFileRecord::GetCopy() { BOOL ok = TRUE; UINT32 Size = GetSize(); CXaraFileRecord* pRecord = new CXaraFileRecord(GetTag(),Size); if (pRecord != NULL && Size > 0) { ok = pRecord->Init(); if (ok) { BYTE* pSrcBuf = GetBuffer(); BYTE* pDestBuf = pRecord->GetBuffer(); ok = (pSrcBuf != NULL) && (pDestBuf != NULL); if (ok) memcpy(pDestBuf,pSrcBuf,Size); } } if (pRecord != NULL && RecordNumber > 0) pRecord->SetRecordNumber(RecordNumber); if (!ok && pRecord != NULL) { delete pRecord; pRecord = NULL; } return pRecord; } /******************************************************************************************** > UINT32 CXaraFileRecord::GetSize() Author: Mark_Neves (Xara Group Ltd) Created: 10/6/96 Inputs: - Returns: The size of the record Purpose: Returns the size of the record. If the size of the record is known exactly, it returns the size of the buffer that's been allocated for the record. If it is not known (i.e. when creating a rec of unknown length for writing purposes) the current write position in the buffer is returned. This is the dangerous case, because it is possible that the size returned is not the correct final size. Errors: - SeeAlso: - ********************************************************************************************/ UINT32 CXaraFileRecord::GetSize() { if (SizeIsKnown) return BufferSize; else { //TRACEUSER( "Markn", _T("*+*+* Getting the size of a record, yet don't know it's exact size\n")); return CurrentPos; } } /******************************************************************************************** > void CXaraFileRecord::FreeBuffer() Author: Mark_Neves (Xara Group Ltd) Created: 21/5/96 Inputs: - Returns: - Purpose: Deallocates the associated buffer, if it has one. Can be safely called if the record no longer has a buffer. Errors: - SeeAlso: - ********************************************************************************************/ void CXaraFileRecord::FreeBuffer() { if (pBuffer != NULL) { CCFree(pBuffer); pBuffer = NULL; BufferSize = 0; } if (m_pTypeList != NULL) { delete m_pTypeList; m_pTypeList = NULL; } Initialised = FALSE; } /******************************************************************************************** > BOOL CXaraFileRecord::AllocBuffer(INT32 Size) Author: Mark_Neves (Xara Group Ltd) Created: 21/5/96 Inputs: Size = Size of buffer in bytes Returns: TRUE if ok, FALSE otherwise Purpose: Allocates a buffer of the given size. If Size == 0, no buffer is allocated, but TRUE is still returned. Errors: - SeeAlso: - ********************************************************************************************/ BOOL CXaraFileRecord::AllocBuffer(INT32 Size) { ERROR3IF(Size < 0,"Buffer size is < 0, it's a bit difficult to allocate that many bytes"); FreeBuffer(); if (Size == 0) return TRUE; if (Size > 0) pBuffer = CCMalloc(Size); if (pBuffer != NULL) { BufferSize = Size; return TRUE; } else return FALSE; } /******************************************************************************************** > BOOL CXaraFileRecord::ExtendBuffer(INT32 Size) Author: Mark_Neves (Xara Group Ltd) Created: 21/5/96 Inputs: Size = number of *extra* bytes to add to the buffer Returns: TRUE if ok, FALSE otherwise Purpose: Extends the buffer by the given amount of bytes Errors: - SeeAlso: - ********************************************************************************************/ BOOL CXaraFileRecord::ExtendBuffer(INT32 Size) { ERROR3IF(pBuffer == NULL,"No buffer to extend"); if (pBuffer == NULL) return FALSE; pBuffer = CCRealloc(pBuffer,BufferSize+Size); if (pBuffer != NULL) { BufferSize += Size; return TRUE; } else return FALSE; } /******************************************************************************************** > INT32 CXaraFileRecord::GetRecordNumber() Author: Mark_Neves (Xara Group Ltd) Created: 30/5/96 Inputs: - Returns: The record number of this record Purpose: Returns the record's number. This value is set by a call to SetRecordNumber() Errors: - SeeAlso: - ********************************************************************************************/ INT32 CXaraFileRecord::GetRecordNumber() { ERROR3IF(RecordNumber == 0,"Record number has not been set, or set incorrectly"); return RecordNumber; } /******************************************************************************************** > void CXaraFileRecord::SetRecordNumber(INT32 n) Author: Mark_Neves (Xara Group Ltd) Created: 30/5/96 Inputs: n = The record number of this record (must be > 0) Returns: - Purpose: Sets the record's number. This value is read by a call to GetRecordNumber() Errors: - SeeAlso: - ********************************************************************************************/ void CXaraFileRecord::SetRecordNumber(UINT32 n) { ERROR3IF(n < 1,"Record number is invalid. Must be >= 1"); RecordNumber = n; } /******************************************************************************************** > BOOL CXaraFileRecord::Write(UINT32 n) Author: Mark_Neves (Xara Group Ltd) Created: 21/5/96 Inputs: n = a UINT32 value Returns: TRUE if OK, FALSE otherwise Purpose: Writes the UINT32 to the record's data section Errors: - SeeAlso: - ********************************************************************************************/ BOOL CXaraFileRecord::WriteUINT32(UINT32 n) { ENTERWRITEFUNCTION(FTT_UINT32); n = NativetoLE(n); BOOL ok = WriteBuffer((BYTE*)&n,sizeof(UINT32)); LEAVEWRITEFUNCTION; return (ok); } BOOL CXaraFileRecord::WriteINT32(INT32 n) { ENTERWRITEFUNCTION(FTT_INT32); n = NativetoLE(n); BOOL ok = WriteBuffer((BYTE*)&n,sizeof(INT32)); LEAVEWRITEFUNCTION; return (ok); } BOOL CXaraFileRecord::WriteReference(INT32 n) { ENTERWRITEFUNCTION(FTT_REFERENCE); n = NativetoLE(n); BOOL ok = WriteBuffer((BYTE*)&n,sizeof(INT32)); LEAVEWRITEFUNCTION; return (ok); } BOOL CXaraFileRecord::WriteFLOAT(FLOAT f) { ENTERWRITEFUNCTION(FTT_FLOAT); BOOL ok = WriteBuffer((BYTE*)&f,sizeof(FLOAT)); LEAVEWRITEFUNCTION; return (ok); } BOOL CXaraFileRecord::WriteUINT16(UINT16 f) { ENTERWRITEFUNCTION(FTT_UINT16); f = NativetoLE(f); BOOL ok = WriteBuffer((BYTE*)&f,sizeof(UINT16)); LEAVEWRITEFUNCTION; return (ok); } BOOL CXaraFileRecord::WriteINT16(INT16 f) { ENTERWRITEFUNCTION(FTT_INT16); f = NativetoLE(f); BOOL ok = WriteBuffer((BYTE*)&f,sizeof(INT16)); LEAVEWRITEFUNCTION; return (ok); } BOOL CXaraFileRecord::WriteFIXED16(FIXED16 f) { ENTERWRITEFUNCTION(FTT_INT32); f = NativetoLE(f); BOOL ok = WriteBuffer((BYTE*)&f,sizeof(FIXED16)); LEAVEWRITEFUNCTION; return (ok); } BOOL CXaraFileRecord::WriteANGLE(ANGLE a) { ENTERWRITEFUNCTION(FTT_INT32); a = NativetoLE(a); BOOL ok = WriteBuffer((BYTE*)&a,sizeof(ANGLE)); LEAVEWRITEFUNCTION; return (ok); } BOOL CXaraFileRecord::WriteDOUBLE(double d) { ENTERWRITEFUNCTION(FTT_DOUBLE); BOOL ok = WriteBuffer((BYTE*)&d,sizeof(double)); LEAVEWRITEFUNCTION; return (ok); } BOOL CXaraFileRecord::WriteWCHAR(WCHAR w) { ENTERWRITEFUNCTION(FTT_WCHAR); w = NativeToUTF16(w); w = NativetoLE(w); BOOL ok = WriteBuffer((BYTE*)&w, SIZEOF_XAR_UTF16); //sizeof(WCHAR)); 2-byte UNICODE stored in Xar files LEAVEWRITEFUNCTION; return (ok); } BOOL CXaraFileRecord::WriteWCHARs(const WCHAR* pw, UINT32 Count) { BOOL ok = TRUE; UINT32 i; for (i = 0; ok && i < Count; i++) ok = WriteWCHAR(pw[i]); return (ok); } /******************************************************************************************** > BOOL CXaraFileRecord::WriteCoord(const DocCoord& Coord) Author: Mark_Neves (Xara Group Ltd) Created: 31/5/96 Inputs: Coord = a coord Returns: TRUE if written successfully FALSE otherwise Purpose: Writes out the coord Errors: - SeeAlso: - ********************************************************************************************/ BOOL CXaraFileRecord::WriteCoord(const DocCoord& Coord) { ENTERWRITEFUNCTION(FTT_COORD); BOOL ok = WriteINT32(Coord.x) && WriteINT32(Coord.y); LEAVEWRITEFUNCTION; return (ok); } BOOL CXaraFileRecord::WriteCoordTrans(const DocCoord& Coord,INT32 dx,INT32 dy) { ENTERWRITEFUNCTION(FTT_COORD); BOOL ok = WriteINT32(Coord.x + dx) && WriteINT32(Coord.y + dy); LEAVEWRITEFUNCTION; return (ok); } /******************************************************************************************** > virtual BOOL CXaraFileRecord::WriteCoordInterleaved(const DocCoord& Coord) Author: Mark_Neves (Xara Group Ltd) Created: 27/8/96 Inputs: Coord = coord to write to the record Returns: TRUE if OK, FALSE otherwise Purpose: Writes out the coord to the record, in an interleaved format. The Coord is translated to the origin set up in the filter that was used to construct this object This version interleaves the bytes of the X & Y components, to try and maximise the run of common bytes, in order to improve the zlib compression. It writes out the top byte of x, then top byte of y, then next byte of x, then next byte of y, and so on. Errors: - SeeAlso: - ********************************************************************************************/ BOOL CXaraFileRecord::WriteCoordInterleaved(const DocCoord& Coord) { ENTERWRITEFUNCTION(FTT_INTCOORD); BOOL ok = WriteCoordTransInterleaved(Coord,0,0); LEAVEWRITEFUNCTION; return (ok); } BOOL CXaraFileRecord::WriteCoordTransInterleaved(const DocCoord& Coord,INT32 dx,INT32 dy) { ENTERWRITEFUNCTION(FTT_INTCOORD); INT32 x = Coord.x + dx; INT32 y = Coord.y + dy; BOOL ok = TRUE; if (ok) ok = WriteBYTE(BYTE((x >> 24) & 0xff)); if (ok) ok = WriteBYTE(BYTE((y >> 24) & 0xff)); if (ok) ok = WriteBYTE(BYTE((x >> 16) & 0xff)); if (ok) ok = WriteBYTE(BYTE((y >> 16) & 0xff)); if (ok) ok = WriteBYTE(BYTE((x >> 8) & 0xff)); if (ok) ok = WriteBYTE(BYTE((y >> 8) & 0xff)); if (ok) ok = WriteBYTE(BYTE((x >> 0) & 0xff)); if (ok) ok = WriteBYTE(BYTE((y >> 0) & 0xff)); LEAVEWRITEFUNCTION; return ok; } /******************************************************************************************** > BOOL CXaraFileRecord::WriteBuffer(BYTE* pBuf,UINT32 BufSize) Author: Mark_Neves (Xara Group Ltd) Created: 21/5/96 Inputs: pBuf = ptr to a BYTE buffer BufSize = the number of bytes in the buffer Returns: TRUE if OK, FALSE otherwise Purpose: Writes out a buffer of BYTEs to the record's data section. Errors: - SeeAlso: - ********************************************************************************************/ BOOL CXaraFileRecord::WriteBuffer(BYTE* pBuf,size_t BufSize) { ERROR3IF(pBuf == NULL,"NULL pBuf param"); BOOL ok = (pBuf != NULL); ENTERWRITEFUNCTION(FTT_BINHEX); STORELENGTH( DWORD(BufSize) ); for (UINT32 i=0;i BOOL CXaraFileRecord::WriteCCPanose(const CCPanose &MyCCPanose) Author: Andy_Hayward (Xara Group Ltd) Created: 09/08/96 Inputs: Panose - CCPanose structure to write out Returns: TRUE if successful, FALSE otherwise Purpose: Writes a CCPanose structure to th file ********************************************************************************************/ BOOL CXaraFileRecord::WriteCCPanose(const CCPanose &MyCCPanose) { BOOL ok = TRUE; PORTNOTE("other","Removed CCPanose usage - write NULL") #ifndef EXCLUDE_FROM_XARALX if (ok) ok = WriteBYTE(MyCCPanose.GetFamilyType()); if (ok) ok = WriteBYTE(MyCCPanose.GetSerifStyle()); if (ok) ok = WriteBYTE(MyCCPanose.GetWeight()); if (ok) ok = WriteBYTE(MyCCPanose.GetProportion()); if (ok) ok = WriteBYTE(MyCCPanose.GetContrast()); if (ok) ok = WriteBYTE(MyCCPanose.GetStrokeVariation()); if (ok) ok = WriteBYTE(MyCCPanose.GetArmStyle()); if (ok) ok = WriteBYTE(MyCCPanose.GetLetterform()); if (ok) ok = WriteBYTE(MyCCPanose.GetMidline()); if (ok) ok = WriteBYTE(MyCCPanose.GetXHeight()); #else if (ok) ok = WriteBYTE( 0 ); if (ok) ok = WriteBYTE( 0 ); if (ok) ok = WriteBYTE( 0 ); if (ok) ok = WriteBYTE( 0 ); if (ok) ok = WriteBYTE( 0 ); if (ok) ok = WriteBYTE( 0 ); if (ok) ok = WriteBYTE( 0 ); if (ok) ok = WriteBYTE( 0 ); if (ok) ok = WriteBYTE( 0 ); if (ok) ok = WriteBYTE( 0 ); #endif return ok; } /******************************************************************************************** > BOOL CXaraFileRecord::WriteUnicode(const TCHAR* pStr) Author: Mark_Neves (Xara Group Ltd) Created: 23/5/96 Inputs: pStr = ptr to zero-terminated string Returns: TRUE if written successfully FALSE otherwise Purpose: Writes out the string as a Unicode string Errors: - SeeAlso: - ********************************************************************************************/ BOOL CXaraFileRecord::WriteUnicode(const TCHAR* pStr) { ERROR3IF(pStr == NULL,"NULL pStr"); if (pStr == NULL) return FALSE; ENTERWRITEFUNCTION(FTT_UNICODE); BOOL ok = TRUE; #ifdef _UNICODE // We must cope with byte-order differences between native storage and XAR file storage: // Native may be big-endian or little-endian, XAR is always little-endian // Native WCHAR may be 16 or 32 bits, XAR is always 16 bits // These differences are handled in WriteWCHAR WCHAR c = 0; INT32 i = 0; do { c = pStr[i++]; ok = WriteWCHAR(c); // Read two bytes into the WCHAR buffer if (!ok) c = 0; // If the read failed then write a terminator } while (c!=0);// Until end of string or no longer OK to write #else // pStr points to an ASCII or DBCS string, and we want it written as a Unicode string // Write out each char separately, converting it to the correct Unicode value // using TextManager::MultiByteToUnicode() // skip along the string, saving each character in turn TCHAR* pCurrentChar = pStr; while (*pCurrentChar!=0 && ok) { // Convert the char to Unicode UINT32 mc = 0; if (UnicodeManager::IsDBCSOS() && UnicodeManager::IsDBCSLeadByte(*pCurrentChar)) { mc = UnicodeManager::ComposeMultiBytes(*pCurrentChar, *(pCurrentChar+1)); pCurrentChar += 2; } else { mc = *pCurrentChar; pCurrentChar += 1; } WCHAR wc = UnicodeManager::MultiByteToUnicode(mc); ok = WriteBuffer( (BYTE*)&wc, sizeof(WCHAR) ); } // Now write a zero terminator if (ok) { WCHAR wc = 0; ok = WriteBuffer( (BYTE*)&wc, sizeof(WCHAR) ); } #endif // _UNICODE LEAVEWRITEFUNCTION; return ok; } /******************************************************************************************** > BOOL CXaraFileRecord::WriteASCII(const TCHAR* pStr) Author: Mark_Neves (Xara Group Ltd) Created: 23/5/96 Inputs: pStr = ptr to zero-terminated string Returns: TRUE if written successfully FALSE otherwise Purpose: Writes out the string as an ASCII string Errors: - SeeAlso: - ********************************************************************************************/ BOOL CXaraFileRecord::WriteASCII(const TCHAR* pStr) { ERROR3IF(pStr == NULL,"NULL pStr"); if (pStr == NULL) return FALSE; ENTERWRITEFUNCTION(FTT_ASCII); size_t len = camStrlen(pStr); BOOL ok= TRUE; #ifdef _UNICODE // Writing a Unicode string at pStr as an ASCII string // Just write out the first byte of each unicode char. for (size_t i=0;ok && i<=len;i++) { PORTNOTE( "record", "UNICODE characters that don't fit into 1 mb character need better handling" ) char acTmp[MB_CUR_MAX]; if( 1 == wctomb( acTmp, pStr[i] ) ) ok = WriteBYTE( acTmp[0] ); else ok = WriteBYTE( '.' ); } LEAVEWRITEFUNCTION; return ok; #else // pStr points at an ASCII string, so write it out ok = WriteBuffer((BYTE*)pStr,len+1); LEAVEWRITEFUNCTION; return (ok); #endif } /******************************************************************************************** > BOOL CXaraFileRecord::WriteBSTR(_bstr_t bstr) Author: Phil_Martin (Xara Group Ltd) Created: 29/01/2004 Inputs: bstr - ptr to zero-terminated WCHAR string Returns: TRUE if written successfully FALSE otherwise Purpose: Writes out the string as a Unicode string Errors: - SeeAlso: - ********************************************************************************************/ /*BOOL CXaraFileRecord::WriteBSTR(_bstr_t bstr) { ERROR3IF((wchar_t*)bstr == NULL, "NULL bstr"); if ((wchar_t*)bstr == NULL) return FALSE; ENTERWRITEFUNCTION(FTT_UNICODE); BOOL ok = WriteBuffer((unsigned char*)((wchar_t*)bstr), bstr.length()*sizeof(WCHAR)); ok = ok && WriteWCHAR(0); // Zero terminate to be consistent with FTT_UNICODE LEAVEWRITEFUNCTION; return (ok); } */ /******************************************************************************************** > BOOL CXaraFileRecord::WriteUTF16STR(const StringVar& pvstr) Author: Phil_Martin (Xara Group Ltd) Created: 28/Mar/2006 Inputs: pvstr - pointer to StringVar Outputs: - Returns: TRUE if OK, FALSE otherwise Purpose: Writes a variable length string as a stream of UTF16 unicode characters Errors: - SeeAlso: StartRecord(), EndRecord() ********************************************************************************************/ BOOL CXaraFileRecord::WriteUTF16STR(const StringVar& pvstr) { #ifdef _UNICODE ENTERWRITEFUNCTION(FTT_UNICODE); BOOL ok = TRUE; WCHAR c = 0; INT32 i = 0; do { c = pvstr.CharAt(i++); ok = WriteWCHAR(c); // Read two bytes into the WCHAR buffer if (!ok) c = 0; // If the read failed then write a terminator } while (c!=0);// Until end of string or no longer OK to write LEAVEWRITEFUNCTION; return ok; // If we terminated due to Read failure tell the caller #else ERROR3("StringVar only holds UNICODE data in UNICODE builds"); return FALSE; #endif } /******************************************************************************************** > BOOL CXaraFileRecord::WriteBYTE(BYTE b) Author: Mark_Neves (Xara Group Ltd) Created: 21/5/96 Inputs: b = a BYTE Returns: TRUE if OK, FALSE otherwise Purpose: Writes a BYTE to the record's data section Errors: - SeeAlso: StartRecord(), EndRecord() ********************************************************************************************/ BOOL CXaraFileRecord::WriteBYTE(BYTE b) { ERROR3IF(!Initialised,"Writing to an uninitialised record"); if (Overflow) return FALSE; ENTERWRITEFUNCTION(FTT_BYTE); BOOL ok = TRUE; if (CurrentPos >= BufferSize) { if (SizeIsKnown) { ERROR3("Record Write Overflow"); Overflow = TRUE; LEAVEWRITEFUNCTION; return FALSE; } else { while (ok && CurrentPos >= BufferSize) ok = ExtendBuffer(CXF_RECORD_CHUNK); } } if (ok) { BYTE* pBuf = (BYTE*)pBuffer; if (CurrentPos < BufferSize) pBuf[CurrentPos++] = b; } LEAVEWRITEFUNCTION; return ok; } /******************************************************************************************** > void CXaraFileRecord::ResetReadPos() Author: Mark_Neves (Xara Group Ltd) Created: 12/6/96 Inputs: - Returns: - Purpose: Resets the read position, so that the next Read() func call starts from the beginning of the data section. Errors: - SeeAlso: StartRecord(), EndRecord() ********************************************************************************************/ void CXaraFileRecord::ResetReadPos() { CurrentPos = 0; } /******************************************************************************************** > BOOL CXaraFileRecord::ReadBYTE(BYTE* pBYTE) Author: Mark_Neves (Xara Group Ltd) Created: 21/5/96 Inputs: pBYTE = ptr to place to stick data Returns: TRUE if OK, FALSE otherwise Purpose: Reads a BYTE from the record's data section Errors: - SeeAlso: StartRecord(), EndRecord() ********************************************************************************************/ BOOL CXaraFileRecord::ReadBYTE(BYTE* pBYTE) { ERROR3IF(pBYTE == NULL,"pBYTE is NULL"); if (pBYTE == NULL) return FALSE; ERROR3IF(CurrentPos >= BufferSize,"No more data in record"); if (CurrentPos >= BufferSize) return FALSE; BYTE* pBuf = (BYTE*)pBuffer; *pBYTE = pBuf[CurrentPos++]; return TRUE; } /******************************************************************************************** > BOOL CXaraFileRecord::ReadBYTEtoBOOL(BOOL* pbool) Author: Phil_Martin (Xara Group Ltd) Created: 07/Feb/2006 Inputs: pbool = ptr to place to stick data Returns: TRUE if OK, FALSE otherwise Purpose: Reads a BYTE from the record's data section Errors: - SeeAlso: StartRecord(), EndRecord() ********************************************************************************************/ BOOL CXaraFileRecord::ReadBYTEtoBOOL(BOOL* pbool) { ERROR3IF(pbool == NULL,"pbool is NULL"); if (pbool == NULL) return FALSE; ERROR3IF(CurrentPos >= BufferSize,"No more data in record"); if (CurrentPos >= BufferSize) return FALSE; BYTE* pBuf = (BYTE*)pBuffer; *pbool = (BOOL)pBuf[CurrentPos++]; return TRUE; } /******************************************************************************************** > BOOL CXaraFileRecord::ReadBYTEnoError(BOOL* pBYTE) Author: Karim_MacDonald (Xara Group Ltd) Created: 05/02/2001 Returns: TRUE if successfully read a BYTE, FALSE if we didn't read a BYTE for any reason. Purpose: Dangerous, no-error version of CXaraFileRecord::ReadBYTE(). !!! DO NOT USE UNLESS YOU ***KNOW EXACTLY*** WHAT YOU ARE DOING !!! See Also: ReadBuffernoError() . ********************************************************************************************/ BOOL CXaraFileRecord::ReadBYTEnoError(BYTE* pBYTE) { ERROR3IF(pBYTE == NULL, "pBYTE is NULL"); if (pBYTE == NULL) return FALSE; // if we run out of buffer, fail quietly (no error!). if (CurrentPos >= BufferSize) return FALSE; BYTE* pBuf = (BYTE*)pBuffer; *pBYTE = pBuf[CurrentPos++]; return TRUE; } BOOL CXaraFileRecord::ReadBuffer(BYTE* pBuf,UINT32 BufSize) { ERROR3IF(pBuf == NULL,"pBuf is NULL"); if (pBuf == NULL) return FALSE; BOOL ok = TRUE; for (UINT32 i=0;ok && i < BufSize;i++) ok = ReadBYTE(pBuf+i); return ok; } /* The following function allows us to still open up old CX2/CX3 files that do NOT contain profiling data. This was necessary since the standard ReadBuffer will error on such a case. Obviously it is only CORRECT to call this function when we are trying to retain backward compatibility within CX3. */ BOOL CXaraFileRecord::ReadBuffernoError(BYTE* pBuf,UINT32 BufSize) { ERROR3IF(pBuf == NULL,"pBuf is NULL"); if (pBuf == NULL) return FALSE; BOOL ok = TRUE; if (CurrentPos >= BufferSize) { pBuf = NULL; return ok; } else { for (UINT32 i=0;ok && i < BufSize;i++) { ok = ReadBYTE(pBuf+i); } } return ok; } BOOL CXaraFileRecord::ReadUINT32(UINT32* pUINT32) { // return ReadBuffer((BYTE*)pUINT32,sizeof(UINT32)); BOOL ok = ReadBuffer((BYTE*)pUINT32,sizeof(UINT32)); *pUINT32 = LEtoNative(*pUINT32); return ok; } BOOL CXaraFileRecord::ReadINT32(INT32* pINT32) { // return ReadBuffer((BYTE*)pINT32,sizeof(INT32)); BOOL ok = ReadBuffer((BYTE*)pINT32,sizeof(INT32)); *pINT32 = LEtoNative(*pINT32); return ok; } BOOL CXaraFileRecord::ReadINT32noError(INT32* pINT32) { // return ReadBuffernoError((BYTE*)pINT32,sizeof(INT32)); BOOL ok = ReadBuffernoError((BYTE*)pINT32,sizeof(INT32)); *pINT32 = LEtoNative(*pINT32); return ok; } BOOL CXaraFileRecord::ReadFIXED16(FIXED16* pn) { BOOL ok = ReadBuffer((BYTE*)pn,sizeof(FIXED16)); *pn = LEtoNative(*pn); return ok; } BOOL CXaraFileRecord::ReadANGLE(ANGLE *pa) { BOOL ok = ReadBuffer((BYTE*)pa,sizeof(ANGLE)); *pa = LEtoNative(*pa); return ok; } BOOL CXaraFileRecord::ReadUINT16(UINT16* pn) { BOOL ok = ReadBuffer((BYTE*)pn,sizeof(UINT16)); *pn = LEtoNative(*pn); return ok; } BOOL CXaraFileRecord::ReadINT16(INT16* pn) { BOOL ok = ReadBuffer((BYTE*)pn,sizeof(INT16)); *pn = LEtoNative(*pn); return ok; } BOOL CXaraFileRecord::ReadFLOAT(FLOAT* pf) { BOOL ok = ReadBuffer((BYTE*)pf,sizeof(FLOAT)); *pf = LEtoNative(*pf); return ok; } BOOL CXaraFileRecord::ReadDOUBLE(double* pd) { BOOL ok = ReadBuffer((BYTE*)pd,sizeof(double)); *pd = LEtoNative(*pd); return ok; } BOOL CXaraFileRecord::ReadDOUBLEnoError(double* pd) { BOOL ok = ReadBuffernoError((BYTE*)pd,sizeof(double)); *pd = LEtoNative(*pd); return ok; } BOOL CXaraFileRecord::ReadWCHAR(WCHAR *pw) { *pw = 0; BOOL ok = ReadBuffer((BYTE*)pw, SIZEOF_XAR_UTF16); //sizeof(WCHAR)); 2-byte UNICODE stored in Xar files *pw = LEtoNative(*pw); *pw = UTF16ToNative(*pw); return ok; } BOOL CXaraFileRecord::ReadCoord(DocCoord* pCoord) { if (pCoord != NULL) return ReadINT32(&(pCoord->x)) && ReadINT32(&(pCoord->y)); else return FALSE; } BOOL CXaraFileRecord::ReadCoordTrans(DocCoord* pCoord,INT32 dx,INT32 dy) { if (pCoord != NULL) { if (ReadINT32(&(pCoord->x)) && ReadINT32(&(pCoord->y))) { pCoord->x += dx; pCoord->y += dy; return TRUE; } } return FALSE; } BOOL CXaraFileRecord::ReadCoordInterleaved(DocCoord* pCoord) { return ReadCoordTransInterleaved(pCoord,0,0); } BOOL CXaraFileRecord::ReadCoordTransInterleaved(DocCoord* pCoord,INT32 dx,INT32 dy) { BOOL ok = TRUE; if (pCoord != NULL) { BYTE b; INT32 x = 0; INT32 y = 0; if (ok) { ok = ReadBYTE(&b); x += (b << 24); } if (ok) { ok = ReadBYTE(&b); y += (b << 24); } if (ok) { ok = ReadBYTE(&b); x += (b << 16); } if (ok) { ok = ReadBYTE(&b); y += (b << 16); } if (ok) { ok = ReadBYTE(&b); x += (b << 8); } if (ok) { ok = ReadBYTE(&b); y += (b << 8); } if (ok) { ok = ReadBYTE(&b); x += (b << 0); } if (ok) { ok = ReadBYTE(&b); y += (b << 0); } pCoord->x = x + dx; pCoord->y = y + dy; } return ok; } BOOL CXaraFileRecord::ReadCCPanose(CCPanose *pMyCCPanose) { BOOL ok = TRUE; BYTE value; PORTNOTE("other","Removed CCPanose usage - read to NULL") #ifndef EXCLUDE_FROM_XARALX if (ok) ok = pMyCCPanose->SetFamilyType(value); if (ok) ok = pMyCCPanose->SetSerifStyle(value); if (ok) ok = pMyCCPanose->SetWeight(value); if (ok) ok = pMyCCPanose->SetProportion(value); if (ok) ok = pMyCCPanose->SetContrast(value); if (ok) ok = pMyCCPanose->SetStrokeVariation(value); if (ok) ok = pMyCCPanose->SetArmStyle(value); if (ok) ok = pMyCCPanose->SetLetterform(value); if (ok) ok = pMyCCPanose->SetMidline(value); if (ok) ok = pMyCCPanose->SetXHeight(value); #else if (ok) ok = ReadBYTE(&value); // pMyCCPanose->SetFamilyType(value); if (ok) ok = ReadBYTE(&value); // pMyCCPanose->SetSerifStyle(value); if (ok) ok = ReadBYTE(&value); // pMyCCPanose->SetWeight(value); if (ok) ok = ReadBYTE(&value); // pMyCCPanose->SetProportion(value); if (ok) ok = ReadBYTE(&value); // pMyCCPanose->SetContrast(value); if (ok) ok = ReadBYTE(&value); // pMyCCPanose->SetStrokeVariation(value); if (ok) ok = ReadBYTE(&value); // pMyCCPanose->SetArmStyle(value); if (ok) ok = ReadBYTE(&value); // pMyCCPanose->SetLetterform(value); if (ok) ok = ReadBYTE(&value); // pMyCCPanose->SetMidline(value); if (ok) ok = ReadBYTE(&value); // pMyCCPanose->SetXHeight(value); #endif return ok; } BOOL CXaraFileRecord::ReadUnicode(StringBase* pStr) { // ASUMPTION!!!! // This function assumes the pStr->MaxLength() will return the max buffer size -1, // i.e. a value is returned that excludes room for a zero-terminated character. // // As the func that does all the hard work takes a TCHAR*, we need to pass in the total buffer // size, otherwise it will fail for strings that exactly fit into the StringBase object. // // This is why MaxLength()+1 is passed in. if (pStr != NULL) return ReadUnicode((TCHAR*)(*pStr),pStr->MaxLength()+1); return FALSE; } BOOL CXaraFileRecord::ReadUnicode(TCHAR* pStr,UINT32 MaxChars) { BOOL ok = TRUE; BYTE* pBuf = (BYTE*)pStr; #ifdef _UNICODE BYTE b1 = 1; BYTE b2 = 1; BYTE* pBufEnd = pBuf + ( MaxChars * sizeof(wchar_t) ); while (ok && !(b1 == 0 && b2 == 0)) { ok = ReadBYTE( &b1 ) && ReadBYTE( &b2 ); if (ok) ok = (pBuf < pBufEnd); if (ok) *pBuf++ = b1; if (ok) ok = (pBuf < pBufEnd); if (ok) *pBuf++ = b2; // Yick, Linux has 4 byte unicdoe chars if (sizeof(TCHAR) == 4) { *pBuf++ = '\0'; *pBuf++ = '\0'; } } #else BYTE* pBufEnd = pBuf+MaxChars; WCHAR wc = 1; BYTE* pwcBuf = (BYTE*)&wc; while (ok && wc != 0) { // Read in the two bytes that make up the Unicode value, and stuff them into 'wc' ok = ReadBYTE(pwcBuf) && ReadBYTE(pwcBuf+1); // Check for buffer overflow if (ok) ok = (pBuf < pBufEnd); if (ok) { // Convert to an ASCII or DBCS if (UnicodeManager::IsDBCSOS()) { UINT32 AsciiCode = UnicodeManager::UnicodeToMultiByte(wc); BYTE LeadByte = 0; BYTE TrailByte = 0; UnicodeManager::DecomposeMultiBytes(AsciiCode, &LeadByte, &TrailByte); if (LeadByte == 0) *pBuf++ = TrailByte; else { if (UnicodeManager::IsDBCSLeadByte(LeadByte)) { ok = (pBuf < pBufEnd-1); if (ok) { *pBuf++ = LeadByte; *pBuf++ = TrailByte; } } else *pBuf++ = TrailByte; } } else { UINT32 AsciiCode = UnicodeManager::UnicodeToMultiByte(wc); *pBuf++ = BYTE(AsciiCode & 0xff); } } } #endif // _UNICODE return ok; } BOOL CXaraFileRecord::ReadASCII(TCHAR* pStr,UINT32 MaxChars) { BOOL ok = TRUE; BYTE b = 1; TCHAR* pBuf = pStr; TCHAR* pBufEnd = pBuf + MaxChars; while (ok && b != 0) { ok = ReadBYTE(&b); if (ok) ok = (pBuf < pBufEnd); if (ok) *pBuf++ = b; } return ok; } #ifdef _UNICODE BOOL CXaraFileRecord::ReadASCII( char *pStr, UINT32 MaxChars ) { BOOL ok = TRUE; BYTE b=1; BYTE* pBuf = (BYTE*)pStr; BYTE* pBufEnd = pBuf+MaxChars; while (ok && b != 0) { ok = ReadBYTE(&b); if (ok) ok = (pBuf < pBufEnd); if (ok) *pBuf++ = b; } return ok; } #endif /******************************************************************************************** > BOOL CXaraFileRecord::ReadBSTR(_bstr_t* pbstr, UINT32 MaxChars) Author: Phil_Martin (Xara Group Ltd) Created: 29/01/2004 Inputs: bstr - pointer to WCHAR buffer MaxChars - size of buffer in WCHARS Returns: TRUE if OK, FALSE otherwise Purpose: Reads a BSTR from the record's data section (i.e. a run of WCHARs) Errors: - SeeAlso: StartRecord(), EndRecord() ********************************************************************************************/ /*BOOL CXaraFileRecord::ReadBSTR(_bstr_t* pbstr, UINT32 MaxChars) { BOOL ok = TRUE; WCHAR c[2] = {0, 0}; *pbstr = ""; do { ok = ReadWCHAR(c); // Read two bytes into the WCHAR buffer if (!ok) c[0]=0; // If the read failed then write a terminator *pbstr += c; // Add the character to the BSTR } while (c[0]!=0 && pbstr->length() BOOL CXaraFileRecord::ReadUTF16STR(StringVar* pvstr, UINT32 MaxChars) Author: Phil_Martin (Xara Group Ltd) Created: 31/Jan/2006 Inputs: vstr - pointer to StringVar MaxChars - size of buffer in WCHARS Returns: TRUE if OK, FALSE otherwise Purpose: Reads a BSTR from the record's data section (i.e. a run of WCHARs) Errors: - SeeAlso: StartRecord(), EndRecord() ********************************************************************************************/ BOOL CXaraFileRecord::ReadUTF16STR(StringVar* pvstr, UINT32 MaxChars) { #ifdef _UNICODE BOOL ok = TRUE; pvstr->Empty(); WCHAR c = 0; do { ok = ReadWCHAR(&c); // Read two bytes into the WCHAR buffer if (!ok) c = 0; // If the read failed then write a terminator *pvstr += c; // Add the character to the VSTR } while (c!=0 && ((UINT32)(pvstr->Length()))GetNumCoords(); // Write out num coords BOOL ok = WriteINT32(NumCoords); // Write out path verbs if (ok) { PathVerb* pVerb = pPath->GetVerbArray(); if (pVerb != NULL) { for (INT32 i=0;ok && i < NumCoords;i++) ok = WriteBYTE(pVerb[i]); } else ok = FALSE; } // Write out coord array if (ok) { DocCoord* pCoord = pPath->GetCoordArray(); if (pCoord != NULL) { for (INT32 i=0;ok && i < NumCoords;i++) ok = WriteCoordTrans(pCoord[i],dx,dy); } else ok = FALSE; } return ok; } BOOL CXaraFileRecord::ReadPath(Path* pPath) { return ReadPathTrans(pPath,0,0); } BOOL CXaraFileRecord::ReadPathTrans(Path* pPath,INT32 dx,INT32 dy) { if (pPath == NULL) return FALSE; INT32 NumCoords; if (!ReadINT32(&NumCoords)) return FALSE; if (NumCoords < 0) return TRUE; BOOL ok = pPath->ClearPath(FALSE) && pPath->MakeSpaceAtEnd(NumCoords); if (ok) { INT32 i; PathVerb* pVerb = pPath->GetVerbArray(); ok = (pVerb != NULL); for (i=0;ok && iGetCoordArray(); if (ok) ok = (pCoord != NULL); for (i=0;ok && iExternalArraysAdded(NumCoords); } return ok; } BOOL CXaraFileRecord::WritePathRelative(Path* pPath) { return WritePathRelativeTrans(pPath,0,0); } BOOL CXaraFileRecord::WritePathRelativeTrans(Path* pPath,INT32 dx,INT32 dy) { if (pPath == NULL) return FALSE; BOOL ok = TRUE; INT32 NumCoords = pPath->GetNumCoords(); #ifndef RELPATHINTERLEAVE // Write out path verbs if (ok) { PathVerb* pVerb = pPath->GetVerbArray(); if (pVerb != NULL) { for (INT32 i=0;ok && i < NumCoords;i++) ok = WriteBYTE(pVerb[i]); } else ok = FALSE; } // Write out coord array if (ok) { DocCoord* pCoord = pPath->GetCoordArray(); if (pCoord != NULL) { ok = WriteCoordTrans(pCoord[0],dx,dy); for (INT32 i=1;ok && i < NumCoords;i++) { INT32 RelX = pCoord[i-1].x - pCoord[i].x; INT32 RelY = pCoord[i-1].y - pCoord[i].y; ok = WriteINT32(RelX); if (ok) ok = WriteINT32(RelY); } } else ok = FALSE; } #else if (ok) { PathVerb* pVerb = pPath->GetVerbArray(); DocCoord* pCoord = pPath->GetCoordArray(); if (pVerb != NULL && pCoord != NULL && NumCoords > 0) { DocCoord TempCoord; ok = WriteBYTE(pVerb[0]); if (ok) ok = WriteCoordTransInterleaved(pCoord[0],dx,dy); for (INT32 i=1;ok && i < NumCoords;i++) { ok = WriteBYTE(pVerb[i]); TempCoord.x = pCoord[i-1].x - pCoord[i].x; TempCoord.y = pCoord[i-1].y - pCoord[i].y; if (ok) ok = WriteCoordTransInterleaved(TempCoord,0,0); } } else ok = FALSE; } #endif return ok; } BOOL CXaraFileRecord::ReadPathRelative(Path* pPath) { return ReadPathRelativeTrans(pPath,0,0); } BOOL CXaraFileRecord::ReadPathRelativeTrans(Path* pPath,INT32 dx,INT32 dy) { if (pPath == NULL) return FALSE; INT32 NumCoords = INT32(GetSize())/(sizeof(BYTE)+sizeof(INT32)+sizeof(INT32)); if (NumCoords < 0) return TRUE; BOOL ok = pPath->ClearPath(FALSE) && pPath->MakeSpaceAtEnd(NumCoords); #ifndef RELPATHINTERLEAVE if (ok) { INT32 i; PathVerb* pVerb = pPath->GetVerbArray(); ok = (pVerb != NULL); for (i=0;ok && iGetCoordArray(); if (ok) ok = (pCoord != NULL); if (ok) ok = ReadCoordTrans(pCoord,dx,dy); if (ok) { INT32 RelX,RelY; for (i=1;ok && iGetVerbArray(); DocCoord* pCoord = pPath->GetCoordArray(); ok = (pVerb != NULL) && (pCoord != NULL); if (ok) ok = ReadBYTE(pVerb); if (ok) ok = ReadCoordTransInterleaved(pCoord,dx,dy); if (ok) { DocCoord TempCoord; for (INT32 i=1;ok && iExternalArraysAdded(NumCoords); return ok; } BOOL CXaraFileRecord::WriteMatrix(const Matrix & m) { return WriteMatrixTrans(m,0,0); } BOOL CXaraFileRecord::WriteMatrixTrans(const Matrix & m,INT32 dx,INT32 dy) { BOOL ok = TRUE; FIXED16 abcd[4]; // matrix components INT32 ef[2]; // translation m.GetComponents(&abcd[0], &ef[0]); if (ok) ok = WriteFIXED16(abcd[0]); if (ok) ok = WriteFIXED16(abcd[1]); if (ok) ok = WriteFIXED16(abcd[2]); if (ok) ok = WriteFIXED16(abcd[3]); if (ok) ok = WriteINT32(ef[0]+dx); if (ok) ok = WriteINT32(ef[1]+dy); return ok; } BOOL CXaraFileRecord::ReadMatrix(Matrix *pMatrix) { return ReadMatrixTrans(pMatrix,0,0); } BOOL CXaraFileRecord::ReadMatrixTrans(Matrix *pMatrix,INT32 dx,INT32 dy) { BOOL ok = TRUE; FIXED16 a; FIXED16 b; FIXED16 c; FIXED16 d; INT32 e; INT32 f; if (ok) ok = ReadFIXED16(&a); if (ok) ok = ReadFIXED16(&b); if (ok) ok = ReadFIXED16(&c); if (ok) ok = ReadFIXED16(&d); if (ok) ok = ReadINT32(&e); if (ok) ok = ReadINT32(&f); (*pMatrix) = Matrix(a,b,c,d,e+dx,f+dy); return ok; } /******************************************************************************************** > virtual BOOL CXaraFileRecord::WriteXOrd(INT32 XOrdinate) Author: Mark_Neves (Xara Group Ltd) Created: 8/8/96 Inputs: XOrdinate = x ordinate to write to the record Returns: TRUE if OK, FALSE otherwise Purpose: Writes out the x ordinate to the record. Base class performs the same function as WriteINT32() Errors: - SeeAlso: - ********************************************************************************************/ BOOL CXaraFileRecord::WriteXOrd(INT32 XOrdinate) { return WriteINT32(XOrdinate); } BOOL CXaraFileRecord::WriteYOrd(INT32 YOrdinate) { return WriteINT32(YOrdinate); } /******************************************************************************************** > virtual BOOL CXaraFileRecord::ReadXOrd(INT32* pXOrdinate) Author: Mark_Neves (Xara Group Ltd) Created: 8/8/96 Inputs: pXOrdinate = ptr place to stick the x ordinate read in Returns: TRUE if OK, FALSE otherwise Purpose: Reads the x ordinate from the record. Base class performs the same function as ReadINT32() Errors: - SeeAlso: - ********************************************************************************************/ BOOL CXaraFileRecord::ReadXOrd(INT32* pXOrdinate) { return ReadINT32(pXOrdinate); } BOOL CXaraFileRecord::ReadYOrd(INT32* pYOrdinate) { return ReadINT32(pYOrdinate); } //------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------- /******************************************************************************************** > CamelotFileRecord::CamelotFileRecord(BaseCamelotFilter* pFilter,UINT32 Tag,INT32 Size) Author: Mark_Neves (Xara Group Ltd) Created: 24/6/96 Inputs: pFilter - ptr to the filter doing the importing/exporting Tag - Tag value for the record Size - The exact size of the record in bytes, or CXF_UNKNOWN_SIZE Purpose: Creates a record object. These are used by CXaraFile for reading and writing records. This derived version sets up the coord origin using the supplied BaseCamelotFilter. This origin is used when writing & reading coords. Errors: - SeeAlso: - ********************************************************************************************/ CamelotFileRecord::CamelotFileRecord(BaseCamelotFilter* pFilter,UINT32 Tag,INT32 Size) : CXaraFileRecord(Tag,Size) { #if !defined(EXCLUDE_FROM_XARLIB) CoordOrigin = DocCoord(0,0); if (pFilter != NULL) CoordOrigin = pFilter->GetCoordOrigin(); #endif } /******************************************************************************************** > CamelotFileRecord::~CamelotFileRecord() Author: Mark_Neves (Xara Group Ltd) Created: 24/6/96 Purpose: Default destructor Errors: - SeeAlso: - ********************************************************************************************/ CamelotFileRecord::~CamelotFileRecord() { } #if !defined(EXCLUDE_FROM_XARLIB) /******************************************************************************************** > virtual BOOL CamelotFileRecord::WritePath(Path* pPath) Author: Mark_Neves (Xara Group Ltd) Created: 24/6/96 Inputs: pPath = ptr to a path Returns: TRUE if OK, FALSE otherwise Purpose: Writes out the path to the record. All Coords in the path are translated to the origin set up in the filter that was used to construct this object Errors: - SeeAlso: - ********************************************************************************************/ BOOL CamelotFileRecord::WritePath(Path* pPath) { return WritePathTrans(pPath,-CoordOrigin.x,-CoordOrigin.y); } /******************************************************************************************** > virtual BOOL CamelotFileRecord::WritePathRelative(Path* pPath) Author: Mark_Neves (Xara Group Ltd) Created: 24/6/96 Inputs: pPath = ptr to a path Returns: TRUE if OK, FALSE otherwise Purpose: Writes out the relative path to the record. All Coords in the path are translated to the origin set up in the filter that was used to construct this object Errors: - SeeAlso: - ********************************************************************************************/ BOOL CamelotFileRecord::WritePathRelative(Path* pPath) { return WritePathRelativeTrans(pPath,-CoordOrigin.x,-CoordOrigin.y); } /******************************************************************************************** > virtual BOOL CamelotFileRecord::WriteCoord(const DocCoord& Coord) Author: Mark_Neves (Xara Group Ltd) Created: 24/6/96 Inputs: Coord = coord to write to the record Returns: TRUE if OK, FALSE otherwise Purpose: Writes out the coord to the record. The Coord is translated to the origin set up in the filter that was used to construct this object Errors: - SeeAlso: - ********************************************************************************************/ BOOL CamelotFileRecord::WriteCoord(const DocCoord& Coord) { return WriteCoordTrans(Coord,-CoordOrigin.x,-CoordOrigin.y); } BOOL CamelotFileRecord::WriteCoordInterleaved(const DocCoord& Coord) { return WriteCoordTransInterleaved(Coord,-CoordOrigin.x,-CoordOrigin.y); } BOOL CamelotFileRecord::WriteMatrix(const Matrix & m) { return WriteMatrixTrans(m,-CoordOrigin.x,-CoordOrigin.y); } /******************************************************************************************** > virtual BOOL CamelotFileRecord::WriteXOrd(INT32 XOrdinate) Author: Mark_Neves (Xara Group Ltd) Created: 8/8/96 Inputs: XOrdinate = x ordinate to write to the record Returns: TRUE if OK, FALSE otherwise Purpose: Writes out the x ordinate to the record. The ordinate is translated to the origin set up in the filter that was used to construct this object Errors: - SeeAlso: - ********************************************************************************************/ BOOL CamelotFileRecord::WriteXOrd(INT32 XOrdinate) { return WriteINT32(XOrdinate-CoordOrigin.x); } BOOL CamelotFileRecord::WriteYOrd(INT32 YOrdinate) { return WriteINT32(YOrdinate-CoordOrigin.y); } /******************************************************************************************** > virtual BOOL CamelotFileRecord::ReadPath(Path* pPath) Author: Mark_Neves (Xara Group Ltd) Created: 24/6/96 Inputs: pPath = ptr to a path Returns: TRUE if OK, FALSE otherwise Purpose: Reads a path from the record. All Coords in the path are translated to the origin set up in the filter that was used to construct this object Errors: - SeeAlso: - ********************************************************************************************/ BOOL CamelotFileRecord::ReadPath(Path* pPath) { return ReadPathTrans(pPath,CoordOrigin.x,CoordOrigin.y); } /******************************************************************************************** > virtual BOOL CamelotFileRecord::ReadPathRelative(Path* pPath) Author: Mark_Neves (Xara Group Ltd) Created: 22/8/96 Inputs: pPath = ptr to a path Returns: TRUE if OK, FALSE otherwise Purpose: Reads a relative path from the record. All Coords in the path are translated to the origin set up in the filter that was used to construct this object Errors: - SeeAlso: - ********************************************************************************************/ BOOL CamelotFileRecord::ReadPathRelative(Path* pPath) { return ReadPathRelativeTrans(pPath,CoordOrigin.x,CoordOrigin.y); } /******************************************************************************************** > virtual BOOL CamelotFileRecord::ReadCoord(DocCoord* pCoord) Author: Mark_Neves (Xara Group Ltd) Created: 24/6/96 Inputs: pCoord = ptr coord to read into Returns: TRUE if OK, FALSE otherwise Purpose: Read in the coord from the record. The Coord is translated to the origin set up in the filter that was used to construct this object Errors: - SeeAlso: - ********************************************************************************************/ BOOL CamelotFileRecord::ReadCoord(DocCoord* pCoord) { return ReadCoordTrans(pCoord,CoordOrigin.x,CoordOrigin.y); } BOOL CamelotFileRecord::ReadCoordInterleaved(DocCoord* pCoord) { return ReadCoordTransInterleaved(pCoord,CoordOrigin.x,CoordOrigin.y); } BOOL CamelotFileRecord::ReadMatrix(Matrix* pm) { return ReadMatrixTrans(pm,CoordOrigin.x,CoordOrigin.y); } /******************************************************************************************** > virtual BOOL CamelotFileRecord::ReadXOrd(INT32* pXOrdinate) Author: Mark_Neves (Xara Group Ltd) Created: 8/8/96 Inputs: pXOrdinate = ptr place to stick the x ordinate read in Returns: TRUE if OK, FALSE otherwise Purpose: Reads the x ordinate from the record. The ordinate is translated to the origin set up in the filter that was used to construct this object Errors: - SeeAlso: - ********************************************************************************************/ BOOL CamelotFileRecord::ReadXOrd(INT32* pXOrdinate) { if (ReadINT32(pXOrdinate)) { *pXOrdinate += CoordOrigin.x; return TRUE; } return FALSE; } BOOL CamelotFileRecord::ReadYOrd(INT32* pYOrdinate) { if (ReadINT32(pYOrdinate)) { *pYOrdinate += CoordOrigin.y; return TRUE; } return FALSE; } #endif