cdrtext.cpp

Go to the documentation of this file.
00001 // $Id: cdrtext.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 // ********* Text objects for CDR files
00099 
00100 /*
00101 */
00102 
00103 #include "camtypes.h"
00104 #include "cdrfiltr.h"
00105 #include "nodetxts.h"
00106 #include "nodetxtl.h"
00107 #include "nodetext.h"
00108 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 //#include "txtattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 #include "fontman.h"
00112 
00113 DECLARE_SOURCE("$Revision: 1282 $");
00114 
00115 #define new CAM_DEBUG_NEW
00116 
00117 static TCHAR *CDRDefaultFontName = "AvantGarde Bk BT";
00118 static CDRTextStyle CDRDefaultTextStyle = {0, (72000*24)/72, FALSE, FALSE, FALSE, CDRSCRIPT_NONE,
00119             (1000*24)/72, 100, JLEFT};
00120 
00121 /********************************************************************************************
00122 
00123 >   BOOL CDRFilter::ConvertText(cdrfOffsetHeader *Header)
00124 
00125     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00126     Created:    24 03 95
00127     Inputs:     none
00128     Returns:    error flag
00129     Purpose:    converts a text object to a node. If the object has an unexpected
00130                 format, then FormatError is set and it return *TRUE* - the return value only
00131                 indicated environmental errors such as lack of memory
00132     SeeAlso:    
00133 
00134 ********************************************************************************************/
00135 
00136 BOOL CDRFilter::ConvertText(cdrfOffsetHeader *Header)
00137 {
00138     // check to see if this has an offset for text on a path
00139     if(FindDataInObject(Header, cdrfOBJOFFSETTYPE_PATHTEXT1) != 0
00140             && FindDataInObject(Header, cdrfOBJOFFSETTYPE_PATHTEXT2) != 0)
00141     {
00142         IsTextOnAPath = TRUE;
00143     }
00144     else
00145     {
00146         IsTextOnAPath = FALSE;
00147     }
00148 
00149     // hey, this is text!
00150     IsText = TRUE;
00151     IsTextStory = FALSE;
00152 
00153     // dispatch conversion to appropriate routine
00154     if(Version == CDRVERSION_3)
00155         return ConvertText3(Header);
00156 
00157     if(Version == CDRVERSION_4)
00158     {
00159         if(CDRDATA_WORD(Header->ObjectType) == cdrfOBJTYPE_TEXT)
00160         {
00161             return ConvertText4Art(Header);
00162         }
00163         else
00164         {
00165             return ConvertText4Para(Header);
00166         }
00167     }
00168 
00169     // if it's a text story we're fiddling with, see how big the frame is
00170     INT32 FrameX = 0, FrameY = 0;
00171     DocCoord Trans = DocCoord(0,0);
00172     if(Header->ObjectType == cdrfOBJTYPE_TEXTSTORY)
00173     {
00174         // find the size of the object
00175         cdrfTextStoryCoordData *Coords = (cdrfTextStoryCoordData *)FindDataInObject(Header, cdrfOBJOFFSETTYPE_COORDS);
00176     
00177         if(Coords == 0)
00178         {
00179             FormatError = TRUE;
00180             return TRUE;
00181         }
00182 
00183         FrameX = CDRDATA_WORD(Coords->XSize);
00184         FrameY = CDRDATA_WORD(Coords->YSize);
00185 TRACEUSER( "Ben", _T("Initial frame dimensions: X = %d Y = %d\n"), FrameX, FrameY);
00186 
00187         IsTextStory = TRUE;
00188     }
00189     else
00190     {
00191         IsTextStory = FALSE;
00192     }
00193 
00194     // OK, the header supplied here is in a block of it's own so we can aquire a new RIFF block
00195     // for the text info
00196 
00197     // the RIFF object will be at a loda chunk, which is at a one higher level than that of
00198     // the txsm chunk - find level we don't want to seek over
00199     ERROR3IF(RIFF->GetObjType() != RIFFOBJECTTYPE_CHUNK || RIFF->GetObjChunkType() != cdrT_loda,
00200         "CDFFilter::ConvertText called with RIFF on a non-loda chunk");
00201     UINT32 EndLevel = RIFF->GetObjLevel() - 1;
00202 
00203     // now stroll though the RIFF file
00204     // stop when we find a txsm chunk, and store any trfd chunks we might meet on the way
00205     BOOL Found = FALSE;
00206     do
00207     {
00208         if(RIFF->GetObjType() == RIFFOBJECTTYPE_CHUNK && RIFF->GetObjChunkType() == cdrT_txsm)
00209         {
00210             // found the text info thingy
00211             Found = TRUE;
00212         }
00213         else if(RIFF->GetObjType() == RIFFOBJECTTYPE_LISTSTART && RIFF->GetObjChunkType() == cdrT_trfl)
00214         {
00215             // grab the list contents
00216             if(!RIFF->GetListContents(&TransformChunk, &TransformChunkSize))
00217                 return FALSE;
00218         }
00219 
00220         UpdateProgress();
00221 
00222         if(!Found)
00223             if(!RIFF->NextObject())
00224                 return FALSE;
00225     
00226     } while(Found == FALSE && (RIFF->GetObjType() != RIFFOBJECTTYPE_LISTEND || RIFF->GetObjLevel() >= EndLevel));
00227 
00228     if(RIFF->GetObjType() != RIFFOBJECTTYPE_CHUNK || RIFF->GetObjChunkType() != cdrT_txsm)
00229     {
00230         FormatError = TRUE;
00231         return TRUE;
00232     }
00233 
00234     // get size of chunk
00235     INT32 TextInfoSize = RIFF->GetObjSize();
00236     
00237     // aquire the chunk data
00238     if(!RIFF->AquireChunkData())
00239         return FALSE;
00240 
00241     // and get a pointer to the 'nice' info chunk
00242     ADDR TextInfo;
00243     if((TextInfo = RIFF->GetAquiredData()) == 0)
00244     {
00245         return FALSE;
00246     }
00247     cdrfTextInfoHdr *TIH = (cdrfTextInfoHdr *)TextInfo;
00248 
00249     // make a new text story node
00250     TextStory *TSNode = new TextStory;
00251 
00252     if(TSNode == 0)
00253         return FALSE;
00254     
00255     // get the number of paragraphs
00256     UINT32 NParagraphs = CDRDATA_WORD(TIH->NParagraphs);
00257 
00258     // set up some variables
00259     INT32 Loc = sizeof(cdrfTextInfoHdr);
00260     INT32 FirstLineSpace = -1;
00261     INT32 InitialFirstLineSpace = -1;
00262     INT32 ThisLineSpace = 0;
00263     INT32 PreviousLineSpace = 0;
00264     INT32 MaximumLineX = 0;     // MaximumLineX and
00265     INT32 Lines = 1;                // Lines only used for artisitic text
00266     Justification Just;         // the justification
00267 
00268     // convert the paragraph
00269     UINT32 CurrentPara;
00270     INT32 LineX;
00271     for(CurrentPara = 0; CurrentPara < NParagraphs; CurrentPara++)
00272     {
00273         // set up a few things
00274         LineX = 0;          // current position in the line
00275         
00276         // check sizes
00277         if((Loc + (INT32)sizeof(cdrfTextInfoParaHdr)) > TextInfoSize)
00278             break;
00279     
00280         // get paragraph header info
00281         cdrfTextInfoParaHdr *ParaHdr = (cdrfTextInfoParaHdr *)(TextInfo + Loc);
00282         Loc += sizeof(cdrfTextInfoParaHdr);
00283 
00284         // sort out font style definitions
00285         INT32 NFontDefns = CDRDATA_WORD(ParaHdr->NFontDefns);
00286 
00287         if((Loc + ((INT32)sizeof(cdrfTextInfoFontDefn) * NFontDefns)) > TextInfoSize)
00288             break;
00289     
00290         cdrfTextInfoFontDefn *FontDefns = (cdrfTextInfoFontDefn *)(TextInfo + Loc);
00291         Loc += (sizeof(cdrfTextInfoFontDefn) * NFontDefns);
00292 
00293         // get some memory for the converted font styles
00294         if(NFontDefns <= 0)
00295             break;
00296 
00297         CDRTextStyle *Styles = new CDRTextStyle[NFontDefns];
00298         
00299         // convert the first definiton from the style
00300         if(!GetTextStyleFromCDRStyle(&Styles[0], ParaHdr->Style))
00301             goto NoMemory;
00302 
00303         // store the justificationness
00304         Just = Styles[0].Just;
00305 
00306         // just in case of random Corel behaviour...
00307         PreviousLineSpace = (Styles[0].FontSize * 12) / 10;
00308 
00309         // go through translating all the other styles
00310         for(INT32 l = 1; l < NFontDefns; l++)
00311         {
00312             if(!GetTextStyleFromDefn(&Styles[l], &FontDefns[l], &Styles[0]))
00313                 return FALSE;
00314         }
00315 
00316         // get the paragraph info
00317         if((Loc + (INT32)sizeof(cdrfTextInfoParaInfo)) > TextInfoSize)
00318             break;
00319         
00320         cdrfTextInfoParaInfo *PInfo = (cdrfTextInfoParaInfo *)(TextInfo + Loc);
00321 
00322         Loc += sizeof(cdrfTextInfoParaInfo);
00323         
00324         INT32 NChars = CDRDATA_WORD(PInfo->NChars);
00325 
00326         // sort out the character array
00327         if((Loc + ((INT32)sizeof(cdrfTextInfoChar) * NChars)) > TextInfoSize)
00328             break;
00329         
00330         cdrfTextInfoChar *Chars = (cdrfTextInfoChar *)(TextInfo + Loc);
00331 
00332         Loc += (sizeof(cdrfTextInfoChar) * NChars);
00333     
00334         // make a new text line for this paragraph
00335         TextLine *CurrentLine = new TextLine(TSNode, LASTCHILD);
00336         if(CurrentLine == 0)
00337             goto NoMemory;
00338 
00339         // and run through adding all those nice characters
00340         INT32 CurrentChar;
00341         for(CurrentChar = 0; CurrentChar < NChars; CurrentChar++)
00342         {
00343             BOOL NewLine = FALSE;       // whether to create a new line here
00344 
00345             if(IsTextStory == FALSE && CDRDATA_WORD(Chars[CurrentChar].Code) == cdrfTEXT_NEWLINE)
00346             {
00347                 // update a couple of artisitic text only variables
00348                 Lines++;
00349 
00350                 if(LineX > MaximumLineX)
00351                     MaximumLineX = LineX;
00352 
00353                 // create a new line
00354                 NewLine = TRUE;
00355             }
00356             
00357             // find the style of the character
00358             INT32 Style = ((CDRDATA_WORD(Chars[CurrentChar].Info)) & cdrfTEXTINFOCHAR_INFO_DEFNMASK)
00359                         >> cdrfTEXTINFOCHAR_INFO_DEFNMASKSBY;
00360 
00361             // create it
00362             if(CDRDATA_WORD(Chars[CurrentChar].Code) >= ' ')
00363             {
00364                 TextChar *C = new TextChar(CurrentLine, LASTCHILD, CDRDATA_WORD(Chars[CurrentChar].Code));
00365 
00366                 if(C == 0)
00367                     goto NoMemory;
00368 
00369                 if(Style < 0 || Style >= NFontDefns)
00370                     Style = 0;
00371 
00372                 // apply attributes
00373                 if(!ApplyTextAttr(C, &Styles[Style], 0 /*&Styles[0]*/))     // for now, we can't base attributes on anything 'cos the optimiser can't hack it
00374                     goto NoMemory;
00375             }
00376 
00377             // add the character width
00378             LineX += CDRDATA_SWORD(Chars[CurrentChar].XSize);
00379 
00380             // update this line's spacing thingy
00381             if(Styles[Style].LineSpace > ThisLineSpace)
00382                 ThisLineSpace = Styles[Style].LineSpace;
00383 
00384             // sort out first line spaceing thing
00385             if(InitialFirstLineSpace == -1)
00386                 InitialFirstLineSpace = Styles[Style].LineSpace;
00387 
00388             if(NewLine)
00389             {
00390                 // apply the line spacing attribute - make a font size attribute
00391                 if(ThisLineSpace < 512)
00392                     ThisLineSpace = PreviousLineSpace;
00393                 TxtLineSpaceAttribute Attr((FIXED16)(((double)Styles[0].ParaLineSpacePercent) /* * 1.2*/ / 100));
00394 
00395                 // attach
00396                 if(!ApplyTextAttrDoApply(CurrentLine, &Attr, FALSE))
00397                     return FALSE;
00398 
00399                 // add an EOL
00400                 EOLNode *EOL = new EOLNode(CurrentLine, LASTCHILD);
00401                 if(EOL == 0)
00402                     goto NoMemory;
00403                 // make a new line
00404                 CurrentLine = new TextLine(TSNode, LASTCHILD);
00405                 if(CurrentLine == 0)
00406                     goto NoMemory;
00407 
00408                 // sort out first line spacing thing
00409                 if(FirstLineSpace == -1)
00410                     FirstLineSpace = ThisLineSpace;
00411 
00412                 // reset things
00413                 LineX = 0;
00414                 PreviousLineSpace = ThisLineSpace;
00415                 ThisLineSpace = 0;
00416             }
00417         }
00418 
00419         // sort out first line spaceing thing
00420         if(FirstLineSpace == -1)
00421             FirstLineSpace = ThisLineSpace;
00422 
00423         // apply the line spacing attribute - make a font size attribute
00424         if(ThisLineSpace < 512)
00425             ThisLineSpace = PreviousLineSpace;
00426         TxtLineSpaceAttribute Attr((FIXED16)(((double)Styles[0].ParaLineSpacePercent)  / 100));
00427     
00428         // attach
00429         if(!ApplyTextAttrDoApply(CurrentLine, &Attr, FALSE))
00430             return FALSE;
00431 
00432         // pop on an end of line node
00433         EOLNode *EOL = new EOLNode(CurrentLine, LASTCHILD);
00434 
00435         if(EOL == 0)
00436             goto NoMemory;
00437 
00438         // get rid of the font styles
00439         delete [] Styles;
00440 
00441         PreviousLineSpace = ThisLineSpace;
00442     }
00443 
00444     // pop a caret at the end of the last line
00445     {
00446         Node *LastLine = TSNode->FindLastChild();
00447 
00448         if(LastLine == 0)
00449             goto FormError;
00450 
00451         Node *LastLineNode = LastLine->FindLastChild();
00452 
00453         ERROR3IF(LastLineNode == 0, "Line node doesn't have any children");
00454         ERROR3IF(!LastLineNode->IsKindOf(CC_RUNTIME_CLASS(EOLNode)), "Last entry of a line is not an EOL node");
00455         
00456         CaretNode *C = new CaretNode(LastLineNode, PREV);
00457         if(C == 0)
00458             goto NoMemory;
00459     }
00460 
00461     // set up maximumlinex - only valid for artisitic text
00462     if(LineX > MaximumLineX)
00463         MaximumLineX = LineX;
00464 
00465     // set up a bounding box for this text object and
00466     // if this is a text story, translate it down a bit
00467     // so that the top of the first line is at the top of the frame
00468     if(IsTextStory)
00469     {
00470         if(FirstLineSpace == -1)
00471             goto FormError;         // no first line? How strange...
00472 
00473         // work out the distance to move the text line down = the first line un 120%ed
00474         INT32 Down = (FirstLineSpace * 10) / 12;
00475 
00476         // work out the rightness shifting
00477         INT32 Right = 0;
00478         if(Just == JCENTRE)
00479         {
00480             Right = (FrameX / 2) * CDRCOORDS_TO_MILLIPOINTS;
00481         }
00482         else if(Just == JRIGHT)
00483         {
00484             Right = FrameX * CDRCOORDS_TO_MILLIPOINTS;
00485         }
00486 
00487         // transform the story
00488         TSNode->SetStoryMatrix(Matrix(Trans.x+Right, Trans.y-Down));
00489 
00490         // set the format width
00491         TSNode->SetImportFormatWidth(FrameX * CDRCOORDS_TO_MILLIPOINTS);
00492 TRACEUSER( "Ben", _T("Import format width initially %d\n"), TSNode->GetImportFormatWidth());
00493 
00494         // bounding box for text story
00495         DocRect BBox = DocRect(Trans.x, Trans.y - (FrameY * CDRCOORDS_TO_MILLIPOINTS),
00496                 Trans.x + (FrameX * CDRCOORDS_TO_MILLIPOINTS), Trans.y);
00497 
00498         TextBBoxes.Add(TSNode, &BBox, JLEFT);
00499     }
00500     else
00501     {
00502         // set the matrix of the story
00503         TSNode->SetStoryMatrix(Matrix(0,0));
00504 
00505         // bounding box for a text object
00506         DocRect BBox = DocRect(0, 0 - FirstLineSpace * Lines,
00507                 (MaximumLineX * CDRCOORDS_TO_MILLIPOINTS), FirstLineSpace);
00508 
00509         TextBBoxes.Add(TSNode, &BBox, Just);
00510 
00511         // see if this is linked to a path
00512         CheckTextForLinks(TSNode, Header);
00513     }
00514 
00515     // set some essential variables
00516     ObjFilled = TRUE;
00517     ObjStroked = FALSE;
00518 
00519     // all done return...
00520     pMadeNode = TSNode;
00521 
00522     return TRUE;
00523 
00524 NoMemory:
00525     TSNode->CascadeDelete();
00526     delete TSNode;
00527     
00528     return FALSE;
00529 
00530 FormError:
00531     FormatError = TRUE;
00532     TSNode->CascadeDelete();
00533     delete TSNode;
00534     
00535     return TRUE;
00536 }
00537 
00538 
00539 /********************************************************************************************
00540 
00541 >   BOOL CDRFilter::ConvertText4Art(cdrfOffsetHeader *Header)
00542 
00543     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00544     Created:    24 03 95
00545     Inputs:     none
00546     Returns:    error flag
00547     Purpose:    converts a version 4 artisitic text object
00548     SeeAlso:    
00549 
00550 ********************************************************************************************/
00551 
00552 BOOL CDRFilter::ConvertText4Art(cdrfOffsetHeader *Header)
00553 {
00554     // get the data from this object
00555     cdrfTextHeaderV4 *Hdr = (cdrfTextHeaderV4 *)FindDataInObject(Header, cdrfOBJOFFSETTYPE_COORDS);
00556 
00557     // it has got some coords, hasn't it?
00558     if(Hdr == 0)
00559     {
00560         FormatError = TRUE;
00561         return TRUE;
00562     }
00563     // find pointer to the characters
00564     cdrfTextCharV4 *ThisChar = (cdrfTextCharV4 *)(Hdr + 1);
00565 
00566     // get the base style
00567     CDRTextStyle BaseStyle;
00568 
00569     WORD *StyleRef = (WORD *)FindDataInObject(Header, cdrfOBJOFFSETTYPE_STYLE);
00570     if(StyleRef == 0)
00571     {
00572         FormatError = TRUE;
00573         return TRUE;
00574     }
00575 
00576     if(!GetTextStyleFromCDRStyle(&BaseStyle, CDRDATA_WORD(*StyleRef)))
00577         return FALSE;
00578 
00579     // make a new text story node
00580     TextStory *TSNode = new TextStory;
00581 
00582     if(TSNode == 0)
00583         return FALSE;
00584 
00585     // run through the text...
00586     INT32 NChars = CDRDATA_WORD(Hdr->NCharacters);
00587     INT32 CurrentChar;
00588     INT32 MaximumLineSpace = BaseStyle.LineSpace;
00589     INT32 Lines = 1;
00590     INT32 Depth = 0;
00591 
00592     // make a new text line
00593     TextLine *CurrentLine = new TextLine(TSNode, LASTCHILD);
00594     if(CurrentLine == 0)
00595         goto NoMemory;
00596 
00597     for(CurrentChar = 0; CurrentChar < NChars; CurrentChar++)
00598     {
00599         BOOL HasStyles = FALSE;
00600 
00601         if(ThisChar->Info != 0)
00602             HasStyles = TRUE;
00603 
00604         if(ThisChar->Code >= ' ')
00605         {
00606             TextChar *C = new TextChar(CurrentLine, LASTCHILD, ThisChar->Code);
00607 
00608             if(C == 0)
00609                 goto NoMemory;
00610 
00611             // apply attributes
00612             if(HasStyles)
00613             {
00614                 // it's got styles of it's own, find and apply them
00615                 cdrfTextCharStyledV4 *SC = (cdrfTextCharStyledV4 *)ThisChar;
00616 
00617                 CDRTextStyle ThisStyle;
00618 
00619                 if(!GetTextStyleFromChar4(&ThisStyle, SC, &BaseStyle))
00620                     return FALSE;
00621 
00622                 if(!ApplyTextAttr(C, &ThisStyle, 0))
00623                     goto NoMemory;
00624         
00625                 if(ThisStyle.LineSpace > MaximumLineSpace)
00626                     MaximumLineSpace = ThisStyle.LineSpace;
00627             }
00628             else
00629             {
00630                 // just apply the normal attributes
00631                 if(!ApplyTextAttr(C, &BaseStyle, 0))
00632                     goto NoMemory;
00633             }
00634         }
00635 
00636         if(ThisChar->Code == cdrfTEXT_NEWLINE)
00637         {
00638             // create a new line...
00639             // apply the line spacing attribute - make a font size attribute
00640 //          TxtLineSpaceAttribute Attr(MaximumLineSpace);
00641             TxtLineSpaceAttribute Attr((FIXED16)(((double)BaseStyle.ParaLineSpacePercent)  / 100));
00642 
00643             // attach
00644             if(!ApplyTextAttrDoApply(CurrentLine, &Attr, FALSE))
00645                 return FALSE;
00646 
00647             // add an EOL
00648             EOLNode *EOL = new EOLNode(CurrentLine, LASTCHILD);
00649             if(EOL == 0)
00650                 goto NoMemory;
00651 
00652             // make a new line
00653             CurrentLine = new TextLine(TSNode, LASTCHILD);
00654             if(CurrentLine == 0)
00655                 goto NoMemory;
00656 
00657             // set things
00658             Lines++;
00659             Depth += MaximumLineSpace;
00660             MaximumLineSpace = BaseStyle.LineSpace;
00661         }
00662 
00663         if(HasStyles)
00664         {
00665             // it's got more than normal bytes in it, so add a few more than usual
00666             ThisChar = (cdrfTextCharV4 *)(((cdrfTextCharStyledV4 *)ThisChar) + 1);
00667         }
00668         else
00669         {
00670             // just a normal character, so simply increment it
00671             ThisChar++;
00672         }
00673     }
00674 
00675     // pop a line space attribute on the last line
00676     {
00677 //      TxtLineSpaceAttribute Attr(MaximumLineSpace);
00678         TxtLineSpaceAttribute Attr((FIXED16)(((double)BaseStyle.ParaLineSpacePercent)  / 100));
00679 
00680         // attach
00681         if(!ApplyTextAttrDoApply(CurrentLine, &Attr, FALSE))
00682             return FALSE;
00683     }
00684 
00685     Depth += MaximumLineSpace;
00686 
00687     // finish the last line with an end of line node
00688     {
00689         EOLNode *EOL = new EOLNode(CurrentLine, LASTCHILD);
00690 
00691         if(EOL == 0)
00692             goto NoMemory;
00693 
00694         // pop a caret at the end of the last line
00695         Node *LastLine = TSNode->FindLastChild();
00696 
00697         if(LastLine == 0)
00698             goto FormError;
00699 
00700         Node *LastLineNode = LastLine->FindLastChild();
00701 
00702         ERROR3IF(LastLineNode == 0, "Line node doesn't have any children");
00703         ERROR3IF(!LastLineNode->IsKindOf(CC_RUNTIME_CLASS(EOLNode)), "Last entry of a line is not an EOL node");
00704         
00705         CaretNode *C = new CaretNode(LastLineNode, PREV);
00706         if(C == 0)
00707             goto NoMemory;
00708     }
00709 
00710     // set the matrix of the story
00711     {
00712         TSNode->SetStoryMatrix(Matrix(0,0));
00713 
00714         // bounding box for a artisitic text object - approximate it's width
00715         INT32 Width = (MaximumLineSpace * NChars) / (Lines * 3);
00716 
00717         DocRect BBox = DocRect(0, 0 - Depth, Width, MaximumLineSpace);
00718 
00719         TextBBoxes.Add(TSNode, &BBox, BaseStyle.Just);
00720     }
00721 
00722     // check it for paths...
00723     CheckTextForLinks(TSNode, Header);
00724     
00725     // set some essential variables
00726     ObjFilled = TRUE;
00727     ObjStroked = FALSE;
00728     IsTextStory = FALSE;
00729 
00730     // all done, return...
00731     pMadeNode = TSNode;
00732 
00733     return TRUE;
00734 
00735 NoMemory:
00736     TSNode->CascadeDelete();
00737     delete TSNode;
00738     
00739     return FALSE;
00740 
00741 FormError:
00742     FormatError = TRUE;
00743     TSNode->CascadeDelete();
00744     delete TSNode;
00745     
00746     return TRUE;
00747 }
00748 
00749 
00750 /********************************************************************************************
00751 
00752 >   BOOL CDRFilter::ConvertText4Para(cdrfOffsetHeader *Header)
00753 
00754     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00755     Created:    24 03 95
00756     Inputs:     none
00757     Returns:    error flag
00758     Purpose:    converts a version 4 paragraph text object
00759     SeeAlso:    
00760 
00761 ********************************************************************************************/
00762 
00763 BOOL CDRFilter::ConvertText4Para(cdrfOffsetHeader *Header)
00764 {
00765     // get the data from this object
00766     cdrfParaTextHeaderV4 *Hdr = (cdrfParaTextHeaderV4 *)FindDataInObject(Header, cdrfOBJOFFSETTYPE_COORDS);
00767 
00768     // set the var...
00769     IsTextStory = TRUE;
00770 
00771     // it has got some coords, hasn't it?
00772     if(Hdr == 0)
00773     {
00774         FormatError = TRUE;
00775         return TRUE;
00776     }
00777 
00778 
00779     // find out what text item we need
00780     if(LinkTable == 0)
00781     {
00782         // no link table, oh dear
00783         FormatError = TRUE;
00784         return TRUE;
00785     }
00786 
00787     cdrfLinkTableHdr *th = (cdrfLinkTableHdr *)LinkTable;
00788 
00789     INT32 Entries = CDRDATA_WORD(th->Entries);
00790     BOOL Found = FALSE;
00791     WORD *Offsets = (WORD *)(LinkTable + CDRDATA_WORD(th->OffsetsOffset));
00792     cdrfLinkTableEntryTextV4 *En;
00793     for(INT32 l = 0; l < Entries; l++)
00794     {
00795         En = (cdrfLinkTableEntryTextV4 *)(LinkTable + CDRDATA_WORD(Offsets[l]));
00796     
00797         if(CDRDATA_WORD(En->Type) == cdrfLINKTABLEENTRYV4_TEXT &&
00798                 CDRDATA_WORD(En->ObjectSerial) == SerialNumber)
00799         {
00800             Found = TRUE;
00801             break;
00802         }
00803     }
00804 
00805     if(Found == FALSE)
00806     {
00807         FormatError = TRUE;
00808         return TRUE;
00809     }
00810     
00811     // locate the text item with those attributes
00812     CDRVectorStoredItem *Item = (CDRVectorStoredItem *)TextV4.GetHead();
00813     
00814     // go through the list of items searching for the reference number given
00815     while(Item != 0)
00816     {
00817         if(Item->Reference == CDRDATA_WORD(En->TextID))
00818         {
00819             // OK, we found it...
00820             break;
00821         }
00822 
00823         Item = (CDRVectorStoredItem *)TextV4.GetNext(Item);
00824     }
00825 
00826     if(Item == 0)
00827     {
00828         FormatError = TRUE;
00829         return TRUE;
00830     }
00831 
00832     Node *Text = Item->Objects;
00833 
00834     // find the base attributes
00835     CDRTextStyle BaseStyle;
00836 
00837     WORD *StyleRef = (WORD *)FindDataInObject(Header, cdrfOBJOFFSETTYPE_STYLE);
00838     if(StyleRef == 0)
00839     {
00840         FormatError = TRUE;
00841         return TRUE;
00842     }
00843 
00844     if(!GetTextStyleFromCDRStyle(&BaseStyle, CDRDATA_WORD(*StyleRef)))
00845         return FALSE;
00846     
00847     // get the maximum height of the first line
00848     ERROR2IF(!IS_A(Text, TextLine), FALSE, "Node in text list is not a text line");
00849 
00850     // apply attributes to the lines
00851     TextLine *CurrentLine = (TextLine *)Text;
00852     while(CurrentLine != 0)
00853     {
00854         if(IS_A(CurrentLine, TextLine))
00855         {
00856 /*          Node *pNode = CurrentLine->FindFirstChild();
00857 
00858             while(pNode != 0)
00859             {
00860                 if(IS_A(pNode, TextChar))
00861                 {
00862                     if(!ApplyTextAttr(pNode, &BaseStyle, 0))
00863                         return FALSE;
00864                 }
00865 
00866                 pNode = pNode->FindNext();
00867             }
00868 */
00869             // attach the line spacing onto it
00870             TxtLineSpaceAttribute Attr((FIXED16)(((double)BaseStyle.ParaLineSpacePercent)  / 100));
00871 
00872             if(!ApplyTextAttrDoApply(CurrentLine, &Attr, FALSE))
00873                 return FALSE;
00874         }
00875         
00876         CurrentLine = (TextLine *)CurrentLine->FindNext();
00877     }
00878 
00879     // add it to a text story
00880     TextStory *TSNode = new TextStory;
00881     if(TSNode == 0)
00882         return FALSE;
00883 
00884     Text->InsertChainSimple(TSNode, FIRSTCHILD);
00885 
00886     // remove references to the nodes now inserted from the item
00887     Item->Objects = 0;
00888 
00889     // set the matrix and add the bbox
00890     {
00891         INT32 FirstLineSpace = Item->BBox.hi.y;     // get the line spacing from the bbox defn
00892 
00893         // get the frame size
00894         INT32 FrameX = CDRDATA_WORD(Hdr->FrameX) * CDRCOORDS_TO_MILLIPOINTS;
00895         INT32 FrameY = CDRDATA_WORD(Hdr->FrameY) * CDRCOORDS_TO_MILLIPOINTS;
00896 
00897         // work out the distance to move the text line down = the first line un 120%ed
00898         INT32 Down = (FirstLineSpace * 10) / 12;
00899 
00900         // work out the shift...
00901         INT32 Right = 0;
00902         if(BaseStyle.Just == JCENTRE)
00903         {
00904             Right = FrameX / 2;
00905         }
00906         else if(BaseStyle.Just == JRIGHT)
00907         {
00908             Right = FrameX;
00909         }
00910 
00911         
00912         // transform the story
00913         TSNode->SetStoryMatrix(Matrix(Right,-Down));
00914 
00915         // bounding box for text story
00916         DocRect BBox = DocRect(0, 0 - FrameY, FrameX, 0);
00917 
00918         TextBBoxes.Add(TSNode, &BBox, JLEFT);
00919 
00920         // set it's width to be formatted to
00921         TSNode->SetImportFormatWidth(FrameX);
00922     }
00923 
00924     // delete the item
00925     delete TextV4.RemoveItem(Item);
00926 
00927     // set a few variables
00928     pMadeNode = TSNode;
00929     ObjFilled = TRUE;
00930     ObjStroked = FALSE;
00931 
00932     return TRUE;
00933 }
00934 
00935 
00936 /********************************************************************************************
00937 
00938 >   BOOL CDRFilter::GetTextStyleFromChar4(CDRTextStyle *TS, cdrfTextCharStyledV4 *Char, CDRTextStyle *BasedOn)
00939 
00940     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00941     Created:    24 03 95
00942     Inputs:     none
00943     Returns:    error flag
00944     Purpose:    gets a text style from a styled version 4 text character
00945     SeeAlso:    
00946 
00947 ********************************************************************************************/
00948 
00949 BOOL CDRFilter::GetTextStyleFromChar4(CDRTextStyle *TS, cdrfTextCharStyledV4 *Char, CDRTextStyle *BasedOn)
00950 {
00951     if(BasedOn != 0)
00952         *TS = *BasedOn;
00953     else
00954         *TS = CDRDefaultTextStyle;
00955 
00956     // font name
00957     if((CDRDATA_WORD(Char->Changes) & cdrfSTYLECHANGEV4_FONTNAME) != 0)
00958     {
00959 /*      TCHAR *FontName = GetFontName(Char->FontRef);
00960         if(FontName != 0)
00961         {
00962             TS->FontName = FontName;
00963         }
00964 */
00965         TS->FontReference = CDRDATA_DWORD(Char->FontRef);
00966     }
00967 
00968     // font size
00969     if((CDRDATA_WORD(Char->Changes) & cdrfSTYLECHANGEV4_FONTSIZE) != 0)
00970     {
00971         if(CDRDATA_WORD(Char->FontSize) != 0)
00972         {
00973             TS->FontSize = CDRDATA_WORD(Char->FontSize) * CDRCOORDS_TO_MILLIPOINTS;
00974         }
00975     }
00976 
00977     // update line spacing
00978     TS->LineSpace = (TS->FontSize * (12 * TS->ParaLineSpacePercent)) / 1000;
00979 
00980     // weight
00981     if((CDRDATA_WORD(Char->Changes) & cdrfSTYLECHANGEV4_WEIGHT) != 0)
00982     {
00983         switch(CDRDATA_WORD(Char->FontType))
00984         {
00985             case cdrfFONTTYPEV4_BOLD:
00986                 TS->Bold = TRUE;
00987                 TS->Italic = FALSE;
00988                 break;
00989 
00990             case cdrfFONTTYPEV4_ITALIC:
00991                 TS->Bold = FALSE;
00992                 TS->Italic = TRUE;
00993                 break;
00994 
00995             case cdrfFONTTYPEV4_BOLDITALIC:
00996                 TS->Bold = TRUE;
00997                 TS->Italic = TRUE;
00998                 break;
00999 
01000             default:
01001                 TS->Bold = FALSE;
01002                 TS->Italic = FALSE;
01003                 break;
01004         }
01005     }
01006     
01007     return TRUE;
01008 }
01009 
01010 /********************************************************************************************
01011 
01012 >   BOOL CDRFilter::ConvertText3(cdrfOffsetHeader *Header)
01013 
01014     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01015     Created:    24 03 95
01016     Inputs:     none
01017     Returns:    error flag
01018     Purpose:    converts a version 3 text object to a node. If the object has an unexpected
01019                 format, then FormatError is set and it return *TRUE* - the return value only
01020                 indicated environmental errors such as lack of memory
01021     SeeAlso:    
01022 
01023 ********************************************************************************************/
01024 
01025 BOOL CDRFilter::ConvertText3(cdrfOffsetHeader *Header)
01026 {
01027     // is it a text story?
01028     if(Header->ObjectType == (cdrfOBJTYPE_TEXTSTORY - cdrfOBJTYPE_V3ADD))
01029         IsTextStory = TRUE;
01030 
01031     // get the data from this object
01032     cdrfTextHeaderV3 *Hdr = (cdrfTextHeaderV3 *)FindDataInObject(Header, cdrfOBJOFFSETTYPE_COORDS);
01033 
01034     // it has got some coords, hasn't it?
01035     if(Hdr == 0)
01036     {
01037         FormatError = TRUE;
01038         return TRUE;
01039     }
01040 //TRACEUSER( "Ben", _T("FrameX = %d, FrameY = %d\n"), Hdr->FrameX, Hdr->FrameY);
01041 
01042     INT32 FrameX = CDRDATA_WORD(Hdr->FrameX) * CDRCOORDS_TO_MILLIPOINTS;
01043     INT32 FrameY = CDRDATA_WORD(Hdr->FrameY) * CDRCOORDS_TO_MILLIPOINTS;
01044 
01045     // find pointer to the characters
01046     cdrfTextCharV3 *ThisChar = (cdrfTextCharV3 *)(Hdr + 1);
01047 
01048     // get the base style
01049     CDRTextStyle BaseStyle;
01050 
01051     if(!GetTextStyle3(&BaseStyle, CDRDATA_WORD(Hdr->BaseFontStyle)))
01052         return FALSE;
01053 
01054     // add the justifcation stuff to it
01055     TRACEUSER( "Ben", _T("Justificatoin V3 = %d\n"), Hdr->Justification);
01056     switch(Hdr->Justification)
01057     {
01058         case cdrfJUSTIFICATIONV3_LEFT:
01059         default:
01060             BaseStyle.Just = JLEFT;
01061             break;
01062 
01063         case cdrfJUSTIFICATIONV3_CENTRE:
01064             BaseStyle.Just = JCENTRE;
01065             break;
01066 
01067         case cdrfJUSTIFICATIONV3_RIGHT:
01068             BaseStyle.Just = JRIGHT;
01069             break;
01070     }
01071     
01072     // make a new text story node
01073     TextStory *TSNode = new TextStory;
01074 
01075     if(TSNode == 0)
01076         return FALSE;
01077 
01078     // run through the text...
01079     INT32 NChars = CDRDATA_WORD(Hdr->NCharacters);
01080     INT32 CurrentChar;
01081     INT32 MaximumLineSpace = BaseStyle.LineSpace;
01082     INT32 Lines = 1;
01083     INT32 Depth = 0;
01084 
01085     // make a new text line
01086     TextLine *CurrentLine = new TextLine(TSNode, LASTCHILD);
01087     if(CurrentLine == 0)
01088         goto NoMemory;
01089 
01090     for(CurrentChar = 0; CurrentChar < NChars; CurrentChar++)
01091     {
01092         BOOL HasStyles = FALSE;
01093 
01094         if(ThisChar->Info != 0)
01095             HasStyles = TRUE;
01096 
01097         if(ThisChar->Code >= ' ')
01098         {
01099             TextChar *C = new TextChar(CurrentLine, LASTCHILD, ThisChar->Code);
01100 
01101             if(C == 0)
01102                 goto NoMemory;
01103 
01104             // apply attributes
01105             if(HasStyles)
01106             {
01107                 // it's got styles of it's own, find and apply them
01108                 cdrfTextCharStyledV3 *SC = (cdrfTextCharStyledV3 *)ThisChar;
01109 
01110                 CDRTextStyle ThisStyle;
01111 
01112                 if(!GetTextStyle3(&ThisStyle, CDRDATA_WORD(SC->Style), &BaseStyle))
01113                     return FALSE;
01114 
01115                 if(!ApplyTextAttr(C, &ThisStyle, 0))
01116                     goto NoMemory;
01117         
01118                 if(ThisStyle.LineSpace > MaximumLineSpace)
01119                     MaximumLineSpace = ThisStyle.LineSpace;
01120             }
01121             else
01122             {
01123                 // just apply the normal attributes
01124                 if(!ApplyTextAttr(C, &BaseStyle, 0))
01125                     goto NoMemory;
01126             }
01127         }
01128 
01129         if(ThisChar->Code == cdrfTEXT_NEWLINE)
01130         {
01131             // create a new line...
01132             // apply the line spacing attribute - make a font size attribute
01133 //          TxtLineSpaceAttribute Attr(MaximumLineSpace);
01134             TxtLineSpaceAttribute Attr((FIXED16)(((double)BaseStyle.ParaLineSpacePercent)  / 100));
01135 
01136             // attach
01137             if(!ApplyTextAttrDoApply(CurrentLine, &Attr, FALSE))
01138                 return FALSE;
01139 
01140             // add an EOL
01141             EOLNode *EOL = new EOLNode(CurrentLine, LASTCHILD);
01142             if(EOL == 0)
01143                 goto NoMemory;
01144 
01145             // make a new line
01146             CurrentLine = new TextLine(TSNode, LASTCHILD);
01147             if(CurrentLine == 0)
01148                 goto NoMemory;
01149 
01150             // set things
01151             Lines++;
01152             Depth += MaximumLineSpace;
01153             MaximumLineSpace = BaseStyle.LineSpace;
01154         }
01155 
01156         if(HasStyles)
01157         {
01158 //TRACEUSER( "Ben", _T("Char has styles, code %d (%c)\n"), ThisChar->Code, ThisChar->Code); 
01159             // it's got more than normal bytes in it, so add a few more than usual
01160             ThisChar = (cdrfTextCharV3 *)(((cdrfTextCharStyledV3 *)ThisChar) + 1);
01161         }
01162         else
01163         {
01164 //TRACEUSER( "Ben", _T("Char, code %d (%c)\n"), ThisChar->Code, ThisChar->Code); 
01165             // just a normal character, so simply increment it
01166             ThisChar++;
01167         }
01168     }
01169 
01170     // pop a line space attribute on the last line
01171     {
01172 //      TxtLineSpaceAttribute Attr(MaximumLineSpace);
01173         TxtLineSpaceAttribute Attr((FIXED16)(((double)BaseStyle.ParaLineSpacePercent)  / 100));
01174 
01175         // attach
01176         if(!ApplyTextAttrDoApply(CurrentLine, &Attr, FALSE))
01177             return FALSE;
01178     }
01179 
01180     Depth += MaximumLineSpace;
01181 
01182     // finish the last line with an end of line node
01183     {
01184         EOLNode *EOL = new EOLNode(CurrentLine, LASTCHILD);
01185 
01186         if(EOL == 0)
01187             goto NoMemory;
01188 
01189         // pop a caret at the end of the last line
01190         Node *LastLine = TSNode->FindLastChild();
01191 
01192         if(LastLine == 0)
01193             goto FormError;
01194 
01195         Node *LastLineNode = LastLine->FindLastChild();
01196 
01197         ERROR3IF(LastLineNode == 0, "Line node doesn't have any children");
01198         ERROR3IF(!LastLineNode->IsKindOf(CC_RUNTIME_CLASS(EOLNode)), "Last entry of a line is not an EOL node");
01199         
01200         CaretNode *C = new CaretNode(LastLineNode, PREV);
01201         if(C == 0)
01202             goto NoMemory;
01203     }
01204 
01205     if(IsTextStory)
01206     {
01207         // get a first line height
01208         INT32 FirstLineHeight = (BaseStyle.LineSpace * 10) / 12;
01209 
01210         // work out the rightness shifting
01211         INT32 Right = 0;
01212         if(BaseStyle.Just == JCENTRE)
01213         {
01214             Right = FrameX / 2;
01215         }
01216         else if(BaseStyle.Just == JRIGHT)
01217         {
01218             Right = FrameX;
01219         }
01220 
01221         // set the matrix of the story
01222         TSNode->SetStoryMatrix(Matrix(Right, -FirstLineHeight));
01223 
01224         // bounding box for a text frame
01225         DocRect BBox = DocRect(0, 0 - FrameY, FrameX, 0);
01226 
01227         TextBBoxes.Add(TSNode, &BBox, JLEFT);
01228     
01229         // set it's width to be formatted to
01230         TSNode->SetImportFormatWidth(FrameX);
01231     }
01232     else
01233     {
01234         // set the matrix of the story
01235         TSNode->SetStoryMatrix(Matrix(0,0));
01236 
01237         // bounding box for a artisitic text object - approximate it's width
01238         INT32 Width = (MaximumLineSpace * NChars) / (Lines * 3);
01239 
01240         DocRect BBox = DocRect(0, 0 - Depth, Width, MaximumLineSpace);
01241 
01242         TextBBoxes.Add(TSNode, &BBox, BaseStyle.Just);
01243     
01244         // check it for path on a text
01245         CheckTextForLinks(TSNode, Header);
01246     }
01247 
01248     // set some essential variables
01249     ObjFilled = TRUE;
01250     ObjStroked = FALSE;
01251 
01252     // all done, return...
01253     pMadeNode = TSNode;
01254 
01255     return TRUE;
01256 
01257 NoMemory:
01258     TSNode->CascadeDelete();
01259     delete TSNode;
01260     
01261     return FALSE;
01262 
01263 FormError:
01264     FormatError = TRUE;
01265     TSNode->CascadeDelete();
01266     delete TSNode;
01267     
01268     return TRUE;
01269 }
01270 
01271 
01272 /********************************************************************************************
01273 
01274 >   BOOL CDRFilter::GetTextStyle3(CDRTextStyle *TS, WORD Style, CDRTextStyle *BasedOn = 0);
01275 
01276     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01277     Created:    04/05/95
01278     Inputs:     none
01279     Returns:    error flag
01280     Purpose:    gets a style for version 3 text from the global text styles table
01281     SeeAlso:    
01282 
01283 ********************************************************************************************/
01284 
01285 BOOL CDRFilter::GetTextStyle3(CDRTextStyle *TS, WORD Style, CDRTextStyle *BasedOn)
01286 {
01287     // copy in the default text style
01288     if(BasedOn == 0)
01289         *TS = CDRDefaultTextStyle;
01290     else
01291         *TS = *BasedOn;
01292 
01293     // if the styles chunk isn't present, return now
01294     if(FontStylesV3 == 0)
01295         return TRUE;
01296 
01297     // find the font definition
01298     cdrfFontStyleTableHeaderV3 *Hdr = (cdrfFontStyleTableHeaderV3 *)FontStylesV3;
01299 
01300     if(Style >= CDRDATA_WORD(Hdr->NOffsets))
01301         return TRUE;        // if there aren't enough entries to find this style
01302 
01303     cdrfFontStyleTableEntryV3 *En = (cdrfFontStyleTableEntryV3 *)(FontStylesV3 + CDRDATA_WORD(Hdr->Offsets[Style]));
01304 
01305     // convert it
01306 
01307     // find the font name
01308 /*  if(FontTableV3 == 0)
01309         return FALSE;
01310 
01311     cdrfFontTableEntryV3 *FEn = (cdrfFontTableEntryV3 *)FontTableV3;
01312     for(INT32 l = 0; l < FontTableEntriesV3; l++)
01313     {
01314         if(FEn[l].Reference == En->FontRef)     // don't need to bother with CDRDATA stuff
01315         {
01316             TS->FontName = (char *)FEn[l].Name;
01317 
01318             break;
01319         }
01320     }
01321 */
01322     // store the font reference
01323     TS->FontReference = CDRDATA_DWORD(En->FontRef);
01324 TRACEUSER( "Ben", _T("Font reference = %d\n"), TS->FontReference);
01325     
01326     // font size
01327     TS->FontSize = CDRDATA_WORD(En->FontSize) * CDRCOORDS_TO_MILLIPOINTS;
01328 
01329     // style...
01330     INT32 S = CDRDATA_WORD(En->FontStyle) & cdrfFONTSTYLEV3_WEIGHT_MASK;
01331     switch(S)
01332     {
01333         case cdrfFONTSTYLEV3_WEIGHT_NORMAL:
01334         default:
01335             TS->Bold = FALSE;
01336             TS->Italic = FALSE;
01337             break;
01338 
01339         case cdrfFONTSTYLEV3_WEIGHT_BOLD:
01340             TS->Bold = TRUE;
01341             TS->Italic = FALSE;
01342             break;
01343 
01344         case cdrfFONTSTYLEV3_WEIGHT_ITALIC:
01345             TS->Bold = FALSE;
01346             TS->Italic = TRUE;
01347             break;
01348 
01349         case cdrfFONTSTYLEV3_WEIGHT_BOLDITALIC:
01350             TS->Bold = TRUE;
01351             TS->Italic = TRUE;
01352             break;
01353     }
01354 
01355     // super or subscriptness
01356     if((CDRDATA_WORD(En->FontStyle) & cdrfFONTSTYLEV3_FLAG_SUPERSCRIPT) != 0)
01357     {
01358         TS->Script = CDRSCRIPT_SUPER;
01359     }
01360     else if((CDRDATA_WORD(En->FontStyle) & cdrfFONTSTYLEV3_FLAG_SUPERSCRIPT) != 0)
01361     {
01362         TS->Script = CDRSCRIPT_SUB;
01363     }
01364 
01365     // the line spacing is a para wide thingy, so we need to reworkout the linespace value
01366     // the line spacing value is a percentage of 120% of the font size
01367     TS->LineSpace = (TS->FontSize * (12 * TS->ParaLineSpacePercent)) / 1000;
01368 
01369     return TRUE;
01370 }
01371 
01372 
01373 /********************************************************************************************
01374 
01375 >   BOOL CDRFilter::GetTextStyleFromCDRStyle(CDRTextStyle *TS, WORD StyleRef, BOOL SearchForParent = TRUE)
01376 
01377     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01378     Created:    27/04/95
01379     Inputs:     
01380     Returns:    error flag
01381     Purpose:    gets a text style from a CDR style. If it can't be found, you get the
01382                 default text style. If SearchForParent is TRUE, the parent style of this
01383                 style will be located
01384     SeeAlso:    
01385 
01386 ********************************************************************************************/
01387 
01388 BOOL CDRFilter::GetTextStyleFromCDRStyle(CDRTextStyle *TS, WORD StyleRef, BOOL SearchForParent)
01389 {
01390     // copy in the default text style
01391     *TS = CDRDefaultTextStyle;
01392 
01393     // find the style
01394     INT32 Size;
01395     cdrfTextStyleHdr *Hdr = (cdrfTextStyleHdr *)Styles.Find(StyleRef, &Size);
01396 
01397     if(Hdr == 0)
01398         return TRUE;        // don't error if it can't be found
01399 
01400     // if necessary, search for the parent style...
01401     if(SearchForParent)
01402     {
01403         if(CDRDATA_WORD(Hdr->Hdr.ObjectType) < 0x7fff)
01404         {
01405             if(!GetTextStyleFromCDRStyle(TS, CDRDATA_WORD(Hdr->Hdr.ObjectType), FALSE))
01406                 return FALSE;
01407         }
01408     }
01409 
01410     // find the font size and stuff.
01411     cdrfTextStyleFont *FontStyle = (cdrfTextStyleFont *)FindDataInObject(&Hdr->Hdr, cdrfTEXTSTYLE_OFFSETTYPE_FONT);
01412     if(FontStyle != 0)
01413     {   
01414         // set fontname
01415 /*      TCHAR *FontName = GetFontName(CDRDATA_WORD(FontStyle->FontRef));
01416         if(FontName != 0)
01417             TS->FontName = FontName;
01418         else
01419             TS->FontName = CDRDefaultFontName;
01420 */
01421         // set font reference
01422         TS->FontReference = CDRDATA_WORD(FontStyle->FontRef);
01423 
01424         // set font size
01425         TS->FontSize = CDRDATA_WORD(FontStyle->FontSize) * CDRCOORDS_TO_MILLIPOINTS;
01426         
01427         // set font bold and italicness
01428         if(Version == CDRVERSION_5)
01429         {
01430             switch(CDRDATA_WORD(FontStyle->FontType))
01431             {
01432                 case cdrfFONTTYPE_BOLD:
01433                     TS->Bold = TRUE;
01434                     TS->Italic = FALSE;
01435                     break;
01436 
01437                 case cdrfFONTTYPE_ITALIC:
01438                     TS->Bold = FALSE;
01439                     TS->Italic = TRUE;
01440                     break;
01441 
01442                 case cdrfFONTTYPE_BOLDITALIC:
01443                     TS->Bold = TRUE;
01444                     TS->Italic = TRUE;
01445                     break;
01446 
01447                 default:
01448                     TS->Bold = FALSE;
01449                     TS->Italic = FALSE;
01450                     break;
01451             }
01452         }
01453         else
01454         {
01455             switch(CDRDATA_WORD(FontStyle->FontType))
01456             {
01457                 case cdrfFONTTYPEV4_BOLD:
01458                     TS->Bold = TRUE;
01459                     TS->Italic = FALSE;
01460                     break;
01461 
01462                 case cdrfFONTTYPEV4_ITALIC:
01463                     TS->Bold = FALSE;
01464                     TS->Italic = TRUE;
01465                     break;
01466 
01467                 case cdrfFONTTYPEV4_BOLDITALIC:
01468                     TS->Bold = TRUE;
01469                     TS->Italic = TRUE;
01470                     break;
01471 
01472                 default:
01473                     TS->Bold = FALSE;
01474                     TS->Italic = FALSE;
01475                     break;
01476             }
01477         }
01478     }
01479 
01480     // find the spacing info
01481     cdrfTextStyleSpacing *Spacing = (cdrfTextStyleSpacing *)FindDataInObject(&Hdr->Hdr, cdrfTEXTSTYLE_OFFSETTYPE_SPACING);
01482     if(Spacing != 0)
01483     {
01484         // set the paragraph line spacing
01485         TS->ParaLineSpacePercent = CDRDATA_SWORD(Spacing->LineSpacing);
01486 
01487     }
01488 
01489     // work out the line spacing for this thingy
01490     // the line spacing value is a percentage of 120% of the font size
01491     TS->LineSpace = (TS->FontSize * (12 * TS->ParaLineSpacePercent)) / 1000;
01492 
01493     // find the alignment
01494     cdrfTextStyleAlignment *Align = (cdrfTextStyleAlignment *)FindDataInObject(&Hdr->Hdr, cdrfTEXTSTYLE_OFFSETTYPE_ALIGNMENT);
01495     if(Align != 0)
01496     {
01497         switch(CDRDATA_WORD(Align->Alignment))
01498         {
01499             case cdrfALIGNMENT_RIGHT:   TS->Just = JRIGHT;  break;
01500             case cdrfALIGNMENT_CENTRE:  TS->Just = JCENTRE; break;
01501             case cdrfALIGNMENT_FULL:    TS->Just = JFULL;   break;
01502             default:                    TS->Just = JLEFT;   break;
01503         }
01504     }
01505     
01506     return TRUE;
01507 }
01508 
01509 
01510 /********************************************************************************************
01511 
01512 >   BOOL CDRFilter::GetTextStyleFromDefn(CDRTextStyle *TS, cdrfTextInfoFontDefn *FontDefn, const CDRTextStyle *BasedOn)
01513 
01514     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01515     Created:    27/04/95
01516     Inputs:     
01517     Returns:    error flag
01518     Purpose:    gets a font style from a font definition stored in a txsm chunk. Anything
01519                 not defined comes from the BasedOn style.
01520     SeeAlso:    
01521 
01522 ********************************************************************************************/
01523 
01524 BOOL CDRFilter::GetTextStyleFromDefn(CDRTextStyle *TS, cdrfTextInfoFontDefn *FontDefn, const CDRTextStyle *BasedOn)
01525 {
01526     // set up the defaults
01527     if(BasedOn != 0)
01528         *TS = *BasedOn;
01529     else
01530         *TS = CDRDefaultTextStyle;
01531 
01532     // add in things which are changed...
01533     if((CDRDATA_WORD(FontDefn->Changes) & cdrfTEXTINFODEFNCHANGES_FONT) != 0)
01534     {
01535         // change the font reference
01536 /*      TCHAR *NewName = GetFontName(CDRDATA_WORD(FontDefn->FontRef));
01537 
01538         if(NewName != 0)
01539             TS->FontName = NewName;
01540 */
01541         TS->FontReference = CDRDATA_WORD(FontDefn->FontRef);
01542     }
01543 
01544     if((CDRDATA_WORD(FontDefn->Changes) & cdrfTEXTINFODEFNCHANGES_SIZE) != 0)
01545     {
01546         // new font size
01547         TS->FontSize = CDRDATA_WORD(FontDefn->FontSize) * CDRCOORDS_TO_MILLIPOINTS;
01548     }
01549 
01550     if((CDRDATA_WORD(FontDefn->Changes) & cdrfTEXTINFODEFNCHANGES_ATTR) != 0)
01551     {
01552         // weightness of the font
01553         if(CDRDATA_WORD(FontDefn->FontType) != 0)
01554         {
01555             // set font bold and italicness
01556             switch(CDRDATA_WORD(FontDefn->FontType))
01557             {
01558                 case cdrfFONTTYPE_BOLD:
01559                     TS->Bold = TRUE;
01560                     TS->Italic = FALSE;
01561                     break;
01562 
01563                 case cdrfFONTTYPE_ITALIC:
01564                     TS->Bold = FALSE;
01565                     TS->Italic = TRUE;
01566                     break;
01567 
01568                 case cdrfFONTTYPE_BOLDITALIC:
01569                     TS->Bold = TRUE;
01570                     TS->Italic = TRUE;
01571                     break;
01572 
01573                 default:
01574                     TS->Bold = FALSE;
01575                     TS->Italic = FALSE;
01576                     break;
01577             }
01578         }
01579     
01580         // new attributes
01581         if(FontDefn->FontAttr.Underline != cdrfLINETYPE_NONE
01582                 || FontDefn->FontAttr.Overline != cdrfLINETYPE_NONE
01583                 || FontDefn->FontAttr.StrikeOut != cdrfLINETYPE_NONE)
01584         {
01585             TS->Underline = TRUE;
01586         }
01587         else
01588         {
01589             TS->Underline = FALSE;
01590         }
01591 
01592         switch(FontDefn->FontAttr.Placement)
01593         {
01594             default:                            TS->Script = CDRSCRIPT_NONE;    break;
01595             case cdrfPLACEMENTTYPE_SUPERSCRIPT: TS->Script = CDRSCRIPT_SUPER;   break;
01596             case cdrfPLACEMENTTYPE_SUBSCRIPT:   TS->Script = CDRSCRIPT_SUB;     break;
01597         }
01598     }
01599 
01600     // the line spacing is a para wide thingy, so we need to reworkout the linespace value
01601     // the line spacing value is a percentage of 120% of the font size
01602     TS->LineSpace = (TS->FontSize * (12 * TS->ParaLineSpacePercent)) / 1000;
01603 
01604     return TRUE;
01605 }
01606 
01607 
01608 /********************************************************************************************
01609 
01610 >   BOOL CDRFilter::ApplyTextAttr(Node *ContextNode, const CDRTextStyle *TS, const CDRTextStyle *BasedOn)
01611 
01612     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01613     Created:    27/04/95
01614     Inputs:     
01615     Returns:    error flag
01616     Purpose:    Applies text attributes to a node from a CDRTextStyle. If BasedOn != 0 then
01617                 the attributes will only be applied if they are different from those
01618                 in *BasedOn.
01619     SeeAlso:    
01620 
01621 ********************************************************************************************/
01622 
01623 BOOL CDRFilter::ApplyTextAttr(Node *ContextNode, const CDRTextStyle *TS, const CDRTextStyle *BasedOn)
01624 {
01625     BOOL CheckExisting = FALSE;
01626 
01627     // if the node has children, then we want to check existing attributes
01628     if(ContextNode->FindFirstChild() != 0)
01629         CheckExisting = TRUE;
01630 
01631     // apply italicness
01632     if(BasedOn == 0 || TS->Italic != BasedOn->Italic)
01633     {
01634         // make a font size attribute
01635         TxtItalicAttribute Attr(TS->Italic);
01636     
01637         // attach
01638         if(!ApplyTextAttrDoApply(ContextNode, &Attr, CheckExisting))
01639             return FALSE;
01640     }
01641 
01642     // apply boldness
01643     if(BasedOn == 0 || TS->Bold != BasedOn->Bold)
01644     {
01645         // make a font size attribute
01646         TxtBoldAttribute Attr(TS->Bold);
01647     
01648         // attach
01649         if(!ApplyTextAttrDoApply(ContextNode, &Attr, CheckExisting))
01650             return FALSE;
01651     }
01652 
01653     // apply underline
01654     if(BasedOn == 0 || TS->Underline != BasedOn->Underline)
01655     {
01656         // make a font size attribute
01657         TxtUnderlineAttribute Attr(TS->Underline);
01658     
01659         // attach
01660         if(!ApplyTextAttrDoApply(ContextNode, &Attr, CheckExisting))
01661             return FALSE;
01662     }
01663 
01664     // apply the scriptness
01665     if(BasedOn == 0 || TS->Script != BasedOn->Script)
01666     {
01667         if(TS->Script != CDRSCRIPT_NONE)
01668         {
01669             TxtScriptAttribute Attr((TS->Script == CDRSCRIPT_SUB)?-0.1:0.33, 0.5);
01670 
01671             // attach
01672             if(!ApplyTextAttrDoApply(ContextNode, &Attr, CheckExisting))
01673                 return FALSE;
01674         }
01675     }
01676 
01677     // apply font size
01678     if(BasedOn == 0 || TS->FontSize != BasedOn->FontSize)
01679     {
01680         // make a font size attribute
01681         TxtFontSizeAttribute Attr(TS->FontSize);
01682     
01683         // attach
01684         if(!ApplyTextAttrDoApply(ContextNode, &Attr, CheckExisting))
01685             return FALSE;
01686     }
01687 
01688     // apply font name
01689 //  if(BasedOn == 0 || TS->FontName != BasedOn->FontName)
01690     if(BasedOn == 0 || TS->FontReference != BasedOn->FontReference)
01691     {
01692         // get a font handle
01693         WORD hTypeface = Fonts.GetHandleForReference(TS->FontReference);
01694         //WORD hTypeface = FONTMANAGER->GetFontHandle(&String_64(TS->FontName)); 
01695 
01696         // make a typeface attribute
01697         TxtFontTypefaceAttribute Attr(hTypeface);
01698     
01699         // attach
01700         if(!ApplyTextAttrDoApply(ContextNode, &Attr, CheckExisting))
01701             return FALSE;
01702     }
01703 
01704     // apply the justification stuff
01705     if((BasedOn == 0 || TS->Just != BasedOn->Just) && TS->Just != JLEFT)
01706     {
01707         // make a justification attribute
01708         TxtJustificationAttribute Attr(TS->Just);
01709     
01710         // attach
01711         if(!ApplyTextAttrDoApply(ContextNode, &Attr, CheckExisting))
01712             return FALSE;
01713     }
01714 
01715     // slap on a aspect ratio thingy so it gets transformed OK
01716     TxtAspectRatioAttribute Attr(1);
01717 
01718     if(!ApplyTextAttrDoApply(ContextNode, &Attr, CheckExisting))
01719         return FALSE;
01720 
01721     return TRUE;
01722 }
01723 
01724 
01725 /********************************************************************************************
01726 
01727 >   BOOL CDRFilter::ApplyTextAttrDoApply(Node *ContextNode, TxtBaseClassAttribute *Attr, BOOL CheckExising)
01728 
01729     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01730     Created:    27/04/95
01731     Inputs:     
01732     Returns:    error flag
01733     Purpose:    Given a text attribute, apply it to a node. If CheckExising is TRUE, the
01734                 existing attributes will be checked, and this attribute will not be applied
01735                 if one of it's type already exists.
01736     SeeAlso:    
01737 
01738 ********************************************************************************************/
01739 
01740 BOOL CDRFilter::ApplyTextAttrDoApply(Node *ContextNode, TxtBaseClassAttribute *Attr, BOOL CheckExisting)
01741 {
01742     // check given attribute
01743     if(Attr == 0)
01744         return FALSE;
01745 
01746     // make a node out of it
01747     NodeAttribute *pNode = Attr->MakeNode();
01748     if(pNode == 0)
01749         return FALSE;
01750 
01751     // if necessary check existing attributes
01752     if(CheckExisting)
01753     {
01754         Node *SearchNode = ContextNode->FindFirstChild();
01755 
01756         // run through it's children
01757         while(SearchNode != 0)
01758         {
01759             if(IS_SAME_CLASS(pNode, SearchNode))
01760             {
01761                 // found an attribute just like the one we're thinking of applying...
01762                 delete pNode;
01763                 return TRUE;        // don't need to do anything more
01764             }
01765 
01766             SearchNode = SearchNode->FindNext();
01767         }
01768     }
01769     
01770     // attach the node
01771     pNode->AttachNode(ContextNode, FIRSTCHILD);
01772     return TRUE;
01773 }
01774 
01775 
01776 /********************************************************************************************
01777 
01778 >   TCHAR *CDRFilter::GetFontName(WORD FontRef)
01779 
01780     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01781     Created:    27/04/95
01782     Inputs:     
01783     Returns:    pointer to font name or 0 for not found
01784     Purpose:    finds a font name
01785     SeeAlso:    
01786 
01787 ********************************************************************************************/
01788 
01789 TCHAR *CDRFilter::GetFontName(WORD FontRef)
01790 {
01791     INT32 Size;
01792     cdrfFontDefn *FD = (cdrfFontDefn *)Fonts.Find(FontRef, &Size);
01793 
01794     if(Version == CDRVERSION_5)
01795     {
01796         if(FD != 0)
01797             return FD->Name;
01798     }
01799     else
01800     {
01801         cdrfFontDefnV4 *FD4 = (cdrfFontDefnV4 *)FD;
01802 
01803         if(FD4 != 0)
01804             return FD4->Name;
01805     }
01806 
01807     return 0;
01808 }
01809 
01810 
01811 /********************************************************************************************
01812 
01813 >   BOOL CDRFontnameStore::AddChunkToStore(RIFFFile *RIFF, CDRVersion Version)
01814 
01815     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01816     Created:    22 03 95
01817     Inputs:     A RIFFFile object
01818     Returns:    error flag
01819     Purpose:    Stores fontname chunks for the CDRFilter class and caches the name
01820     SeeAlso:    CDRFilter
01821 
01822 ********************************************************************************************/
01823 
01824 BOOL CDRFontnameStore::AddChunkToStore(RIFFFile *RIFF, CDRVersion Version)
01825 {
01826     if(RIFF->GetObjType() != RIFFOBJECTTYPE_CHUNK)
01827     {
01828         ERROR2(FALSE, "CDRAttributeStore::AddChunkToStore called without a chunk in the RIFFFile");
01829     }
01830 
01831     // get a new item obect
01832     CDRFontnameStoredItem *Item = new CDRFontnameStoredItem;
01833 
01834     if(Item == 0)
01835         return FALSE;
01836 
01837     // get the data of the RIFF chunk
01838     if(!Item->Aquire(RIFF))
01839     {
01840         delete Item;
01841         return FALSE;
01842     }
01843 
01844     Item->Size = RIFF->GetObjSize();
01845 
01846     // and add the new item to the list
01847     AddTail(Item);
01848 
01849     // cache the font name
01850     DWORD Reference;
01851     TCHAR *Name = 0;
01852     if(Version == CDRVERSION_5)
01853     {
01854         cdrfFontDefn *FD = (cdrfFontDefn *)Item->Block;
01855 
01856         if(FD == 0)
01857             return FALSE;
01858 
01859         Reference = FD->Reference;  
01860         Name = FD->Name;
01861     }
01862     else if(Version == CDRVERSION_4)
01863     {
01864         cdrfFontDefnV4 *FD = (cdrfFontDefnV4 *)Item->Block;
01865 
01866         if(FD == 0)
01867             return FALSE;
01868     
01869         Reference = FD->Reference;  
01870         Name = FD->Name;
01871     }
01872 
01873 //  if(Name != 0)
01874 //      FONTMANAGER->CacheNamedFont(&String_64(Name));
01875 
01876     // get the item ready...
01877     return Item->GetTypefaceForUse(Reference, Name);
01878 }
01879 
01880 /********************************************************************************************
01881 
01882 >   BOOL CDRFontnameStore::AddFontToStore(DWORD Reference, TCHAR *Fontname)
01883 
01884     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01885     Created:    03 01 96
01886     Inputs:     Fontname
01887     Returns:    error flag
01888     Purpose:    Adds another fontname to the list
01889     SeeAlso:    CDRFilter
01890 
01891 ********************************************************************************************/
01892 
01893 BOOL CDRFontnameStore::AddFontToStore(DWORD Reference, TCHAR *Fontname)
01894 {
01895 TRACEUSER( "Ben", _T("**** attempting to add %s\n"), Fontname);
01896     // get a new item obect
01897     CDRFontnameStoredItem *Item = new CDRFontnameStoredItem;
01898 
01899     if(Item == 0)
01900         return FALSE;
01901 
01902     // and add the new item to the list
01903     AddTail(Item);
01904 
01905     // get the item ready...
01906     return Item->GetTypefaceForUse(Reference, Fontname);
01907 }
01908 
01909 /********************************************************************************************
01910 
01911 >   virtual WORD CDRFontnameStore::GetHandleForReference(DWORD Reference)
01912 
01913     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01914     Created:    03 01 96
01915     Inputs:     The reference of the interesting font
01916     Returns:    The handle of the font.
01917     Purpose:    To get a handle for use in an attribute given a CDR reference
01918     SeeAlso:    CDRFilter
01919 
01920 ********************************************************************************************/
01921 
01922 WORD CDRFontnameStore::GetHandleForReference(DWORD Reference)
01923 {
01924     // scan the list comparing references with the stored items.
01925     CDRFontnameStoredItem *Item;
01926 
01927     if(IsEmpty())
01928         return 0;       // no items in the list
01929     
01930     Item = (CDRFontnameStoredItem *)GetHead();
01931 
01932     // scan though the list looking for the reference
01933     while(Item != 0)
01934     {
01935         if(Item->Reference == Reference)
01936         {
01937             return Item->hTypeface;
01938         }
01939 
01940         Item = (CDRFontnameStoredItem *)GetNext(Item);
01941     }
01942 
01943 
01944     // nothing helpful found - return the default font handle
01945     return FONTMANAGER->GetFont()->GetFontHandle();
01946 }
01947 
01948 /********************************************************************************************
01949 
01950 >   class CDRFontnameStoredItemEnumer : public EnumFonts
01951 
01952     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01953     Created:    03 01 96
01954     Purpose:    A class for those tricky font enumerations in the CDR filter
01955     SeeAlso:    CDRFilter
01956 
01957 ********************************************************************************************/
01958 
01959 class CDRFontnameStoredItemEnumer : public EnumAllFonts
01960 {
01961 public:
01962     CDRFontnameStoredItemEnumer() {TheFontName = 0; Found = FALSE;};
01963     
01964     TCHAR *TheFontName;
01965     FontClass TheFontClass;                             
01966     BOOL Found;
01967     String_64 TheRealFontName;
01968 
01969     BOOL NewFont(FontClass Class, ENUMLOGFONT FAR* lpelf, NEWTEXTMETRIC FAR* lpntm);
01970 
01971 };
01972 
01973 BOOL CDRFontnameStoredItemEnumer::NewFont(FontClass Class, ENUMLOGFONT FAR* lpelf, NEWTEXTMETRIC FAR* lpntm)
01974 {
01975     // got it already?
01976     if(Found)
01977         return TRUE;
01978     
01979     // check we've got a nice font name
01980     ERROR3IF(TheFontName == 0, "Set up that silly little font name first, there's a good chap");
01981 
01982 TRACEUSER( "Ben", _T("against %s\n"), lpelf->elfLogFont.lfFaceName);
01983     // do a case insenstive compare of the two fontnames
01984     if(_tcsncicmp(TheFontName, lpelf->elfLogFont.lfFaceName, 64) == 0)
01985     {
01986 TRACEUSER( "Ben", _T("MATCH\n"));
01987         // then we've found the thingy we want - let's have it...
01988         Found = TRUE;
01989         
01990         // store the font class
01991         TheFontClass = Class;
01992 
01993         // copy across the real font name
01994         TheRealFontName = lpelf->elfLogFont.lfFaceName;
01995     }
01996 
01997     return TRUE;
01998 }
01999 
02000 
02001 /********************************************************************************************
02002 
02003 >   BOOL CDRFontnameStoredItem::GetTypefaceForUse(DWORD Reference, TCHAR *FontName)
02004 
02005     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02006     Created:    03 01 96
02007     Inputs:     CDR file font reference, pointer to font name
02008     Returns:    error flag
02009     Purpose:    Sets the Reference and hTypeface variables of the entry.
02010                 It enumerates the font name to get the right class and capitalisation of
02011                 the name, then caches it with the fontmanager. It then gets a typeface
02012                 handle for it, which is stored for future retreval.
02013     SeeAlso:    CDRFilter
02014 
02015 ********************************************************************************************/
02016 
02017 BOOL CDRFontnameStoredItem::GetTypefaceForUse(DWORD tReference, TCHAR *FontName)
02018 {
02019     Reference = tReference;
02020 
02021     // OK, so we need to enumerate all those lovely little font tickles, and
02022     // would like to know the real font name and the lovelyness known as the
02023     // font class thingy. Splendid!
02024 
02025     // first of all, catch your font.
02026     CDRFontnameStoredItemEnumer EnumThing;
02027     EnumThing.TheFontName = FontName;
02028     EnumThing.Execute();
02029 
02030     // did we actually get one?
02031     if(EnumThing.Found == FALSE)
02032     {
02033         // make up a default typeface handle...
02034         hTypeface = FONTMANAGER->GetFont()->GetFontHandle();
02035         
02036         return TRUE;
02037     }
02038 
02039     // righteho, we now have a nice font name... so let's cache the thingy and get
02040     // ourselves a nice handle.
02041     hTypeface = FONTMANAGER->CacheNamedFont(&EnumThing.TheRealFontName);
02042 TRACEUSER( "Ben", _T("Reference = %d, Real font name is '%s', handle is %d\n"), tReference, (TCHAR *)EnumThing.TheRealFontName, hTypeface);
02043 
02044     // check to see nothing's gone terriably wrong
02045     if(!HNDLVALID(hTypeface))
02046         return FALSE;
02047 
02048     return TRUE;
02049 }
02050 
02051 /********************************************************************************************
02052 
02053 >   CDRBBoxList::CDRBBoxList()
02054 
02055     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02056     Created:    01/05/95
02057     Inputs:     -
02058     Returns:    -
02059     Purpose:    constructor
02060     SeeAlso:    CDRFilter
02061 
02062 ********************************************************************************************/
02063 
02064 CDRBBoxList::CDRBBoxList()
02065 {
02066 }
02067 
02068 
02069 /********************************************************************************************
02070 
02071 >   CDRBBoxList::~CDRBBoxList()
02072 
02073     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02074     Created:    01/05/95
02075     Inputs:     -
02076     Returns:    -
02077     Purpose:    destructor
02078     SeeAlso:    CDRFilter
02079 
02080 ********************************************************************************************/
02081 
02082 CDRBBoxList::~CDRBBoxList()
02083 {
02084 }
02085 
02086 
02087 /********************************************************************************************
02088 
02089 >   CDRBBoxListItem::CDRBBoxListItem()
02090 
02091     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02092     Created:    01/05/95
02093     Inputs:     -
02094     Returns:    -
02095     Purpose:    constructor
02096     SeeAlso:    CDRFilter
02097 
02098 ********************************************************************************************/
02099 
02100 CDRBBoxListItem::CDRBBoxListItem()
02101 {
02102     pNode = 0;
02103 }
02104 
02105 
02106 /********************************************************************************************
02107 
02108 >   CDRBBoxListItem::~CDRBBoxListItem()
02109 
02110     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02111     Created:    01/05/95
02112     Inputs:     -
02113     Returns:    -
02114     Purpose:    destructor
02115     SeeAlso:    CDRFilter
02116 
02117 ********************************************************************************************/
02118 
02119 CDRBBoxListItem::~CDRBBoxListItem()
02120 {
02121 }
02122 
02123 
02124 /********************************************************************************************
02125 
02126 >   BOOL CDRBBoxList::Add(Node *N, DocRect *BBox, Justification Just)
02127 
02128     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02129     Created:    01/05/95
02130     Inputs:     node the bounding box is associated with, bounding box
02131     Returns:    error flag
02132     Purpose:    Adds a bounding box to the list
02133     SeeAlso:    CDRFilter
02134 
02135 ********************************************************************************************/
02136 
02137 BOOL CDRBBoxList::Add(Node *N, DocRect *BBox, Justification Just)
02138 {
02139     CDRBBoxListItem *Item = new CDRBBoxListItem;
02140 
02141     Item->pNode = N;
02142     Item->BBox = *BBox;
02143 
02144     // alter the BBox for various justification options
02145     if(Just == JCENTRE)
02146     {
02147         BBox->Translate(0 - (BBox->Width() / 2), 0);
02148     }
02149     else if(Just == JRIGHT)
02150     {
02151         BBox->Translate(0 - BBox->Width(), 0);
02152     }
02153 
02154     AddTail(Item);
02155 
02156     return TRUE;
02157 }
02158 
02159 /********************************************************************************************
02160 
02161 >   BOOL CDRBBoxList::Find(Node *N, DocRect *BBox)
02162 
02163     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02164     Created:    01/05/95
02165     Inputs:     node to look up, a DocRect for the result
02166     Returns:    whether it found an entry for this node
02167     Purpose:    Finds a bounding box from a list of bounding boxes
02168     SeeAlso:    CDRFilter
02169 
02170 ********************************************************************************************/
02171 
02172 BOOL CDRBBoxList::Find(Node *N, DocRect *BBox)
02173 {
02174     CDRBBoxListItem *Item = (CDRBBoxListItem *)GetHead();
02175 
02176     while(Item != 0)
02177     {
02178         if(Item->pNode == N)
02179         {
02180             if(BBox != 0)
02181             {
02182                 *BBox = Item->BBox;
02183             }
02184             return TRUE;
02185         }
02186 
02187         Item = (CDRBBoxListItem *)GetNext(Item);
02188     }
02189 
02190     return FALSE;
02191 }
02192 
02193 
02194 /********************************************************************************************
02195 
02196 >   DocRect *CDRBBoxList::Find(Node *N)
02197 
02198     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02199     Created:    01/05/95
02200     Inputs:     node to look up
02201     Returns:    DocRect or 0, can be modified
02202     Purpose:    Finds a stored bounding box, returning a pointer to the DocRect which can be
02203                 modified, for example, as a result of a transformation
02204     SeeAlso:    CDRFilter
02205 
02206 ********************************************************************************************/
02207 
02208 DocRect *CDRBBoxList::Find(Node *N)
02209 {
02210     CDRBBoxListItem *Item = (CDRBBoxListItem *)GetHead();
02211 
02212     while(Item != 0)
02213     {
02214         if(Item->pNode == N)
02215         {
02216             return &Item->BBox;
02217         }
02218 
02219         Item = (CDRBBoxListItem *)GetNext(Item);
02220     }
02221 
02222     return 0;
02223 }
02224 
02225 
02226 /********************************************************************************************
02227 
02228 >   BOOL CDRFilter::ProcessTextList4()
02229 
02230     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02231     Created:    12/05/95
02232     Inputs:     -
02233     Returns:    error flag
02234     Purpose:    Processes the list of text objects for a version 4 CDR file creating text
02235                 lines and textchars with partially applied attributes.
02236     SeeAlso:    CDRFilter
02237 
02238 ********************************************************************************************/
02239 
02240 BOOL CDRFilter::ProcessTextList4()
02241 {
02242     // What we've got...
02243     //  btxt                the list we're current on
02244     //      strl            contains text for a paragraph object
02245     //          btid        the id of the text
02246     //          parl        a pargraph
02247     //              para    paragraph info
02248     // then any number of...
02249     //              bnch    n plain characters
02250     //              bsch    a character with styles applied to it
02251 
02252     ERROR3IF(RIFF->GetObjType() != RIFFOBJECTTYPE_LISTSTART || RIFF->GetObjChunkType() != cdrT_btxt,
02253             "ProcessTextList4 called in the wrong context");
02254 
02255     UINT32 EndLevel = RIFF->GetObjLevel();
02256 
02257     do {
02258         if(RIFF->GetObjType() == RIFFOBJECTTYPE_LISTSTART && RIFF->GetObjChunkType() == cdrT_strl)
02259         {
02260             if(!ProcessTextListItem4())
02261                 return FALSE;
02262         }
02263 
02264         if(!RIFF->NextObject())
02265             return FALSE;
02266     
02267     } while(RIFF->GetObjType() != RIFFOBJECTTYPE_LISTEND || RIFF->GetObjLevel() > EndLevel);
02268 
02269     return TRUE;
02270 }
02271 
02272 
02273 /********************************************************************************************
02274 
02275 >   BOOL CDRFilter::ProcessTextListItem4()
02276 
02277     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02278     Created:    12/05/95
02279     Inputs:     -
02280     Returns:    error flag
02281     Purpose:    Processes a item from the list of text objects for a version 4 CDR file
02282                 creating text lines and textchars with partially applied attributes.
02283     SeeAlso:    CDRFilter
02284 
02285 ********************************************************************************************/
02286 
02287 BOOL CDRFilter::ProcessTextListItem4()
02288 {
02289     // What we've got...
02290     //  strl            contains text for a paragraph object
02291     //      btid        the id of the text
02292     //      parl        a pargraph
02293     //          para    paragraph info
02294     // then any number of...
02295     //          bnch    n plain characters
02296     //          bsch    a character with styles applied to it
02297 
02298     ERROR3IF(RIFF->GetObjType() != RIFFOBJECTTYPE_LISTSTART || RIFF->GetObjChunkType() != cdrT_strl,
02299             "ProcessTextListItem4 called in the wrong context");
02300 
02301     UINT32 EndLevel = RIFF->GetObjLevel();
02302 
02303     TextLine *FirstLine = 0;
02304     TextLine *CurrentLine = 0;
02305     INT32 MaxFirstLineSpace = 0;
02306     BOOL IsFirstLine = TRUE;
02307 
02308     WORD ID = 0;
02309 
02310     CDRTextStyle BaseStyle = CDRDefaultTextStyle;
02311 
02312     do {
02313     
02314         if(RIFF->GetObjType() == RIFFOBJECTTYPE_CHUNK)
02315         {
02316             switch(RIFF->GetObjChunkType())
02317             {
02318                 case cdrT_btid:
02319                     // id of thingy, store
02320                     {
02321                         if(!RIFF->AquireChunkData())
02322                             return FALSE;
02323 
02324                         WORD *Thingy = (WORD *)RIFF->GetAquiredData();
02325 
02326                         ERROR2IF(Thingy == 0, FALSE, "Couldn't get aquired data");
02327 
02328                         ID = CDRDATA_WORD(*Thingy);
02329                     }
02330                     break;
02331                 
02332                 case cdrT_para:
02333                     {
02334                         // do we need an end of line node for something?
02335                         if(CurrentLine != 0)
02336                         {
02337                             EOLNode *EOL = new EOLNode(CurrentLine, LASTCHILD);
02338 
02339                             if(EOL == 0)
02340                                 return FALSE;
02341                         }
02342 
02343                         // new paragraph start - create a new line
02344                         if(CurrentLine == 0)
02345                         {
02346                             CurrentLine = new TextLine;
02347                         }
02348                         else
02349                         {
02350                             CurrentLine = new TextLine(CurrentLine, NEXT);
02351                         }
02352 
02353                         if(CurrentLine == 0)
02354                             return FALSE;
02355 
02356                         if(FirstLine == 0)
02357                             FirstLine = CurrentLine;
02358                         else
02359                             IsFirstLine = FALSE;
02360 
02361                         // get the style of this paragraph
02362                         if(!RIFF->AquireChunkData())
02363                             return FALSE;
02364 
02365                         cdrfParaDefnV4 *Para = (cdrfParaDefnV4 *)RIFF->GetAquiredData();
02366                         if(Para == 0)
02367                             return FALSE;
02368 
02369                         if(!GetTextStyleFromCDRStyle(&BaseStyle, CDRDATA_WORD(Para->Style)))
02370                             return FALSE;
02371 
02372                         if(IsFirstLine && BaseStyle.LineSpace > MaxFirstLineSpace)
02373                             MaxFirstLineSpace = BaseStyle.LineSpace;
02374                     }
02375                     break;
02376                 
02377                 case cdrT_bnch:
02378                     // a load of characters
02379                     ERROR2IF(CurrentLine == 0, FALSE, "CurrentLine is zero when characters found");
02380                     
02381                     {
02382                         // get the chunk data
02383                         if(!RIFF->AquireChunkData())
02384                             return FALSE;
02385                     
02386                         // process it...
02387                         cdrfTextListCharV4 *Chars = (cdrfTextListCharV4 *)RIFF->GetAquiredData();
02388                         ERROR2IF(Chars == 0, FALSE, "no data from aquire data");
02389 
02390                         INT32 NChars = RIFF->GetObjSize() / sizeof(cdrfTextListCharV4);
02391 
02392                         // add all the nice characters we've got
02393                         for(INT32 l = 0; l < NChars; l++)
02394                         {
02395                             if(CDRDATA_WORD(Chars[l].Char) >= ' ')
02396                             {
02397                                 TextChar *NewChar = new TextChar(CurrentLine, LASTCHILD, CDRDATA_WORD(Chars[l].Char));
02398 
02399                                 if(NewChar == 0)
02400                                     return FALSE;
02401 
02402                                 // apply attributes
02403                                 if(!ApplyTextAttr(NewChar, &BaseStyle, 0))
02404                                     return FALSE;
02405                             }
02406                         }
02407                     }                   
02408                     break;
02409 
02410                 case cdrT_bsch:
02411                     // a character with styles attached
02412                     ERROR2IF(CurrentLine == 0, FALSE, "CurrentLine is zero when characters found");
02413                     {
02414                         // get the chunk data
02415                         if(!RIFF->AquireChunkData())
02416                             return FALSE;
02417                     
02418                         // process it...
02419                         cdrfTextListCharStyledV4 *Char = (cdrfTextListCharStyledV4 *)RIFF->GetAquiredData();
02420                         ERROR2IF(Char == 0, FALSE, "no data from aquire data");
02421 
02422                         if(CDRDATA_WORD(Char->Char) >= ' ')
02423                         {
02424                             TextChar *NewChar = new TextChar(CurrentLine, LASTCHILD, CDRDATA_WORD(Char->Char));
02425 
02426                             if(NewChar == 0)
02427                                 return FALSE;
02428 
02429                             // apply attributes to it
02430                             CDRTextStyle ThisStyle = BaseStyle;
02431 
02432                             // font size
02433                             ThisStyle.FontSize = CDRDATA_WORD(Char->FontSize) * CDRCOORDS_TO_MILLIPOINTS;
02434     
02435                             // font name
02436 /*                          TCHAR *FontName = GetFontName(CDRDATA_WORD(Char->FontRef));
02437                             if(FontName != 0)
02438                             {
02439                                 ThisStyle.FontName = FontName;
02440                             }
02441 */
02442                             ThisStyle.FontReference = CDRDATA_WORD(Char->FontRef);
02443 
02444                             // bold and italicness
02445                             switch(Char->Weight)
02446                             {
02447                                 case cdrfFONTTYPEV4_BOLD:
02448                                     ThisStyle.Bold = TRUE;
02449                                     ThisStyle.Italic = FALSE;
02450                                     break;
02451 
02452                                 case cdrfFONTTYPEV4_ITALIC:
02453                                     ThisStyle.Bold = FALSE;
02454                                     ThisStyle.Italic = TRUE;
02455                                     break;
02456 
02457                                 case cdrfFONTTYPEV4_BOLDITALIC:
02458                                     ThisStyle.Bold = TRUE;
02459                                     ThisStyle.Italic = TRUE;
02460                                     break;
02461 
02462                                 default:
02463                                     ThisStyle.Bold = FALSE;
02464                                     ThisStyle.Italic = FALSE;
02465                                     break;
02466                             }
02467 
02468                             // placement
02469                             switch(Char->Placement)
02470                             {
02471                                 default:
02472                                 case cdrfPLACEMENTV4_NONE:  ThisStyle.Script = CDRSCRIPT_NONE;  break;
02473                                 case cdrfPLACEMENTV4_SUPER: ThisStyle.Script = CDRSCRIPT_SUPER; break;
02474                                 case cdrfPLACEMENTV4_SUB:   ThisStyle.Script = CDRSCRIPT_SUB;   break;
02475                             }
02476 
02477                             // apply attributes
02478                             if(!ApplyTextAttr(NewChar, &ThisStyle, 0))
02479                                 return FALSE;
02480 
02481                             // sort out max first line space
02482                             if(IsFirstLine && ThisStyle.LineSpace > MaxFirstLineSpace)
02483                                 MaxFirstLineSpace = ThisStyle.LineSpace;
02484                         }
02485                     }
02486                     break;
02487 
02488                 default:
02489                     break;
02490             }
02491         }
02492 
02493         UpdateProgress();
02494 
02495         if(!RIFF->NextObject())
02496             return FALSE;
02497     
02498     } while(RIFF->GetObjType() != RIFFOBJECTTYPE_LISTEND || RIFF->GetObjLevel() > EndLevel);
02499 
02500     if(CurrentLine != 0)
02501     {
02502         // pop some ending stuff on it
02503         CaretNode *Caret = new CaretNode(CurrentLine, LASTCHILD);
02504         EOLNode *EOL = new EOLNode(CurrentLine, LASTCHILD);
02505         if(Caret == 0 || EOL == 0)
02506             return FALSE;
02507     }
02508 
02509     if(FirstLine != 0)
02510     {
02511         // got something - add it to the list of text stuff
02512         CDRVectorStoredItem *Item = new CDRVectorStoredItem;
02513 
02514         if(Item == 0)
02515             return FALSE;
02516 
02517         // store objects
02518         Item->Objects = FirstLine;
02519         Item->Reference = ID;
02520 
02521         // pop max first line in the bbox
02522         Item->BBox.hi.y = MaxFirstLineSpace;
02523 
02524         TextV4.AddTail(Item);
02525     }
02526     
02527     return TRUE;
02528 }
02529 
02530 
02531 /********************************************************************************************
02532 
02533 >   BOOL CDRFilter::MakeTextOnPathLinkList()
02534 
02535     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02536     Created:    09/06/95
02537     Inputs:     -
02538     Returns:    error flag
02539     Purpose:    creates the list of paths which should be linked to text stories to get
02540                 text on paths.
02541     SeeAlso:    CDRFilter
02542 
02543 ********************************************************************************************/
02544 
02545 BOOL CDRFilter::MakeTextOnPathLinkList()
02546 {
02547     if(LinkTable == 0)
02548         return TRUE;        // no link table, no list...
02549 
02550     // run through the table creating entries
02551     cdrfLinkTableHdr *Table = (cdrfLinkTableHdr *)LinkTable;
02552     INT32 Entries = CDRDATA_WORD(Table->Entries);
02553     WORD *Offsets = (WORD *)(LinkTable + CDRDATA_WORD(Table->OffsetsOffset));
02554 
02555     if(Version != CDRVERSION_3)
02556     {
02557         // make for versions 4 and 5
02558         for(INT32 l = 0; l < Entries; l++)
02559         {
02560             cdrfLinkTableEntryTextOnPath *En = (cdrfLinkTableEntryTextOnPath *)(LinkTable + CDRDATA_WORD(Offsets[l]));
02561 
02562             if(En->Type == cdrfLINKTABLEENTRY_TEXTONPATH)
02563             {
02564                 // make a new list item for this thingy
02565                 CDRTextOnPathLink *Item = new CDRTextOnPathLink;
02566 
02567                 if(Item == 0)
02568                     return FALSE;
02569 
02570                 // pop in the serial numbers
02571                 Item->PathSerialNumber = CDRDATA_WORD(En->PathSerialNumber);
02572                 Item->TextSerialNumber = CDRDATA_WORD(En->TextSerialNumber);
02573 
02574                 // add the item to the list
02575                 TextOnPathLinks.AddTail(Item);
02576             }
02577         }
02578     }
02579     else
02580     {
02581         // make for version 3
02582         for(INT32 l = 0; l < Entries; l++)
02583         {
02584             cdrfLinkTableEntryTextOnPathV3 *En = (cdrfLinkTableEntryTextOnPathV3 *)(LinkTable + CDRDATA_WORD(Offsets[l]));
02585 
02586             if(En->Type == cdrfLINKTABLEENTRYV3_TEXTONPATH)
02587             {
02588                 // make a new list item for this thingy
02589                 CDRTextOnPathLink *Item = new CDRTextOnPathLink;
02590 
02591                 if(Item == 0)
02592                     return FALSE;
02593 
02594                 // pop in the serial numbers
02595                 Item->PathSerialNumber = CDRDATA_WORD(En->PathSerialNumber);
02596                 Item->TextSerialNumber = CDRDATA_WORD(En->TextSerialNumber);
02597 
02598                 // add the item to the list
02599                 TextOnPathLinks.AddTail(Item);
02600             }
02601         }
02602     }
02603     
02604     return TRUE;
02605 }
02606 
02607 
02608 /********************************************************************************************
02609 
02610 >   BOOL CDRFilter::AttachTextToPaths()
02611 
02612     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02613     Created:    09/06/95
02614     Inputs:     -
02615     Returns:    error flag
02616     Purpose:    attachs paths to text stories from the list of links.
02617     SeeAlso:    CDRFilter
02618 
02619 ********************************************************************************************/
02620 
02621 BOOL CDRFilter::AttachTextToPaths()
02622 {
02623     // set attributes to no colours - we mustn't render these here paths
02624     if(!SetFillColour(DocColour(COLOUR_TRANS)))
02625         return FALSE;
02626     if(!SetLineColour(DocColour(COLOUR_TRANS)))
02627         return FALSE;
02628     CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = TRUE;
02629 
02630     // go through the entries in the list...
02631     CDRTextOnPathLink *Item = (CDRTextOnPathLink *)TextOnPathLinks.GetHead();
02632 
02633     while(Item != 0)
02634     {
02635         // if this is complete, process it
02636         if(Item->pPath != 0 && Item->pTextStory != 0)
02637         {
02638             // both things were found, so join them up nicely...
02639 
02640             // make a copy of the path
02641             NodePath *pPath;
02642             if(!Item->pPath->NodeCopy((Node **)&pPath))
02643                 return FALSE;
02644 
02645             // delete it's old attributes
02646             pPath->DeleteChildren(pPath->FindFirstChild());
02647 
02648             // apply some attributes to the path
02649             pPath->InkPath.IsFilled = FALSE;
02650             pPath->InkPath.IsStroked = FALSE;
02651             if(!AttributeManager::ApplyBasedOnDefaults(pPath, CurrentAttrs))
02652                 return FALSE;
02653 
02654             // and attach the nodes together
02655             Node *pFirstLine = Item->pTextStory->FindFirstChild(CC_RUNTIME_CLASS(TextLine));
02656             ERROR2IF(pFirstLine == 0, FALSE, "TextStory had no line when attaching path");
02657             pPath->AttachNode(pFirstLine, PREV);
02658 
02659             // now sort out justification along the path
02660             if(Item->Justi != JLEFT)
02661             {
02662                 // knock up an attribute and pop it on
02663                 TxtJustificationAttribute Attr(Item->Justi);
02664                 NodeAttribute *pNode = Attr.MakeNode();
02665                 if(pNode == 0)
02666                     return FALSE;
02667                 pNode->AttachNode(Item->pTextStory, FIRSTCHILD);
02668             }
02669             else
02670             {
02671                 TRACEUSER( "Ben", _T("Text on path not completed: path serial = %d, path ptr = %X\ntext serial = %d, text ptr = %X\n\n"), Item->PathSerialNumber, Item->pPath, Item->TextSerialNumber, Item->pTextStory);
02672             }
02673         
02674             // and the positioning
02675             Item->pTextStory->SetImportBaseShift((BaseShiftEnum)Item->Position);
02676         }
02677         
02678         // next!
02679         Item = (CDRTextOnPathLink *)TextOnPathLinks.GetNext(Item);
02680     }
02681 
02682     return TRUE;
02683 }
02684 
02685 
02686 /********************************************************************************************
02687 
02688 >   BOOL CDRFilter::CheckTextForLinks(TextStory *pTextStory, cdrfOffsetHeader *Header)
02689 
02690     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02691     Created:    09/06/95
02692     Inputs:     -
02693     Returns:    error flag
02694     Purpose:    checks to see if this text story is in the link table
02695     SeeAlso:    CDRFilter
02696 
02697 ********************************************************************************************/
02698 
02699 BOOL CDRFilter::CheckTextForLinks(TextStory *pTextStory, cdrfOffsetHeader *Header)
02700 {
02701     if(IsTextOnAPath != TRUE)
02702         return TRUE;        // not on a path, so don't search
02703 
02704     // go through the entries in the list...
02705     CDRTextOnPathLink *Item = (CDRTextOnPathLink *)TextOnPathLinks.GetHead();
02706 
02707     while(Item != 0)
02708     {
02709         // does this link refer to this text story?
02710         if(SerialNumber == Item->TextSerialNumber)
02711         {
02712             // yep - make the entry refer to this text story
02713             Item->pTextStory = pTextStory;
02714 
02715             // set up some justification and positioning stuff
02716             cdrfTextOnPathInfo *Info;
02717             if((Info = (cdrfTextOnPathInfo *)FindDataInObject(Header, cdrfOBJOFFSETTYPE_PATHTEXT1)) != 0)
02718             {
02719                 switch(CDRDATA_WORD(Info->Alignment))
02720                 {
02721                     case cdrfTEXTONPATHALIGN_RIGHT:
02722                         Item->Justi = JRIGHT;
02723                         break;
02724 
02725                     case cdrfTEXTONPATHALIGN_CENTRE:
02726                         Item->Justi = JCENTRE;
02727                         break;
02728 
02729                     default:
02730                     case cdrfTEXTONPATHALIGN_LEFT:
02731                         Item->Justi = JLEFT;
02732                         break;
02733                 }
02734 
02735                 switch(CDRDATA_WORD(Info->Position))
02736                 {
02737                     case cdrfTEXTONPATHPOS_BOTTOM:
02738                         Item->Position = AlignDescenders;
02739                         break;
02740 
02741                     case cdrfTEXTONPATHPOS_TOP:
02742                         Item->Position = AlignAscenders;
02743                         break;
02744 
02745                     case cdrfTEXTONPATHPOS_CENTRE:
02746                         Item->Position = AlignCentres;
02747                         break;
02748 
02749                     case cdrfTEXTONPATHPOS_BASELINE:
02750                     default:
02751                         Item->Position = AlignBaseline;
02752                         break;
02753 
02754                 }
02755             }
02756 
02757             // return now so we don't get duplicates...
02758             return TRUE;
02759         }
02760         
02761         // next!
02762         Item = (CDRTextOnPathLink *)TextOnPathLinks.GetNext(Item);
02763     }
02764     
02765     return TRUE;
02766 }
02767 
02768 
02769 /********************************************************************************************
02770 
02771 >   CDRTextOnPathLink::CDRTextOnPathLink()
02772 
02773     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02774     Created:    09/06/95
02775     Inputs:     -
02776     Returns:    -
02777     Purpose:    constructor
02778     SeeAlso:    CDRFilter
02779 
02780 ********************************************************************************************/
02781 
02782 CDRTextOnPathLink::CDRTextOnPathLink()
02783 {
02784     PathSerialNumber = -1;
02785     pPath = 0;
02786     TextSerialNumber = -1;
02787     pTextStory = 0;
02788     Justi = JLEFT;
02789     Position = AlignBaseline;
02790 }
02791 
02792 
02793 /********************************************************************************************
02794 
02795 >   CDRTextOnPathLink::~CDRTextOnPathLink()
02796 
02797     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
02798     Created:    09/06/95
02799     Inputs:     -
02800     Returns:    -
02801     Purpose:    destructor
02802     SeeAlso:    CDRFilter
02803 
02804 ********************************************************************************************/
02805 
02806 CDRTextOnPathLink::~CDRTextOnPathLink()
02807 {
02808 }
02809 
02810 
02811 

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