prnmks.cpp

Go to the documentation of this file.
00001 // $Id: prnmks.cpp 1320 2006-06-14 14:39:32Z 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 //
00099 // Author  : Mike
00100 // Created : 23/07/96
00101 // Purpose : The PrintMarks Manager and all its helper classes.
00102 //           This manager handles the caching and rendering of print marks
00103 //           within a document. PrintMarks are generally only used for typesetting
00104 
00105 /*
00106 */
00107 
00108 #include "camtypes.h"
00109 //#include "node.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 #include "prnmks.h"
00112 //#include "group.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 #include "fileutil.h"
00114 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00115 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00116 //#include "opdesc.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00117 #include "nativeop.h"
00118 #include "layer.h"
00119 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00120 #include "page.h"
00121 //#include "nodeattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00122 #include "colormgr.h"
00123 #include "prnmkcom.h"
00124 #include "qualattr.h"
00125 //#include "matrix.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00126 #include "dbugtree.h"
00127 //#include "paths.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00128 #include "cctime.h"
00129 #include "nodetxts.h"
00130 #include "nodetxtl.h"
00131 #include "colplate.h"
00132 #include "printctl.h"
00133 #include "fontman.h"
00134 #include "psrndrgn.h"
00135 #include "psdc.h"
00136 //#include "printstr.h"
00137 #include <stdlib.h>
00138 
00139 CC_IMPLEMENT_MEMDUMP(LoadPrintMarks, LoadDirect);
00140 CC_IMPLEMENT_MEMDUMP(PrintMarksMan, CC_CLASS_MEMDUMP);
00141 CC_IMPLEMENT_MEMDUMP(PrintMarksCache, CC_CLASS_MEMDUMP);
00142 CC_IMPLEMENT_MEMDUMP(PrintMark, CC_CLASS_MEMDUMP);
00143 CC_IMPLEMENT_DYNCREATE(MarkPosition, ListItem);
00144 CC_IMPLEMENT_DYNCREATE(PrintMarkItem, ListItem);
00145 CC_IMPLEMENT_MEMDUMP(MarkFormatRegion, CC_CLASS_MEMDUMP);
00146 CC_IMPLEMENT_DYNCREATE(PageRect, ListItem);
00147 CC_IMPLEMENT_DYNAMIC(PageRectList, List);
00148 
00149 DECLARE_SOURCE("$Revision: 1320 $");
00150 
00151 #define new CAM_DEBUG_NEW
00152 
00153 
00154 /*****************************************************************************************
00155 
00156 >   MarkFormat::MarkFormat()
00157 
00158     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00159     Created:    23/07/96
00160     Purpose:    Construct a Mark format object
00161 
00162 *****************************************************************************************/
00163 
00164 MarkFormat::MarkFormat()
00165 {
00166     Top = Middle = Bottom = FALSE;
00167     Left = Centre = Right = FALSE;
00168 }
00169 
00170 BOOL MarkFormat::IsValid() const
00171 {
00172     return (Top || Middle || Bottom || Left || Centre || Right);
00173 }
00174 
00175 void MarkFormat::MakeValid()
00176 {
00177     Centre = Middle = TRUE;
00178     Top = Bottom = Left = Right = FALSE;
00179 }
00180 
00181 INT32 operator==(const MarkFormat& x, const MarkFormat& y)
00182 {
00183     return ( (x.Centre == y.Centre) &&
00184              (x.Middle == y.Middle) &&
00185              (x.Left   == y.Left)   &&
00186              (x.Right  == y.Right)  &&
00187              (x.Top    == y.Top)    &&
00188              (x.Bottom == y.Bottom)
00189             );
00190 }
00191 
00192 
00193 
00194 /*****************************************************************************************
00195 
00196 >   BYTE MarkFormat::GetAsFlagByte(void)
00197 
00198     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00199     Created:    6/9/96
00200 
00201     Returns:    A Byte with bits set for each of the mark formats available
00202 
00203     Purpose:    Fill in a mark format object from a "flags byte"
00204                 Used for native file load/save
00205 
00206     SeeAlso:    MarkFormat::SetFromFlagByte
00207 
00208 *****************************************************************************************/
00209 
00210 BYTE MarkFormat::GetAsFlagByte(void)
00211 {
00212     BYTE Flags = 0;
00213 
00214     if (Left)   Flags |= 0x01;
00215     if (Centre) Flags |= 0x02;
00216     if (Right)  Flags |= 0x04;
00217     if (Top)    Flags |= 0x08;
00218     if (Middle) Flags |= 0x10;
00219     if (Bottom) Flags |= 0x20;
00220 
00221     return(Flags);
00222 }
00223 
00224 
00225 
00226 /*****************************************************************************************
00227 
00228 >   void MarkFormat::SetFromFlagByte(BYTE Flags)
00229 
00230     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00231     Created:    6/9/96
00232 
00233     Inputs:     Flags - A Byte with bits set for each of the mark formats available
00234 
00235     Purpose:    Fill in a mark format object from a "flags byte"
00236                 Used for native file load/save
00237 
00238     SeeAlso:    MarkFormat::GetAsFlagByte
00239 
00240 *****************************************************************************************/
00241 
00242 void MarkFormat::SetFromFlagByte(BYTE Flags)
00243 {
00244     Left    = (Flags & 0x01) ? TRUE : FALSE;
00245     Centre  = (Flags & 0x02) ? TRUE : FALSE;
00246     Right   = (Flags & 0x04) ? TRUE : FALSE;
00247     Top     = (Flags & 0x08) ? TRUE : FALSE;
00248     Middle  = (Flags & 0x10) ? TRUE : FALSE;
00249     Bottom  = (Flags & 0x20) ? TRUE : FALSE;
00250 }
00251 
00252 
00253 
00254 
00255 
00256 /*****************************************************************************************
00257 
00258 >   MarkPosition::MarkPosition()
00259 
00260     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00261     Created:    23/07/96
00262     Purpose:    Construct a mark position object
00263 
00264 *****************************************************************************************/
00265 
00266 MarkPosition::MarkPosition()
00267 {
00268     Initialise();
00269 }
00270 
00271 
00272 /*****************************************************************************************
00273 
00274 >   void MarkPosition::Initialise()
00275 
00276     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00277     Created:    23/07/96
00278     Purpose:    Initialise all the local variables in this mark position
00279 
00280 *****************************************************************************************/
00281 
00282 void MarkPosition::Initialise()
00283 {
00284     Region = MarkRegion_TopLeft;
00285 }
00286 
00287 
00288 /*****************************************************************************************
00289 
00290 >   BOOL MarkPosition::IsEqualTo(const MarkPosition* pOther) const
00291 
00292     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00293     Created:    23/07/96
00294     Inputs:     pOther = a pointer to a mark position to match
00295     Returns:    TRUE if pOther is identical to this mark
00296                 FALSE if not
00297     Purpose:    Check whether another mark position is identical to this one
00298 
00299 *****************************************************************************************/
00300 
00301 BOOL MarkPosition::IsEqualTo(const MarkPosition* pOther) const
00302 {
00303     ERROR2IF(pOther==NULL, FALSE, "NULL pointer passed to MarkPosition::IsEqualTo");
00304     return ( (Region == pOther->Region) &&
00305              (Format == pOther->Format)
00306            );
00307 }
00308 
00309 
00310 /*****************************************************************************************
00311 
00312 >   PrintMark::PrintMark
00313 
00314     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00315     Created:    23/07/96
00316     Purpose:    Construct a new print mark
00317 
00318 *****************************************************************************************/
00319 
00320 PrintMark::PrintMark()
00321 {
00322     MarkIsCustom    = FALSE;
00323     IDByte          = 0;
00324     Type            = MarkType_Unknown;
00325     Orientation     = MO_None;
00326     OnAsDefault     = FALSE;
00327 }
00328 
00329 
00330 /*****************************************************************************************
00331 
00332 >   virtual PrintMark::~PrintMark()
00333 
00334     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00335     Created:    23/07/96
00336     Purpose:    virtual destructor, destroys all instances of the 'MarkPositions' list
00337 
00338 *****************************************************************************************/
00339 
00340 PrintMark::~PrintMark()
00341 {
00342     MarkPosition* pMarkPos;
00343     while ((pMarkPos=(MarkPosition*)MarkPositions.RemoveTail()))
00344         delete pMarkPos;
00345 }
00346 
00347 
00348 
00349 /*****************************************************************************************
00350 
00351 >   void PrintMark::SetMarkMenuText(const String_256* pMenuText)
00352 
00353     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00354     Created:    23/07/96
00355     Inputs:     pMenuText = a pointer to a string containing the textual description of 
00356                             the print mark, (may be used in menus).
00357     Purpose:    Set this print mars menu text
00358 
00359 *****************************************************************************************/
00360 
00361 void PrintMark::SetMarkMenuText(const String_256* pMenuText)
00362 {
00363     ERROR3IF(pMenuText==NULL,"ERROR ERROR, NULL pointer passed to SetMarkMenuText");
00364     if (pMenuText!=NULL)
00365         MenuText = (*pMenuText);
00366 }
00367 
00368 
00369 /*****************************************************************************************
00370 
00371 >   String_256 PrintMark::GetMarkMenuText() const
00372 
00373     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00374     Created:    23/07/96
00375     Inputs:     -
00376     Returns:    This print marks textual description
00377     Purpose:    Return the menu text string saved in this print mark
00378 
00379 *****************************************************************************************/
00380 
00381 String_256 PrintMark::GetMarkMenuText() const
00382 {
00383     return MenuText;
00384 }
00385 
00386 
00387 /*****************************************************************************************
00388 
00389 >   void PrintMark::AddNewPosition(MarkPosition* pNewMarkPos)
00390 
00391     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00392     Created:    23/07/96
00393     Inputs:     pNewMarkPos, a pointer to a new mark position
00394     Returns:    This print marks textual description
00395     Purpose:    Return the menu text string saved in this print mark
00396 
00397 *****************************************************************************************/
00398 
00399 void PrintMark::AddNewPosition(MarkPosition* pNewMarkPos)
00400 {
00401     ERROR3IF(pNewMarkPos==NULL,"NULL MarkPosition pointer passed to AddNewPosition");
00402     if (pNewMarkPos)
00403     {
00404         if (!FindMarkPosition(pNewMarkPos))
00405             MarkPositions.AddTail(pNewMarkPos);
00406     }
00407 }
00408 
00409 /*****************************************************************************************
00410 
00411 >   BOOL PrintMark::FindMarkPosition(const MarkPosition* pSearchMark, MarkPosition** pFoundMark=NULL) const
00412 
00413     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00414     Created:    23/07/96
00415     Inputs:     pSearchMark = a pointer to a print mark to search for
00416                 pFoundMark, a pointer to a pointer to be set on exit. This defaults to null
00417                 when we're only interested in whether the mark exists or not.
00418 
00419     Outputs:    pFoundMark set to a pointer to the print mark in the cache if we find it
00420                 pFoundMark set to NULL if no match found
00421                                     
00422     Returns:    TRUE if there is a mark in the cache identical to this search mark
00423                 FALSE if there isn't
00424     Purpose:    Check the cache to see if there's a mark already in it which matches
00425                 pSearchMark. You can get the pointer to this cached mark by using pFoundMark
00426 
00427 *****************************************************************************************/
00428 
00429 BOOL PrintMark::FindMarkPosition(const MarkPosition* pSearchMark, MarkPosition** pFoundMark) const
00430 {
00431     ERROR3IF(pSearchMark==NULL,"PrintMark::FindMarkPosition passed a NULL search mark pointer");
00432     if (pSearchMark)
00433     {
00434         MarkPosition* pMarkPos = GetFirstPosition();
00435         while (pMarkPos)
00436         {
00437             // Check to see if this exists
00438             if (pSearchMark->IsEqualTo(pMarkPos))
00439             {
00440                 if (pFoundMark!=NULL)
00441                     (*pFoundMark=pMarkPos);
00442                 return TRUE;
00443             }
00444             pMarkPos = GetNextPosition(pMarkPos);
00445         }
00446     }
00447     if (pFoundMark!=NULL)
00448         (*pFoundMark=NULL);
00449     return FALSE;
00450 }
00451 
00452 /*****************************************************************************************
00453 
00454 >   BOOL PrintMark::IsSimilarTo(const PrintMark* pOther) const
00455 
00456     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00457     Created:    23/07/96
00458     Inputs:     pOther, a pointer to another print mark
00459     Returns:    TRUE if this print mark is similar to pOther.
00460                 FALSE if not
00461     Purpose:    Checks whether this print mark is similar to pOther. The current checks
00462                 for similarity are...
00463                 (1) the mark is of the same type
00464                 (2) the mark has the same menu text
00465 
00466 *****************************************************************************************/
00467 
00468 BOOL PrintMark::IsSimilarTo(const PrintMark* pOther) const
00469 {
00470     ERROR2IF(pOther==NULL, FALSE, "NULL PrintMark pointer passed to IsSimilar()");
00471 
00472     if (Type == pOther->GetType())
00473     {
00474         if (MenuText == pOther->GetMarkMenuText())
00475             return TRUE;
00476     }
00477     return FALSE;
00478 }
00479 
00480 
00481 
00482 /*****************************************************************************************
00483 
00484 >   PrintMarkItem::PrintMarkItem
00485 
00486     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00487     Created:    23/07/96
00488     Purpose:    Construct a new print mark item
00489 
00490 *****************************************************************************************/
00491 
00492 PrintMarkItem::PrintMarkItem()
00493 {
00494     pMarkGlyph  = NULL;
00495     Handle      = 0;
00496     Saveable    = TRUE;
00497     Renderable  = TRUE;
00498 }
00499 
00500 
00501 /*****************************************************************************************
00502 
00503 >   PrintMarkItem::~PrintMarkItem
00504 
00505     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00506     Created:    23/07/96
00507     Purpose:    destruct a print mark item
00508 
00509 *****************************************************************************************/
00510 
00511 PrintMarkItem::~PrintMarkItem()
00512 {
00513     RemoveMark();
00514 }
00515 
00516 
00517 
00518 
00519 /*****************************************************************************************
00520 
00521     BOOL PrintMarkItem::SetMarkGlyph(NodeGroup* pNewMark, BOOL MakeCopy=FALSE)
00522 
00523     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00524     Created:    23/07/96
00525     Inputs:     pNewMark = A pointer to a group node containing the mark. 
00526                            The node should still be in the tree.
00527                 MakeCopy = TRUE, the mark will be left where it is and an
00528                                  attribute complete copy will be made.
00529                            FALSE, the mark will be extracted from the document as is. 
00530     Purpose:    Cache a print mark in this print mark item. The mark pointer should be
00531                 a group held in the document tree. As we attempt to make attributes
00532                 complete on this group, it has to be in the tree. MakeCopy which defaults
00533                 to FALSE will, when TRUE, copy the entire group and used the copy, hence
00534                 it will leave the document unaffected. When FALSE the group will be
00535                 extracted from the tree. This is only acceptable in a few circumstances
00536                 when undo is not being generated.
00537 
00538 *****************************************************************************************/
00539 
00540 BOOL PrintMarkItem::SetMarkGlyph(NodeGroup* pNewMark, BOOL MakeCopy)
00541 {
00542     ERROR2IF(pNewMark==NULL,FALSE, "NULL mark pointer passed to SetMark");
00543 
00544     if (MakeCopy)
00545     {
00546         NodeGroup* pNewGroup = new NodeGroup;
00547         if (pNewGroup==NULL)
00548             return FALSE;
00549 
00550         NodeGroup* pNewGroup1 = new NodeGroup;
00551         if (pNewGroup1==NULL)
00552         {
00553             delete pNewGroup;
00554             return FALSE;
00555         }
00556         
00557         // attach this new group to the tree
00558         pNewGroup->AttachNode(pNewMark,NEXT);
00559         pNewGroup1->AttachNode(pNewGroup,FIRSTCHILD);
00560 
00561         // copy the children across to this new group
00562         if (!pNewMark->CopyChildrenTo(pNewGroup1))
00563         {
00564             // CascadeDelete unlinks the node from the tree so don't panic.
00565             pNewGroup->CascadeDelete();
00566             delete pNewGroup;
00567             return FALSE;
00568         }
00569 
00570         // make sure we have all the attributes we're gonna need
00571         if (!pNewGroup->MakeAttributeComplete(NULL,TRUE,NULL,TRUE))
00572         {
00573             pNewGroup->CascadeDelete();
00574             delete pNewGroup;
00575             return FALSE;
00576         }
00577 
00578         // dump the tree out
00579         //TRACEUSER( "Mike", _T("Dumping subtree contents\n\n"));
00580         //DebugTreeDlg::DumpSubTree(pNewGroup);
00581         
00582         // rip the node out of the tree and stick it in our cache.
00583         pNewGroup->UnlinkNodeFromTree();
00584                 
00585         // Make sure we get rid of any previously cached mark
00586         if (pMarkGlyph!=NULL)
00587             RemoveMark();
00588 
00589         pMarkGlyph = pNewGroup;
00590     }
00591     else
00592     {
00593         if (!pNewMark->MakeAttributeComplete(NULL,TRUE,NULL,TRUE))
00594             return FALSE;
00595 
00596         pNewMark->UnlinkNodeFromTree();
00597                 
00598         // Make sure we get rid of any previously cached mark
00599         if (pMarkGlyph!=NULL)
00600             RemoveMark();
00601 
00602         pMarkGlyph = pNewMark;
00603     }
00604 
00605     return TRUE;
00606 }
00607 
00608 
00609 /*****************************************************************************************
00610 
00611 >   void PrintMarkItem::RemoveMark()
00612 
00613     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00614     Created:    23/07/96
00615     Purpose:    Remove the cached mark from our list structure. This is generally
00616                 called when the mark item is destroyed.
00617 
00618 *****************************************************************************************/
00619 
00620 void PrintMarkItem::RemoveMark()
00621 {
00622     // check to see if we have a sub tree here
00623     if (pMarkGlyph!=NULL)
00624     {
00625         Node* pNode = pMarkGlyph->FindFirstChild();
00626         if (pNode!=NULL)
00627             pMarkGlyph->DeleteChildren(pNode);
00628     }
00629     delete pMarkGlyph;
00630     pMarkGlyph = NULL;
00631 }
00632 
00633 
00634 INT32 PrintMarkItem::GetWidth() const
00635 {
00636     if (pMarkGlyph!=NULL)
00637     {
00638         DocRect bounds = pMarkGlyph->GetBoundingRect();
00639         return bounds.Width();
00640     }
00641     return 0;
00642 }
00643 
00644 INT32 PrintMarkItem::GetHeight() const
00645 {
00646     if (pMarkGlyph!=NULL)
00647     {
00648         DocRect bounds = pMarkGlyph->GetBoundingRect();
00649         return bounds.Height();
00650     }
00651     return 0;
00652 }
00653 
00654 DocCoord PrintMarkItem::GetOrigin() const
00655 {
00656     if (pMarkGlyph!=NULL)
00657     {
00658         DocRect bounds = pMarkGlyph->GetBoundingRect();
00659         return bounds.lo;
00660     }
00661     return DocCoord(0,0);
00662 }
00663 
00664 
00665 MarkOrient PrintMarkItem::GetOrient() const
00666 {
00667     return Mark.GetOrientation();
00668 }
00669 
00670 
00671 BOOL PrintMarkItem::DefaultsToOn() const
00672 {
00673     return Mark.DefaultsToOn();
00674 }
00675 
00676 
00677 BOOL PrintMarkItem::NeedsSaving() const
00678 {
00679     return Saveable;
00680 }
00681 
00682 
00683 void PrintMarkItem::SetSaveable(BOOL savestate)
00684 {
00685     Saveable = savestate;
00686 }
00687 
00688 BOOL PrintMarkItem::NeedsToRender() const
00689 {
00690     return Renderable;
00691 }
00692 
00693 void PrintMarkItem::SetRenderable(BOOL renderstate)
00694 {
00695     Renderable = renderstate;
00696 }
00697 
00698 
00699 
00700 /*****************************************************************************************
00701 
00702 >   PrintMarksCache::PrintMarksCache()
00703 
00704     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00705     Created:    23/07/96
00706     Purpose:    Construct the PrintMarksCache object. This used to be part of the print
00707                 marks manager but I've now split it into its own class to prevent
00708                 confusion with the handling of cache marks and document marks. Various
00709                 functions do similar things so it could become confusing without a
00710                 scope resolution operator PMMCache::FindMark as opposed to Doc::FindMark
00711 
00712 *****************************************************************************************/
00713 
00714 PrintMarksCache::PrintMarksCache()
00715 {
00716     NextHandle=0;
00717     TextInfoHandle=0;
00718     CropMarkHandle=0;
00719 }
00720 
00721 
00722 /*****************************************************************************************
00723 
00724 >   PrintMarksCache::~PrintMarksCache()
00725 
00726     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00727     Created:    23/07/96
00728     Purpose:    Destroys the cached marks completely
00729 
00730 *****************************************************************************************/
00731 
00732 PrintMarksCache::~PrintMarksCache()
00733 {
00734     Invalidate();
00735 }
00736 
00737 
00738 /*****************************************************************************************
00739 
00740 >   PrintMarksCache::~PrintMarksCache()
00741 
00742     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00743     Created:    23/07/96
00744     Purpose:    Invalidate the cache list. If we do this, all the mark references
00745                 in existing document will reference nothing. As we create new marks
00746                 new handles will be built, so it might be necessary to delete references
00747                 made in all doc components.
00748                 Use with care.
00749 
00750 *****************************************************************************************/
00751 
00752 void PrintMarksCache::Invalidate()
00753 {
00754     // destroy all marks in the cache.
00755     PrintMarkItem* pItem;
00756     while ((pItem=(PrintMarkItem*)PrintMarkCache.RemoveTail())) // assignment
00757         delete pItem;
00758     // Make sure the crop and text info handles don't reference anything
00759     CropMarkHandle=0;
00760     TextInfoHandle=0;
00761 }
00762 
00763 
00764 /*****************************************************************************************
00765 
00766 >   UINT32 PrintMarksCache::GetUniqueHandle()
00767 
00768     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00769     Created:    23/07/96
00770     Inputs:     -
00771     Returns:    A handle used to reference a unique print mark
00772     Purpose:    Generate a unique print mark handle. All handles will be >=1 and hence
00773                 an illegal handle is given the value 0.
00774 
00775 *****************************************************************************************/
00776 
00777 UINT32 PrintMarksCache::GetUniqueHandle()
00778 {
00779     NextHandle++;
00780     return (NextHandle);
00781 }
00782 
00783 
00784 
00785 /*****************************************************************************************
00786 
00787 >   PrintMarkItem* PrintMarksCache::GetFirstMark() const
00788 
00789     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00790     Created:    23/07/96
00791     Inputs:     -
00792     Returns:    A pointer to the first cached mark
00793     Purpose:    Return a pointer to the first cached mark
00794 
00795 *****************************************************************************************/
00796 
00797 PrintMarkItem* PrintMarksCache::GetFirstMark() const
00798 {
00799     return ((PrintMarkItem*)PrintMarkCache.GetHead()); 
00800 }
00801 
00802 
00803 /*****************************************************************************************
00804 
00805 >   PrintMarkItem* PrintMarksCache::GetNextMark(PrintMarkItem* pCurrMark) const
00806 
00807     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00808     Created:    23/07/96
00809     Inputs:     A pointer to a print mark item
00810     Returns:    A pointer to the next print mark item after this
00811     Purpose:    Returns the next print mark item beyond pCurrMark
00812 
00813 *****************************************************************************************/
00814 
00815 PrintMarkItem* PrintMarksCache::GetNextMark(PrintMarkItem* pCurrMark) const
00816 {
00817     return ((PrintMarkItem*)PrintMarkCache.GetNext(pCurrMark));
00818 }
00819 
00820 
00821 /*****************************************************************************************
00822 
00823 >   BOOL PrintMarksCache::DoesMarkExist(PrintMark* pCheckMark) const
00824 
00825     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00826     Created:    23/07/96
00827     Inputs:     A pointer to a print mark
00828     Returns:    TRUE if this mark already exists in the cache
00829                 FALSE if not
00830     Purpose:    Try to find a print mark in the cache
00831 
00832 *****************************************************************************************/
00833 
00834 BOOL PrintMarksCache::DoesMarkExist(PrintMark* pCheckMark) const
00835 {
00836     PrintMarkItem* pItem = GetFirstMark();
00837     while (pItem)
00838     {
00839         PrintMark* pCurrMark = pItem->GetPrintMark();
00840         if (pCheckMark->IsSimilarTo(pCurrMark))
00841             return TRUE;
00842         pItem = GetNextMark(pItem);
00843     }
00844     return FALSE;
00845 }
00846 
00847 
00848 /*****************************************************************************************
00849 
00850 >   PrintMarkItem* PrintMarksCache::FindMark(UINT32 SearchHandle)
00851 
00852     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00853     Created:    23/07/96
00854     Inputs:     SearchHandle = the handle of the mark to search for
00855     Returns:    A pointer to the print mark described by this handle (NULL if none)
00856     Purpose:    Try to find a print mark in the cache, using its handle
00857 
00858 *****************************************************************************************/
00859 
00860 PrintMarkItem* PrintMarksCache::FindMark(UINT32 SearchHandle)
00861 {
00862     PrintMarkItem* pItem = GetFirstMark();
00863     while (pItem)
00864     {
00865         if (pItem->GetHandle() == SearchHandle)
00866             return pItem;
00867         pItem = GetNextMark(pItem);
00868     }
00869     return NULL;
00870 }
00871 
00872 
00873 
00874 
00875 /*****************************************************************************************
00876 
00877 >   BOOL PrintMarksCache::DecodeCachedLayers(Document* pDocument)
00878 
00879     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00880     Created:    23/07/96
00881     Inputs:     pDocument = a pointer to a document
00882     Returns:    TRUE if the document has been processed
00883                 
00884     Purpose:    Given a document, we scan each layer in the document. For each layer
00885                 we check the loaded layer name. If the layer name contains a % at the
00886                 begining (meaning its a format string) and the format is PRINTMARK, we
00887                 take the first group in the layer (+ all its contents) and assign a
00888                 new print mark item to this group. This group object will (if successfully)
00889                 loaded, become a new print mark.
00890     
00891 *****************************************************************************************/
00892 
00893 BOOL PrintMarksCache::DecodeCachedLayers(Document* pDocument)
00894 {
00895     ERROR2IF(pDocument==NULL,FALSE,"NULL Layer passed to DecodeCachedLayer");
00896     
00897     Spread* pSpread = pDocument->FindFirstSpread();
00898     Layer* pLayer;
00899     while (pSpread!=NULL)
00900     {
00901         pLayer = pSpread->FindFirstLayer();
00902         while (pLayer!=NULL)
00903         {
00904             DecodeCachedLayer(pLayer);
00905             pLayer = pLayer->FindNextLayer(); // Find next layer
00906         }
00907         pSpread = pSpread->FindNextSpread();
00908     }
00909     return TRUE;
00910 }
00911 
00912 
00913 /*****************************************************************************************
00914 
00915 >   BOOL PrintMarksMan::DecodeCachedLayer(Layer* pLayer)
00916 
00917     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00918     Created:    23/07/96
00919     Inputs:     pLayer = a pointer to a layer
00920     Returns:    TRUE if the layer has been processed
00921     Purpose:    Given a layer, if the layer contains a print mark, strip the print mark
00922                 out and try to add it to the PrintMarksMan cache.
00923     
00924 *****************************************************************************************/
00925 
00926 BOOL PrintMarksCache::DecodeCachedLayer(Layer* pLayer)
00927 {
00928     ERROR2IF(pLayer==NULL,FALSE,"NULL Layer passed to DecodeCachedLayer");
00929 
00930     // Read in the layer name
00931     String_256 Name;
00932     String_16 Token;
00933 
00934     Name = pLayer->GetLayerID();
00935     Name.Left(&Token, 10);
00936 
00937     BOOL IsValid = FALSE;
00938     BOOL IsCustomMark = FALSE;
00939     if (Token == String_16(_T("%PRINTMARK")))               // This text must not be internationalised
00940         IsValid = TRUE;
00941 
00942     if (!IsValid && Token == String_16(_T("%CUSTOMMAR")))   // This text must not be internationalised
00943     {
00944         IsValid = TRUE;
00945         IsCustomMark = TRUE;
00946     }
00947 
00948     if (!IsValid)
00949         return FALSE;
00950 
00951     // find the first renderable group in this layer.
00952     NodeGroup* pGroup = (NodeGroup*)pLayer->FindFirstChild(CC_RUNTIME_CLASS(NodeGroup));
00953     if (pGroup==NULL)
00954         return FALSE;
00955 
00956     // Create a new mark structure to put the decoded data into
00957     PrintMarkItem* pNewMark = new PrintMarkItem;
00958     if (!pNewMark)
00959         return FALSE;
00960 
00961     PrintMark* pMark = pNewMark->GetPrintMark();
00962     pMark->SetCustomOrDefault(IsCustomMark);        // Remember if it's a custom or default mark
00963     if (!DecodeMarkFormat(&Name, pMark))
00964     {
00965         delete pNewMark;
00966         return FALSE;
00967     }
00968 
00969     // Right we have a new print mark descriptor, 
00970     // we simply merge the mark into the
00971     // cache. It would be faster, before copying the subtree, to check whether we
00972     // dont already have this mark cached in the print mark manager.
00973 
00974     if (DoesMarkExist(pMark))
00975     {
00976         delete pNewMark;
00977         return TRUE;
00978     }
00979 
00980     // Add a handle to this mark
00981     pNewMark->SetHandle(GetUniqueHandle());
00982 
00983     // ok the mark does not exist, so now look for that first group
00984     if (!pNewMark->SetMarkGlyph(pGroup, TRUE))
00985     {
00986         delete pNewMark;
00987         return FALSE;
00988     }
00989 
00990     // Hey hey, we've finally done it! cool!
00991     PrintMarkCache.AddTail(pNewMark);
00992 
00993     return TRUE;
00994 }
00995 
00996 
00997 /*****************************************************************************************
00998 
00999 >   UINT32 PrintMarksCache::AddNewMark(PrintMarkItem* pNewMark, NodeGroup* pGroup)
01000 
01001     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01002     Created:    23/07/96
01003     Inputs:     pNewMark = a pointer to the new mark to add
01004                 pGroup = a pointer to the glyph to use. 
01005     Returns:    The handle of the newly added mark
01006     Purpose:    A simple way of adding a prebuilt mark to the list. The mark must be in
01007                 a renderable format, in that it should be a group with all needed attrs
01008                 as children, followed by a child group containing all the ink objects
01009     
01010 *****************************************************************************************/
01011 
01012 UINT32 PrintMarksCache::AddNewMark(PrintMarkItem* pNewMark, NodeGroup* pGroup)
01013 {
01014     // Add a handle to this mark
01015     UINT32 hndle = GetUniqueHandle();
01016     pNewMark->SetHandle(hndle);
01017     pNewMark->pMarkGlyph = pGroup;
01018     // Hey hey, we've finally done it! cool!
01019     PrintMarkCache.AddTail(pNewMark);
01020     return hndle;
01021 }
01022 
01023 
01024 /*****************************************************************************************
01025 
01026 >   void PrintMarksCache::UpdateMarkGlyph(PrintMarkItem *pMarkItem, NodeGroup *pGroup)
01027 
01028     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01029     Created:    23/07/96
01030     Inputs:     pMarkItem = a pointer to an existing cached mark
01031                 pGroup    = a pointer to a new glyph to use.
01032     Returns:    -
01033     Purpose:    Change the mark glyph to this new mark.
01034 
01035 *****************************************************************************************/
01036 
01037 void PrintMarksCache::UpdateMarkGlyph(PrintMarkItem *pMarkItem, NodeGroup *pGroup)
01038 {
01039     if (pMarkItem!=NULL)
01040     {
01041         // Make sure there's nothing in there at the mo.
01042         pMarkItem->RemoveMark();
01043         // now set the new mark glyph
01044         pMarkItem->pMarkGlyph = pGroup;
01045     }
01046 }
01047 
01048 
01049 
01050 /*****************************************************************************************
01051 
01052 >   BOOL PrintMarksCache::DecodeMarkFormat(const String_256 *pFormatString, PrintMark* pMark)
01053 
01054     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01055     Created:    23/07/96
01056     Inputs:     pFormatString
01057     Outputs:    pMark
01058     Returns:    TRUE if the format string was valid.
01059     Purpose:    Decode the string pointed to by pFormatString, placing each format
01060                 identifier into the output mark.
01061 
01062                 Special tag         Mark name           ID On/off Type      Position(s)
01063                 %PRINTMARK  = "Registration mark",      3,  1,  _R(ID_STAR), 3MCS + 7MC + 11MCS + 15MC
01064                 %CUSTOMMARK = "User registration mark", 0,  1,  _R(ID_STAR), 3MCS + 7MC + 11MCS + 15MC
01065 
01066 *****************************************************************************************/
01067 
01068 BOOL PrintMarksCache::DecodeMarkFormat(const String_256 *pFormatString, PrintMark* pMark)
01069 {
01070     ERROR2IF(pFormatString == NULL, FALSE, "NULL pointer passed to DecodeMarkFormat");
01071     ERROR2IF(pMark == NULL, FALSE, "NULL mark pointer passed to DecodeMarkFormat");
01072 
01073     String_256 Name(*pFormatString);
01074     String_256 MenuText;
01075     String_256 MenuID;
01076     MarkFormat NewFormat;
01077     MarkRegion NewRegion;
01078     MarkOrient NewOrient;
01079 
01080     const TCHAR COMMA   = TEXT(',');        // This text must not be internationalised
01081 //  const TCHAR EQUALS  = TEXT('=');
01082     const TCHAR QUOTES  = TEXT('"');
01083     const TCHAR PLUS    = TEXT('+');
01084     const TCHAR SPACE   = TEXT(' ');
01085 
01086     INT32 pos, pos1;
01087 
01088     // Everything is hunky dory at the moment! ER NOT!
01089     BOOL AllIsWell = FALSE;
01090 
01091     // Turn on the exceptions function in the string reading class
01092     StringBase::EnableExceptionHandler();
01093 
01094     //try 
01095     {
01096         // toast everything up to the first quote
01097         pos = Name.FindNextChar(QUOTES);
01098         Name.Remove(0,pos+1);
01099 
01100         // now find the last quote of the first string
01101         pos = Name.FindNextChar(QUOTES);
01102         Name.Left(&MenuText,pos);
01103         Name.Remove(0,pos+1);
01104 
01105         // skip over the first comma onto the ID field
01106         pos  = Name.SkipComma();
01107         Name.Remove(0,pos);
01108         pos = 0;
01109         INT32 ID = Name.ConvertToInteger(pos);
01110         Name.Remove(0,pos);
01111         if (ID < 0 || ID > 255)
01112             ID = 0;
01113         pMark->SetIDByte((BYTE)ID);
01114 
01115         // skip over the next comma onto the enable/disable state
01116         pos  = Name.SkipComma();
01117         Name.Remove(0,pos);
01118         BOOL Enabled = (Name[0] == TEXT('1'));
01119 
01120         // skip comma to next field
01121         pos  = Name.SkipComma();
01122         pos1 = Name.FindNextChar(COMMA, pos+1);
01123         Name.Mid(&MenuID, pos, (pos1-pos));
01124         Name.Remove(0,pos1+1);
01125 
01126         // turn the menu id into a type of mark if we recognise it
01127         MarkType actid = (MarkType)DecodeToMarkType(&MenuID);
01128 
01129         // skip the orientation field
01130         pos=Name.FindNextChar();
01131         NewOrient=MO_None;
01132         if (Name[pos] == TEXT('H'))
01133             NewOrient=MO_Horizontal;
01134         else if (Name[pos] == TEXT('V'))
01135             NewOrient=MO_Vertical;
01136 
01137         // remove the orientation bit
01138         pos = Name.SkipComma();
01139 
01140         // Add what we have so far
01141         pMark->SetMarkMenuText(&MenuText);
01142         pMark->SetOrientation(NewOrient);
01143         pMark->SetType(actid);
01144         pMark->SetDefaultState(Enabled);
01145 
01146         // The remainder of this string is a format list
01147 //      BOOL format=FALSE;
01148 //      BOOL eos=FALSE;
01149 
01150         // Turn our exception handler off but don't pop it.
01151         StringBase::DisableExceptionHandler(FALSE);
01152 
01153         INT32 region;
01154 
01155         while (pos>0)
01156         {
01157             // Try to create a new mark to add
01158             MarkPosition* pNewMark = new MarkPosition;
01159 
01160             if (pNewMark!=NULL)
01161             {
01162                 region = Name.ConvertToInteger(pos);
01163 
01164                 if (region<1 || region>MAXPAGEREGIONS)
01165                 {
01166                     // Ok, the region number is out of range so lets
01167                     // skip to the next one (if there is one!)
01168                     // we need to find the next +
01169                     delete pNewMark;
01170                     pos = Name.FindNextChar(PLUS, pos);
01171                 }
01172                 else
01173                 {
01174                     // store this type of region
01175                     NewRegion = (MarkRegion)(region-1);
01176                     pNewMark->SetRegion(NewRegion);
01177                                 
01178                     // if we haven't run off the end of the string
01179                     while ( Name.IsLegal(pos) && (Name[pos]!=PLUS) )
01180                     {
01181                         TCHAR c = Name[pos];
01182                         
01183                         switch (c)
01184                         {
01185                             case TEXT('T'): NewFormat.Top=TRUE;     break;
01186                             case TEXT('M'): NewFormat.Middle=TRUE;  break;
01187                             case TEXT('B'): NewFormat.Bottom=TRUE;  break;
01188                             case TEXT('L'): NewFormat.Left=TRUE;    break;
01189                             case TEXT('C'): NewFormat.Centre=TRUE;  break;
01190                             case TEXT('R'): NewFormat.Right=TRUE;   break;
01191                             default:
01192                                 // unknown token, just ignore it!
01193                                 if (c != SPACE)
01194                                     TRACEUSER( "Mike", _T("Unknown format character during PrintMarksMan::DecodeMarkFormat"));
01195                                 break;
01196                         }
01197                         
01198                         pos = Name.FindNextChar(pos+1);
01199                     }
01200 
01201                     // make sure the format is ok
01202                     if (!NewFormat.IsValid())
01203                         NewFormat.MakeValid();
01204                     
01205                     // and set it in the structure.
01206                     pNewMark->SetFormat(NewFormat);
01207 
01208                     // Add the new mark position to the list.
01209                     pMark->AddNewPosition(pNewMark);
01210 
01211                     AllIsWell=TRUE;
01212 
01213                     if (Name.IsLegal(pos))
01214                         pos = Name.FindNextChar(pos+1);
01215                 }
01216             }
01217             else
01218             {
01219                 pos = -1;
01220             }
01221         }
01222     }
01223 PORTNOTE("other", "Disabled random use of MFC CUserException in Kernel code")
01224 #ifndef EXCLUDE_FROM_XARALX
01225     catch (CUserException)
01226     {
01227         // An exception has been thrown which means
01228         // we failed to parse this string, so simply report failure
01229         AllIsWell = FALSE;
01230     }
01231 #endif
01232 
01233     // Switch off the exception state finally, (and of course pop it)!
01234     StringBase::DisableExceptionHandler();
01235 
01236     return AllIsWell;
01237 }
01238 
01239 
01240 
01241 /*****************************************************************************************
01242 
01243 >   UINT32 PrintMarksCache::DecodeToMarkType(String_256* Name) const
01244 
01245     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01246     Created:    23/07/96
01247     Inputs:     Name = a pointer to a string describing the mark type
01248     Returns:    A unsigned integer describing the mark type (see MarkType for instances)
01249     Purpose:    Have a look at the string passed in and check to see it matches any of
01250                 the known mark type names. If so return the proper mark type enum, otherwise
01251                 'Unkown' is returned.
01252     
01253 *****************************************************************************************/
01254 
01255 UINT32 PrintMarksCache::DecodeToMarkType(const String_256* Name) const
01256 {
01257     ERROR2IF(Name == NULL, MarkType_Unknown, "NULL pointer passed to DecodeToMarkType");
01258     
01259     if ((*Name)==String_16(_T("ID_NONE")))  return MarkType_Unknown; /*NORESOURCEFIX*/
01260     if ((*Name)==String_16(_T("ID_STAR")))  return MarkType_Star; /*NORESOURCEFIX*/ 
01261     if ((*Name)==String_16(_T("ID_REGM")))  return MarkType_Registration; /*NORESOURCEFIX*/
01262     if ((*Name)==String_16(_T("ID_CBAR")))  return MarkType_ColourBar; /*NORESOURCEFIX*/
01263     if ((*Name)==String_16(_T("ID_GBAR")))  return MarkType_GreyBar; /*NORESOURCEFIX*/
01264     if ((*Name)==String_16(_T("ID_INFO")))  return MarkType_Information; /*NORESOURCEFIX*/
01265     
01266     return MarkType_Unknown;
01267 }
01268 
01269 
01270 /*****************************************************************************************
01271 
01272 >   BOOL PrintMarksCache::CreateCropMark()
01273 
01274     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01275     Created:    10/08/96
01276     Inputs:
01277     Returns:    -
01278     Purpose:    
01279     
01280 *****************************************************************************************/
01281 
01282 BOOL PrintMarksCache::CreateCropMark()
01283 {
01284     if (CropMarkHandle>0)
01285         return TRUE;
01286 
01287     // Create a particular mark structure for this crop mark
01288     PrintMarkItem* pMarkItem = new PrintMarkItem;
01289     if (pMarkItem==NULL)
01290         return FALSE;
01291 
01292     MarkPosition* pPosition = new MarkPosition;
01293     if (pPosition==NULL)
01294     {
01295         delete pMarkItem;
01296         return FALSE;
01297     }
01298 
01299     MarkFormat format;
01300     pPosition->SetRegion(MarkRegion_Top1);
01301     pPosition->SetFormat(format);
01302     String_256 MenuText(_R(IDS_PRINTMARK_CROPMARKS));
01303 
01304     PrintMark* pMark = pMarkItem->GetPrintMark();
01305     pMark->SetCustomOrDefault(FALSE);
01306     pMark->SetIDByte(PRINTMARK_CROPMARKID);
01307     pMark->SetType(MarkType_Crop);
01308     pMark->SetMarkMenuText(&MenuText);
01309     pMark->SetOrientation(MO_Horizontal);
01310     pMark->SetDefaultState(TRUE);
01311     pMark->AddNewPosition(pPosition);
01312 
01313     // we don't want to save this mark
01314     pMarkItem->SetSaveable(FALSE);
01315     // we render this without formatting in a different way
01316     pMarkItem->SetRenderable(FALSE);
01317     // finally stick the thing in our cache!
01318     CropMarkHandle = AddNewMark(pMarkItem, NULL);
01319     
01320     return TRUE;
01321 }
01322 
01323 
01324 
01325 /*****************************************************************************************
01326 
01327 >   BOOL PrintMarksCache::CreateTextInfoMark()
01328 
01329     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01330     Created:    10/08/96
01331     Inputs:     pComp      = the document component containing the print marks
01332                 CurrRegion = the current region we're formatting marks in
01333     Returns:    -
01334     Purpose:    This function creates a text information mark which will describe the
01335                 current print job. As this will be created and destroyed on each print
01336                 it should be reasonably fast to execute. We include the following
01337                 information in the text....
01338 
01339                     Document title
01340                     Date
01341                     Time
01342                     Page number?
01343                     Plate name
01344     
01345 *****************************************************************************************/
01346 
01347 BOOL PrintMarksCache::CreateTextInfoMark()
01348 {
01349     // is it already created?
01350     if (TextInfoHandle>0)
01351         return TRUE;
01352 
01353     // Create a particular mark structure for this info
01354     PrintMarkItem* pMarkItem = new PrintMarkItem;
01355     if (pMarkItem==NULL)
01356         return FALSE;
01357 
01358     MarkPosition* pPosition = new MarkPosition;
01359     if (pPosition==NULL)
01360     {
01361         delete pMarkItem;
01362         return FALSE;
01363     }
01364 
01365     MarkFormat format;
01366     format.Middle = TRUE;
01367     format.Left = TRUE;
01368     pPosition->SetRegion(MarkRegion_Top2);
01369     pPosition->SetFormat(format);
01370 
01371     String_256 MenuText(_R(IDS_PRINTMARK_PLATEINFO));
01372     PrintMark* pMark = pMarkItem->GetPrintMark();
01373     pMark->SetCustomOrDefault(FALSE);
01374     pMark->SetIDByte(PRINTMARK_INFOMARKID);
01375     pMark->SetType(MarkType_Information);
01376     pMark->SetMarkMenuText(&MenuText);
01377     pMark->SetOrientation(MO_Horizontal);
01378     pMark->SetDefaultState(TRUE);
01379     pMark->AddNewPosition(pPosition);
01380 
01381     // we don't want to save this mark
01382     pMarkItem->SetSaveable(FALSE);
01383     // finally stick the thing in our cache!
01384     TextInfoHandle = AddNewMark(pMarkItem, NULL);
01385     
01386     return TRUE;
01387 }
01388 
01389 
01390 
01391 /*****************************************************************************************
01392 
01393 >   BOOL PrintMarksCache::UpdateTextInfoMark(Document* pDocument, RenderRegion* pRRegion)
01394 
01395     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01396     Created:    10/08/96
01397     Inputs:     pComp      = the document component containing the print marks
01398                 CurrRegion = the current region we're formatting marks in
01399     Returns:    -
01400     Purpose:    This function creates a text information mark which will describe the
01401                 current print job. As this will be created and destroyed on each print
01402                 it should be reasonably fast to execute. We include the following
01403                 information in the text....
01404 
01405                     Document title
01406                     Date
01407                     Time
01408                     Page number?
01409                     Plate name
01410     
01411 *****************************************************************************************/
01412 
01413 BOOL PrintMarksCache::UpdateTextInfoMark(Document* pDocument, RenderRegion* pRRegion)
01414 {
01415     // We should at least have one of these.
01416     if (TextInfoHandle==0)
01417         return FALSE;
01418 
01419     // find it in the cache
01420     PrintMarkItem *pMarkItem = FindMark(TextInfoHandle);
01421     if (!pMarkItem)
01422         return FALSE;
01423 
01424     // first put all the information we need to display in a string.
01425     String_256 TextInfo;
01426     BuildTextInfoString(pDocument, pRRegion, &TextInfo);
01427 
01428     // create a proper mark structure to fit this mark in
01429     NodeGroup* pNewGroup = new NodeGroup;
01430     if (pNewGroup==NULL)
01431         return FALSE;
01432 
01433     NodeGroup* pNewGroup1 = new NodeGroup;
01434     if (pNewGroup1==NULL)
01435     {
01436         delete pNewGroup;
01437         return FALSE;
01438     }
01439 /*
01440     // Make a text style LOGFONT to describe the text information
01441     LOGFONT Style;
01442     Style.lfHeight          =0x08;      // 8pt text
01443     Style.lfWidth           =0x05;
01444     Style.lfEscapement      =0x00;
01445     Style.lfOrientation     =0x00;
01446     Style.lfWeight          =0x190;
01447     Style.lfItalic          =0x00;
01448     Style.lfUnderline       =0x00;
01449     Style.lfStrikeOut       =0x00;
01450     Style.lfCharSet         =0x00;
01451     Style.lfOutPrecision    =0x03;
01452     Style.lfClipPrecision   =0x02;
01453     Style.lfQuality         =0x01;
01454     Style.lfPitchAndFamily  =0x12;
01455     camStrncpy(Style.lfFaceName, TEXT("Times New Roman\0"), 16);
01456 */
01457     String_64 FontName(_T("Courier New"));
01458     MILLIPOINT FontSize = 9*1000;
01459 
01460     // now create the text story to put in the mark.
01461     TextStory *pStory;
01462     DocColour TextCol(COLOUR_BLACK);
01463 #ifdef _UNICODE
01464     pStory = TextStory::CreateFromChars(DocCoord(0,0), NULL, (TCHAR *)TextInfo, pDocument, NULL, FALSE, &TextCol);
01465 #else
01466     pStory = TextStory::CreateFromChars(DocCoord(0,0), (char *)TextInfo, NULL, pDocument, NULL, FALSE, &TextCol);
01467 #endif
01468     if (pStory==NULL)
01469     {
01470         // deleting this will delete the mark position
01471         delete pNewGroup1;
01472         delete pNewGroup;
01473         return FALSE;
01474     }
01475 
01476     // ok make sure the attributes are set nicely
01477     if (!SetInfoMarkAttributes(pStory,&FontName,FontSize))
01478     {
01479         delete pStory;
01480         delete pNewGroup1;
01481         delete pNewGroup;
01482         return FALSE;
01483     }
01484 
01485     // Turn the print as shapes on. This means we will render it rather
01486     // than GDI rendering it. It also means the text goes out after our header
01487     // which sets things like Negative transfer. If we don't render the
01488     // text we wont have put out our header yet..... Hence the text has a habit
01489     // of vanishing on 'Negative' prints, black on black n all that. We could
01490     // set the colour of the text of course, hmm maybe? This is quicker for now.
01491     pStory->SetPrintingAsShapes(TRUE);
01492 
01493     // attach this new group to the tree
01494     pNewGroup1->AttachNode(pNewGroup,FIRSTCHILD);
01495     // attach the story to the group
01496     pStory->AttachNode(pNewGroup1,FIRSTCHILD);
01497 
01498     // We need to attach this structure to the tree, at the insertion node and makeattributes complete on it.
01499     pDocument->InsertNewNode(pNewGroup,NULL);
01500 
01501 /*
01502     // make sure we have all the attributes we're gonna need
01503     if (!pNewGroup->MakeAttributeComplete(NULL,TRUE,NULL,TRUE))
01504     {
01505         pNewGroup->CascadeDelete();
01506         delete pNewGroup;
01507         return FALSE;
01508     }
01509 */
01510     // time to format the story into shape.
01511     if (!pStory->FormatAndChildren())
01512     {
01513         pNewGroup->CascadeDelete();
01514         delete pNewGroup;
01515         return FALSE;
01516     }
01517 
01518     // ok this is silly, but here we go, make the text into shapes so
01519     // it bloomin well prints properly.
01520     NodeGroup* pNGroup = new NodeGroup;
01521     if (pNGroup!=NULL)
01522     {
01523         // stuff it in the tree
01524         pNGroup->AttachNode(pNewGroup1,NEXT);
01525         // copy all children as shapes
01526         if (pNewGroup1->CopyChildrenAsShapes(pNGroup))
01527         {
01528             // rip the node out of the tree and stick it in our cache.
01529             pNGroup->UnlinkNodeFromTree();
01530             // destroy the first group we created
01531             pNewGroup->CascadeDelete();
01532             delete pNewGroup;
01533             // finally stick the thing in our cache!
01534             // rip the node out of the tree and stick it in our cache.
01535             // finally stick the thing in our cache!
01536             UpdateMarkGlyph(pMarkItem, pNGroup);
01537             return TRUE;
01538         }
01539         pNGroup->CascadeDelete();
01540         delete pNGroup;
01541     }
01542 
01543     // rip the node out of the tree and stick it in our cache.
01544     pNewGroup->UnlinkNodeFromTree();
01545     // finally stick the thing in our cache!
01546     UpdateMarkGlyph(pMarkItem, pNewGroup);
01547 
01548     return TRUE;
01549 }
01550 
01551 
01552 /*****************************************************************************************
01553 
01554 >   BOOL PrintMarksCache::SetInfoMarkAttributes(TextStory *pStory, String_64 *pFontName, MILLIPOINT FontSize)
01555 
01556     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01557     Created:    10/08/96
01558     Inputs:     pComp      = the document component containing the print marks
01559                 CurrRegion = the current region we're formatting marks in
01560     Returns:    -
01561     Purpose:    This function creates a text information mark which will describe the
01562                 current print job. As this will be created and destroyed on each print
01563                 it should be reasonably fast to execute. We include the following
01564                 information in the text....
01565 
01566                     Document title
01567                     Date
01568                     Time
01569                     Page number?
01570                     Plate name
01571     
01572 *****************************************************************************************/
01573 
01574 BOOL PrintMarksCache::SetInfoMarkAttributes(TextStory *pStory, String_64 *pFontName, MILLIPOINT FontSize)
01575 {
01576     BOOL ok;
01577 
01578     // Ensure the font is cached. The fontmangler will return a replace font if
01579     // it can't find the required one.
01580     WORD Handle = FONTMANAGER->CacheNamedFont(pFontName);
01581     if (Handle==ILLEGALFHANDLE)
01582         return FALSE;
01583 
01584     // find the first line in this story
01585     TextLine* pTextLine = pStory->FindFirstLine();
01586     if (pTextLine==NULL)
01587         return FALSE;
01588 
01589     // Delete the current instances of the attribute first
01590     ok = DeleteChildAttribute(pTextLine, CC_RUNTIME_CLASS(AttrTxtFontTypeface));
01591     if (!ok) ok = DeleteChildAttribute(pStory, CC_RUNTIME_CLASS(AttrTxtFontTypeface));
01592 
01593     ok = DeleteChildAttribute(pTextLine, CC_RUNTIME_CLASS(AttrTxtFontSize));
01594     if (!ok) ok = DeleteChildAttribute(pStory, CC_RUNTIME_CLASS(AttrTxtFontSize));
01595     
01596     // now create new ones
01597     TxtFontTypefaceAttribute FontAttr(Handle);
01598     TxtFontSizeAttribute     SizeAttr(FontSize);
01599 
01600             ok = ((AttributeValue*)&FontAttr)->MakeNode(pTextLine,PREV) != NULL;
01601     if (ok) ok = ((AttributeValue*)&SizeAttr)->MakeNode(pTextLine,PREV) != NULL;
01602 
01603     return ok;
01604 }
01605 
01606 /***********************************************************************************************
01607 
01608 >   BOOL PrintMarksCache::DeleteChildAttribute(NodeRenderableInk* pParent, CCRuntimeClass* pReqdAttrib)
01609 
01610     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01611     Created:    10/08/96
01612     Inputs:     -
01613     Purpose:    Delete a child attribute of a specified type from this parent.
01614 
01615 ***********************************************************************************************/
01616 
01617 // Should this be in Node.h ?
01618 
01619 BOOL PrintMarksCache::DeleteChildAttribute(NodeRenderableInk* pParent, CCRuntimeClass* pReqdAttrib)
01620 {
01621     ERROR2IF(pParent==NULL || pReqdAttrib==NULL, FALSE, "NULL parameter");
01622     NodeAttribute* pAppliedAttr = pParent->GetChildAttrOfType(pReqdAttrib);
01623     if (!pAppliedAttr)
01624         return FALSE;
01625 
01626     pAppliedAttr->CascadeDelete();
01627     delete pAppliedAttr;
01628     return TRUE;
01629 }
01630 
01631 
01632 
01633 
01634 /***********************************************************************************************
01635 
01636 >   void PrintMarksCache::DestroyTextInfoMark()
01637 
01638     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01639     Created:    10/08/96
01640     Inputs:     -
01641     Purpose:    Throw away any cached print information mark
01642 
01643 ***********************************************************************************************/
01644 
01645 void PrintMarksCache::DestroyTextInfoMark()
01646 {
01647     if (TextInfoHandle>0)
01648     {
01649         PrintMarkItem *pItem = FindMark(TextInfoHandle);
01650         if (pItem!=NULL)
01651         {
01652             pItem = (PrintMarkItem*)PrintMarkCache.RemoveItem(pItem);
01653             if (pItem) delete pItem;
01654         }
01655     }
01656     TextInfoHandle=0;
01657 }
01658 
01659 
01660 /***********************************************************************************************
01661 
01662 >   void PrintMarksCache::BuildTextInfoString(Document *pDocument, RenderRegion* pRRegion, String_256 *pString)
01663 
01664     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01665     Created:    10/08/96
01666     Inputs:     pMark = a print mark item pointer
01667                 pForm = a mark format object pointer
01668     Purpose:    
01669 
01670 ***********************************************************************************************/
01671 
01672 void PrintMarksCache::BuildTextInfoString(Document *pDocument, RenderRegion* pRRegion, String_256 *pString)
01673 {
01674     // First add the doc title to the string
01675     (*pString) = pDocument->GetTitle();
01676     (*pString) += TEXT("  ");
01677 
01678     // now add the date and time (set up by StartPrinting above)
01679     (*pString) += CachedTime;
01680 
01681     // ok add the plate name of the plate we're rendering
01682     ColourPlate *pColPlate = pRRegion->GetRenderView()->GetColourPlate();
01683     if (pColPlate!=NULL)
01684     {
01685         String_64 PlateName;
01686         
01687         pColPlate->GetDescription(&PlateName);
01688         (*pString) += TEXT("  (");
01689         (*pString) += PlateName;
01690         (*pString) += TEXT(")");
01691     }
01692 }
01693 
01694 
01695 
01696 /********************************************************************************************
01697 
01698 >   PageRectList::PageRectList()
01699 
01700     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01701     Created:    31/07/96
01702     Purpose:    The page rect list and all its helper functions provide for the upkeep of
01703                 a list of rectangles. These rectangles generally specify the positions of
01704                 printing pages on a single sheet of paper. For instance, you might be printing
01705                 a single page as 4x4 multiple fit to one sheet of paper. You would then have
01706                 16 rectangle entries in this list. For each entry, the print marks manager
01707                 will render crop marks around the outside of the paper to match up with each
01708                 rectangle. Cool hu?
01709     SeeAlso:
01710 
01711 ********************************************************************************************/
01712 
01713 PageRect::PageRect(const DocRect &rect)
01714 {
01715     Rect = rect;
01716 }
01717 
01718 PageRectList::~PageRectList()
01719 {
01720     DeleteAll();
01721 }
01722 
01723 void PageRectList::DeleteAll()
01724 {
01725     PageRect* pItem;
01726     while ((pItem=((PageRect*)RemoveTail()))) // assignment
01727         delete pItem;
01728 }
01729 
01730 inline PageRect* PageRectList::GetFirstPageRect() const
01731 {
01732     return ((PageRect*)GetHead());
01733 }
01734         
01735 inline PageRect* PageRectList::GetNextPageRect(PageRect* pItem) const
01736 {
01737     return ((PageRect*)GetNext(pItem));
01738 }
01739 
01740 BOOL PageRectList::AddPageRect(const DocRect &rect)
01741 {
01742     if (FindPageRect(rect)==NULL)
01743     {
01744         PageRect *pRect = new PageRect(rect);
01745         if (pRect)
01746         {
01747             AddTail(pRect);
01748             return TRUE;
01749         }
01750         return FALSE;
01751     }
01752     return TRUE;
01753 }
01754 
01755 PageRect* PageRectList::FindPageRect(const DocRect &rect) const
01756 {
01757     PageRect* pItem = GetFirstPageRect();
01758     while (pItem)
01759     {
01760         if (pItem->Rect == rect)
01761             return pItem;
01762         pItem = GetNextPageRect(pItem);
01763     }
01764     return NULL;
01765 }
01766 
01767 
01768 
01769 
01770 
01771 
01772 /*****************************************************************************************
01773 
01774 >   PrintMarksMan::PrintMarksMan()
01775 
01776     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01777     Created:    23/07/96
01778     Purpose:    Constructor for the PrintMarks Manager
01779 
01780 *****************************************************************************************/
01781 
01782 PrintMarksMan::PrintMarksMan()
01783 {
01784     Bleed = 0;
01785     TemplateCached=FALSE;
01786     EmulsionDown=FALSE;
01787 }
01788 
01789 /*****************************************************************************************
01790 
01791 >   PrintMarksMan::PrintMarksMan()
01792 
01793     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01794     Created:    23/07/96
01795     Purpose:    Destruct the PrintMarks manager. We delete all remaining cached items
01796                 here.
01797 
01798 *****************************************************************************************/
01799 
01800 PrintMarksMan::~PrintMarksMan()
01801 {
01802 }
01803 
01804 
01805 /*****************************************************************************************
01806 
01807 >   BOOL PrintMarksMan::IsTemplateCached() const
01808 
01809     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01810     Created:    23/07/96
01811     Returns:    TRUE if we've cached the print marks template once during the life
01812                      of the program
01813                 FALSE if not.
01814     Purpose:    Return whether the disc based template file of marks has been cached once
01815                 already.
01816 
01817 *****************************************************************************************/
01818 
01819 BOOL PrintMarksMan::IsTemplateCached() const
01820 {
01821     return TemplateCached;
01822 }
01823 
01824 
01825 
01826 /*****************************************************************************************
01827 
01828 >   BOOL PrintMarksMan::ConstructCache()
01829 
01830     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01831     Created:    23/07/96
01832     Purpose:    Here we construct the cache afresh. Well almost afresh, we need to 
01833                 do the following
01834                 
01835                 (1) find the disc file containing our marks
01836                 (2) load the file as a document
01837                 (3) convert all index colours used in objects to lookalike doc colours
01838                 (4) enumerate each layer and decode the layer name
01839                 (5) find the group inside the layer which contains the mark
01840                 (6) make a copy of this information as a PrintMarkItem
01841                 (7) merge the PrintMarkItem with the current contents of the cache.
01842                     This is v.important as there will be valuable information already
01843                     in the cache we don't want to lose.
01844                 (8) destroy the document on completion (or partial completion==failure)
01845 
01846                 easy really. We use various lower level functions to perform all of course.
01847 
01848 *****************************************************************************************/
01849 
01850 BOOL PrintMarksMan::ConstructCache()
01851 {
01852     // If its already cached then ignore this call.
01853     if (TemplateCached)
01854         return TRUE;
01855 
01856     BOOL ok=FALSE;
01857     // otherwise do some serious stuff.
01858     TCHAR SearchFile[] = _T("mrktmpl.xar");
01859 //  TCHAR *OutputBuff = new TCHAR[_MAX_PATH];
01860     if (1 /*OutputBuff*/)
01861     {
01862         LoadPrintMarks LdPrintMark;
01863         // try to find the search file...
01864         StringVar s(CamResource::GetResourceFilePath(SearchFile));
01865 PORTNOTE("other", "Disabled printmark resource file finding")
01866 #ifndef EXCLUDE_FROM_XARALX
01867         ok = FileUtil::FindResourceFile(SearchFile, OutputBuff);
01868 #endif
01869         // Add a crop mark bits.
01870         ok = ok && PMMCache.CreateCropMark();
01871         // Add a text info mark too.
01872         ok = ok && PMMCache.CreateTextInfoMark();
01873         // Get the winoil level direct loader to do its stuff
01874         ok = ok && LdPrintMark.Execute(s);
01875         // delete the allocated buffer
01876 //      delete OutputBuff;
01877     }
01878     // return all is well/not well
01879     return (TemplateCached=ok);
01880 }
01881 
01882 
01883 
01884 /*****************************************************************************************
01885 
01886 >   virtual BOOL LoadPrintMarks::OnLoadDocument(Document* pKernelDoc)
01887 
01888     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01889     Created:    06/08/96
01890     Inputs:     pKernelDoc = a pointer to the loaded kernel document
01891     Returns     TRUE if the document was processed correctly
01892                 FALSE if not.
01893     Purpose:    Decode all print marks in this loaded document.
01894 
01895 *****************************************************************************************/
01896 
01897 BOOL LoadPrintMarks::OnLoadDocument(Document* pKernelDoc)
01898 {
01899     // Get a pointer to the marks manager
01900     PrintMarksMan* pPrintMarksMan = GetApplication()->GetMarksManager();
01901     if (pPrintMarksMan==NULL)
01902         return FALSE;
01903     
01904     // ok do the conversion of all colours.
01905     pPrintMarksMan->ConvertAllDocColours(pKernelDoc);
01906     
01907     // ok we now have a loaded document, lets scan of the all the layers we need.
01908     // should we respond to an error from here?
01909     pPrintMarksMan->PMMCache.DecodeCachedLayers(pKernelDoc);
01910     
01911     // All is well we hope.
01912     return TRUE;
01913 }
01914 
01915 
01916 
01917 
01918 /*****************************************************************************************
01919 
01920 >   void PrintMarksMan::ConvertAllDocColours(Document* pDoc)
01921 
01922     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> / Mike
01923     Created:    31/07/96
01924     Purpose:    Convert all the index colours in the document to local doc colours. This
01925                 avoids problems with copying data out of the tree and deleting the index
01926                 colours. What does this mean. Ok, if you make a copy of the print mark,
01927                 put the copy in the PMM and delete the original document, you will
01928                 delete the doc component colour list which contains all used index colour
01929                 definitions. These index col defs contain usage counts which will be
01930                 incremented during the copy. An attempt to delete all these index colours
01931                 will cause an error (index colour still in use) even though its not in
01932                 use in the document. Hence we need to remove all index colour references
01933                 from the document before we make a copy. This is what the function does
01934                 by making local doc colours.
01935 
01936 *****************************************************************************************/
01937 
01938 void PrintMarksMan::ConvertAllDocColours(Document* pDoc)
01939 {
01940     ERROR3IF(pDoc==NULL,"No doc pointer during PrintMarksMan::ConvertAllDocColours!");
01941 
01942     Node *CurNode = Node::DocFindFirstDepthFirst(pDoc);
01943     Node *NextNode;
01944 
01945     while (CurNode !=NULL)
01946     {
01947         // We may be about to chop this node out of the tree, so get the next node now
01948         NextNode = CurNode->DocFindNextDepthFirst();
01949 
01950         // Use to scan the colour fields of the attribute.
01951         UINT32 Context = 0;
01952         DocColour *pColour;
01953 
01954         if (CurNode->IsAnAttribute())
01955         {
01956             NodeAttribute *pNodeAttr = (NodeAttribute *) CurNode;
01957 
01958             // Get the next colour field from the attribute
01959             pColour = pNodeAttr->EnumerateColourFields(Context++);
01960 
01961             while (pColour != NULL)
01962             {
01963                 // For each colour field, make sure the colour is a local DocColour so that
01964                 // the sub-tree is entirely stand-alone
01965                 if (pColour->FindParentIndexedColour() != NULL)
01966                 {
01967                     ColourGeneric ColDef;
01968                     ColourContext *cc = ColourManager::GetColourContext(pColour->GetColourModel());
01969                     ERROR3IF(cc == NULL, "Can't find colour context?!");
01970 
01971                     // Get the IndexedColour definition as a standalone colour definition
01972                     cc->ConvertColour(pColour->FindParentIndexedColour(), &ColDef);
01973 
01974                     // Make the DocColour into a simple standalone "lookalike" of the parent colour
01975                     *pColour = DocColour(pColour->GetColourModel(), &ColDef);
01976                 }
01977 
01978                 pColour = pNodeAttr->EnumerateColourFields(Context++);
01979             }
01980         }
01981         CurNode = NextNode;
01982     }
01983 }
01984 
01985 
01986 /*****************************************************************************************
01987 
01988 >   void PrintMarksMan::InvalidateCache()
01989 
01990     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01991     Created:    29/07/96
01992     Inputs:     -
01993     Returns:    -
01994     Purpose:    Throws away the cache entirely. We unset the 'Template has been cached'
01995                 variable which will result in a proper refiltering of the mark template
01996                 file the next time we initialise.
01997     
01998 *****************************************************************************************/
01999 
02000 void PrintMarksMan::InvalidateCache()
02001 {
02002     // Force a proper recache next time the marks are accessed
02003     TemplateCached=FALSE;
02004     // Destroy everything in the current marks list
02005     PMMCache.Invalidate();
02006 }
02007 
02008 
02009 
02010 /*****************************************************************************************
02011 
02012 >   BOOL PrintMarksMan::AddMarkToDoc(UINT32 MarkHandle, Document* pDocument)
02013 
02014     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02015     Created:    29/07/96
02016     Inputs:     MarkHandle = the handle of the mark to add
02017                 pDocument = a pointer to a document to add the mark to
02018     Returns:    TRUE if the mark has been added,
02019                 FALSE if not.
02020     Purpose:    Add a mark reference to the documents displayable printer marks
02021     
02022 *****************************************************************************************/
02023 
02024 BOOL PrintMarksMan::AddMarkToDoc(UINT32 MarkHandle, Document* pDocument)
02025 {
02026     ERROR2IF(pDocument==NULL,FALSE,"NULL document pointer passed to AddMarkToDoc!");
02027     // Sanity check, make sure this mark handle actually exists
02028     if (!PMMCache.FindMark(MarkHandle))
02029     {
02030         ERROR3("Illegal handle given to PrintMarksMan::AddMarkToDoc");
02031         return FALSE;
02032     }
02033 
02034     // ok, try to find the print marks component in this document.
02035     PrintMarksComponent* pComponent = 
02036     (PrintMarksComponent*)pDocument->GetDocComponent(CC_RUNTIME_CLASS(PrintMarksComponent));
02037     if (!pComponent)
02038     {
02039         ERROR3("We're stimmied, there's no PrintMarksComponent in this document!");
02040         return FALSE;
02041     }
02042 
02043     // super duper, we've got the doc component, so lets add our mark reference to
02044     // its list.
02045     return pComponent->AddMark(MarkHandle);
02046 }
02047 
02048 
02049 
02050 
02051 /*****************************************************************************************
02052 
02053 >   BOOL PrintMarksMan::RemoveMarkFromDoc(UINT32 MarkHandle, Document* pDocument)
02054 
02055     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02056     Created:    29/07/96
02057     Inputs:     MarkHandle = the handle of the mark to remove
02058                 pDocument = a pointer to a document to remove the mark from
02059     Returns:    TRUE if the mark has been removed
02060                 FALSE if not. This result will occur only when the document does not
02061                 contain a print marks component or I cannot find the specified mark.
02062                 If the mark exists it will never fail to be removed.
02063     Purpose:    Removes the mark reference held in the print marks doc component inside
02064                 this document.
02065     
02066 *****************************************************************************************/
02067 
02068 BOOL PrintMarksMan::RemoveMarkFromDoc(UINT32 MarkHandle, Document* pDocument)
02069 {
02070     ERROR2IF(pDocument==NULL,FALSE,"NULL document pointer passed to AddMarkToDoc!");
02071     // ok, try to find the print marks component in this document.
02072     PrintMarksComponent* pComponent = 
02073     (PrintMarksComponent*)pDocument->GetDocComponent(CC_RUNTIME_CLASS(PrintMarksComponent));
02074     if (!pComponent)
02075     {
02076         ERROR3("We're stimmied, there's no PrintMarksComponent in this document!");
02077         return FALSE;
02078     }
02079 
02080     // super duper, we've got the doc component, so lets add our mark reference to
02081     // its list.
02082     pComponent->RemoveMark(MarkHandle);
02083     return TRUE;
02084 }
02085 
02086 
02087 
02088 
02089 /*****************************************************************************************
02090 
02091 >   BOOL PrintMarksMan::AddDefaultMarksToDoc(Document* pDocument)
02092 
02093     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02094     Created:    29/07/96
02095     Inputs:     pDocument = a pointer to a document to add the default set to
02096     Returns:    TRUE if all 'defaults to on' marks have been added,
02097                 FALSE if none have.
02098     Purpose:    Add all 'defaults to on' mark references to the documents displayable 
02099                 printer marks.
02100     
02101 *****************************************************************************************/
02102 
02103 BOOL PrintMarksMan::AddDefaultMarksToDoc(Document* pDocument)
02104 {
02105     ERROR3IF(pDocument==NULL,"NULL document pointer passed to AddDefaultMarks()");
02106     BOOL Added=FALSE;
02107     if (pDocument!=NULL)
02108     {
02109         // Get that print marks doc component
02110         PrintMarksComponent* pMarksComp = 
02111         (PrintMarksComponent*)pDocument->GetDocComponent(CC_RUNTIME_CLASS(PrintMarksComponent));
02112         if (pMarksComp && pMarksComp->IsVirgin())
02113         {
02114             // now go through each print mark and add it if necessary
02115             PrintMarkItem* pMarkItem = PMMCache.GetFirstMark();
02116             while (pMarkItem)
02117             {
02118                 // check to see if this mark is on by default
02119                 if (pMarkItem->DefaultsToOn())
02120                 {
02121                     // Add this item to the document
02122                     UINT32 handle = pMarkItem->GetHandle();
02123                     pMarksComp->AddMark(handle);
02124                 }
02125                 // find the next print mark item
02126                 pMarkItem = PMMCache.GetNextMark(pMarkItem);
02127             }
02128             // ok we've tried to add em.
02129             Added=TRUE;
02130         }
02131     }
02132     return Added;
02133 }
02134 
02135 
02136 
02137 
02138 
02139 
02140 
02141 /*****************************************************************************************
02142 
02143 >   void PrintMarksMan::SetImagesettingRect()
02144 
02145     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02146     Created:    29/07/96
02147     Inputs:     -
02148     Returns:    -
02149     Purpose:    Define the print marks rectangle. During a print this rectangle will
02150                 determin where print marks will be placed. For instance if you are
02151                 printing a 2x2 multiple fit page, the print marks rectangle will be the
02152                 union of all these page tiles. Hence the print marks will be places around
02153                 the entire print area. Crop marks will be placed in this area too but
02154                 will be positioned to align with each page.
02155     Notes:      The union of the PageRects, added while printing the current paper will
02156                 give the imagesetting rectangle. Each one of these PageRects needs a
02157                 set of crop marks.
02158     
02159 *****************************************************************************************/
02160 
02161 void PrintMarksMan::SetImagesettingRect()
02162 {
02163     ImagesettingRect.MakeEmpty();
02164     PageRect* pRect = PageRects.GetFirstPageRect();
02165     while (pRect)
02166     {
02167         ImagesettingRect = ImagesettingRect.Union(pRect->Rect);
02168         pRect = PageRects.GetNextPageRect(pRect);
02169     }
02170 }
02171 
02172 
02173 
02174 
02175 /*****************************************************************************************
02176 
02177 >   void PrintMarksMan::StartPrinting()
02178 
02179     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02180     Created:    29/07/96
02181     Inputs:     -
02182     Returns:    -
02183     Purpose:    Called from the print control system to tell the print mark manager that
02184                 printing has started. Here we make sure all our print time local variables
02185                 are set to default values.
02186     
02187 *****************************************************************************************/
02188 
02189 void PrintMarksMan::StartPrinting()
02190 {
02191     // destroy the current set of rectangles
02192     PageRects.DeleteAll();
02193     ImagesettingRect.MakeEmpty();
02194     EmulsionDown=FALSE;
02195     Bleed=0;
02196     // now cache the print time
02197     CCTime MyTime;
02198     PMMCache.CachedTime.Empty();
02199     String_64 TimeFormat(_T("%dy/%mt/%yr  %th.%mn %pm"));
02200     MyTime.ConvertStandardDateAndTime(&TimeFormat, &PMMCache.CachedTime);
02201 }
02202 
02203 
02204 /*****************************************************************************************
02205 
02206 >   void PrintMarksMan::EndPrinting()
02207 
02208     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02209     Created:    29/07/96
02210     Inputs:     -
02211     Returns:    -
02212     Purpose:    Called from the print control system to tell the print mark manager that
02213                 printing has ended. Here we delete all the page rectangle positions added
02214                 to our cached list.
02215     
02216 *****************************************************************************************/
02217 
02218 void PrintMarksMan::EndPrinting()
02219 {
02220     PageRects.DeleteAll();
02221     ImagesettingRect.MakeEmpty();
02222 }
02223 
02224 
02225 
02226 /*****************************************************************************************
02227 
02228 >   void PrintMarksMan::SetBleed(MILLIPOINT bleed)
02229 
02230     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02231     Created:    29/07/96
02232     Inputs:     bleed = the bleed used during this print
02233     Returns:    -
02234     Purpose:    Tells the print marks manager what bleed to use during this print pass.
02235                 This is usually a globally set value and is unlikely to change across
02236                 plates or pages. We use the value to inflate the typesetting rect by.
02237     
02238 *****************************************************************************************/
02239 
02240 void PrintMarksMan::SetBleed(MILLIPOINT bleed)
02241 {
02242     Bleed=bleed;
02243 }
02244 
02245 
02246 /*****************************************************************************************
02247 
02248 >   BOOL PrintMarksMan::AddPageRect(const DocRect& rect)
02249 
02250     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02251     Created:    29/07/96
02252     Inputs:     rect = a document rectangle specifying the a pages position in the
02253                        print paper coordinate system
02254     Returns:    -
02255     Purpose:    This function provides the ability to specify n page rectangles. Each of
02256                 these rectangles will have crop marks positioned around the paper edge to
02257                 line up with this rectangle. Hence the print system uses this function
02258                 to specify the final positions of all the multi fit page rectangles during
02259                 a print. We make sure we then create and render the right number of crop
02260                 marks to fit this rectangle list.
02261     SeeAlso:    ScreenView::EnumeratePagePatches().
02262     
02263 *****************************************************************************************/
02264 
02265 BOOL PrintMarksMan::AddPageRect(const DocRect& rect)
02266 {
02267     // add this rectangle
02268     return PageRects.AddPageRect(rect);
02269 }
02270 
02271 
02272 
02273 /*****************************************************************************************
02274 
02275 >   void PrintMarksMan::SetEmulsionDown(BOOL state)
02276 
02277     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02278     Created:    29/07/96
02279     Inputs:     state = the new state of the emulsion down flag the print marks manager
02280                         will use during this print
02281     Returns:    -
02282     Purpose:    Tells the print marks manager which way up the emulsion is. This determins
02283                 whether the marks manager will flip its marks during rendering or not.
02284     
02285 *****************************************************************************************/
02286 
02287 void PrintMarksMan::SetEmulsionDown(BOOL state)
02288 {
02289     EmulsionDown=state;
02290 }   
02291 
02292 
02293 /*****************************************************************************************
02294 
02295 >   void PrintMarksMan::ResetPageRects()
02296 
02297     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02298     Created:    29/07/96
02299     Inputs:     -
02300     Returns:    -
02301     Purpose:    Destroys the list of page rectangles the print marks manager caches.
02302     
02303 *****************************************************************************************/
02304 
02305 void PrintMarksMan::ResetPageRects()
02306 {
02307     PageRects.DeleteAll();
02308 }
02309 
02310 
02311 
02312 /*****************************************************************************************
02313 
02314 >   MILLIPOINT PrintMarksMan::AdjustedBleed() const
02315 
02316     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02317     Created:    29/07/96
02318     Inputs:     -
02319     Returns:    the size of the bleed as we know it
02320     Purpose:    Internal function to get the adjusted bleed value
02321     
02322 *****************************************************************************************/
02323 
02324 MILLIPOINT PrintMarksMan::AdjustedBleed() const
02325 {
02326     return (Bleed+OUTSIDEBLEEDWIDTH);
02327 }
02328 
02329 /*****************************************************************************************
02330 
02331 >   void PrintMarksMan::RenderPrintMarks(Document *ScopeDoc, BOOL DisplayEm=TRUE, BOOL LoadTemplateMarks=TRUE);
02332 
02333     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>/Jason
02334     Created:    ... / 28/8/96
02335     Inputs:     ScopeDoc - points to the document for which you want to find out.
02336                 Pass in NULL to use the selected doc.
02337 
02338                 DisplayEm - TRUE to enable, FALSE to disable, printing of printers marks
02339 
02340                 LoadTemplateMarks - TRUE to ensure that the printers marks are cached in the
02341                 PMM, or FALSE to merely enable/disable printing thereof. Note that if the PMM
02342                 cache is not initialised, then no print marks are available, and hence this
02343                 variable defaults to TRUE. If they're already cached, nothing is done.
02344 
02345     Purpose:    Enable/Disable output of printers marks for the given document
02346 
02347     SeeAlso:    PrinterMarksMan::ShowPrintMarks;
02348                 TypesetInfo::SetOutputPrintersMarks
02349 
02350 *****************************************************************************************/
02351 
02352 void PrintMarksMan::RenderPrintMarks(Document *ScopeDoc, BOOL DisplayEm, BOOL UpdateCache)
02353 {
02354     TypesetInfo *pInfo = TypesetInfo::FindTypesetInfoForDoc(ScopeDoc);
02355     if (pInfo != NULL)
02356         pInfo->SetOutputPrintersMarks(DisplayEm);
02357 
02358     if (DisplayEm && UpdateCache)
02359         ConstructCache();
02360 }
02361 
02362 
02363 
02364 /*****************************************************************************************
02365 
02366 >   BOOL PrintMarksMan::ShowPrintMarks(Document *ScopeDoc) const
02367 
02368     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02369     Created:    28/8/96
02370     Inputs:     ScopeDoc - points to the document for which you want to find out.
02371                 Pass in NULL to use the selected doc.
02372 
02373     Returns:    TRUE if printers marks will be output when printing this document
02374 
02375     Purpose:    Determine if a docuemnt will output printers marks when printing
02376 
02377     SeeAlso:    PrinterMarksMan::RenderPrintMarks;
02378                 TypesetInfo::SetOutputPrintersMarks
02379 
02380 *****************************************************************************************/
02381 
02382 BOOL PrintMarksMan::ShowPrintMarks(Document *ScopeDoc) const
02383 {
02384     TypesetInfo *pInfo = TypesetInfo::FindTypesetInfoForDoc(ScopeDoc);
02385     if (pInfo != NULL)
02386         return(pInfo->OutputPrintersMarks());
02387 
02388     return(FALSE);
02389 }
02390 
02391 
02392 MILLIPOINT PrintMarksMan::GetCropMarkWidth(Document *ScopeDoc) const
02393 {
02394     if (ShowPrintMarks(ScopeDoc))
02395         return (CROPMARK_LENGTH + OUTSIDEBLEEDWIDTH);
02396     else
02397         return 0;
02398 }
02399 
02400 
02401 
02402 /*****************************************************************************************
02403 
02404 >   void PrintMarksMan::RenderPrintMarks(PrintMarksComponent *pComp, 
02405                                          RenderRegion* pRRegion, 
02406                                          const Matrix &ViewTrans,
02407                                          const DocRect &ClipRect,
02408                                          Spread* pSpread)
02409     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02410     Created:    10/08/96
02411     Inputs:     pComp   = the document component containing the print marks
02412                 pRRegion= the render region to draw in
02413                 pSpread = the spread to draw
02414     Returns:
02415     Purpose:    Render all print marks contained in this doc component and the crop
02416                 marks if they are enabled.
02417     
02418 *****************************************************************************************/
02419 
02420 void PrintMarksMan::RenderPrintMarks(PrintMarksComponent *pComp, 
02421                                      RenderRegion* pRRegion,
02422                                      const Matrix &ViewTrans,
02423                                      const DocRect &ClipRect,
02424                                      Spread* pSpread)
02425 {
02426     // if any of these are null we can't do the job
02427     if (pComp==NULL || pRRegion==NULL || pSpread==NULL)
02428         return;
02429 
02430     // do we need to display our marks?
02431     if ( !ShowPrintMarks( (Document *) (pSpread->FindOwnerDoc()) ) )
02432         return;
02433 
02434     // if there's no imagesetting rect to render around we can't position our marks
02435     if (ImagesettingRect.IsEmpty())
02436         return;
02437 
02438     // Go get the adjusted bleed
02439     MILLIPOINT adjbleed = AdjustedBleed();
02440 
02441     // is this region a postscript render region?
02442 PORTNOTE("printing", "disabled print mark generation use of PrintPSRenderRegion")
02443 #ifndef EXCLUDE_FROM_XARALX
02444     BOOL OldClipState = FALSE;
02445     BOOL IsPostScript = pRRegion->IS_KIND_OF(PrintPSRenderRegion);
02446     PSPrintDC *pPrintDC = NULL;
02447 
02448     // configure the postscript clipping region
02449     if (IsPostScript)
02450     {
02451         // Get the render DC
02452         pPrintDC = (PSPrintDC*)pRRegion->GetRenderDC();
02453         if (pPrintDC==NULL)
02454             return;
02455 
02456         // Disable the print clipping for the moment
02457         OldClipState = pPrintDC->SetClipping(FALSE);
02458     }
02459 #endif      
02460 
02461     // check for any user doc marks
02462     DocPrintMark* pDocMark = pComp->GetFirstMark();
02463     if (pDocMark!=NULL)
02464     {
02465         // Update the text info mark now. This builds the time/date etc.
02466         Document* pDoc = Document::GetSelected();
02467         PMMCache.UpdateTextInfoMark(pDoc, pRRegion);
02468 
02469         // get the bleed size used in this spread
02470         RenderPrintMarksAroundRect(pComp, pRRegion, NULL, ImagesettingRect, adjbleed);
02471 
02472         // ok are crop marks created?
02473         if (PMMCache.CropMarkHandle>0)
02474         {
02475             // and are they in this document component?
02476             if (pComp->FindMark(PMMCache.CropMarkHandle)!=NULL)
02477                 RenderCropMarksAroundRect(pRRegion, NULL, ImagesettingRect, adjbleed);
02478         }
02479     }
02480 
02481 PORTNOTE("printing", "disabled print mark generation use of PrintPSRenderRegion")
02482 #ifndef EXCLUDE_FROM_XARALX
02483     // finalise any bleed area clipping in PostScript
02484     if (IsPostScript)
02485     {
02486         if (pPrintDC)
02487         {
02488             // Reset the clipping state of affairs.
02489             pPrintDC->SetClipping(TRUE); //OldClipState);
02490             // Export the cliptobleed stuff
02491             pPrintDC->OutputPSClipping();
02492             // ClipToBleed(pRRegion,pSpread);
02493         }
02494     }
02495 #endif
02496 }
02497 
02498 
02499 
02500 
02501 /*****************************************************************************************
02502 
02503 >   woid PrintMarksMan::ClipToBleed(RenderRegion *pRRegion,Spread *pSpread)
02504 
02505     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02506     Created:    28/8/96
02507     Inputs:     pRRegion = a pointer to a render region
02508                 Pass in NULL to use the selected doc.
02509     Returns:    -
02510     Purpose:    Export the bleed rectangle as the current clipping region. All graphics
02511                 will be clipped to this region.
02512 
02513 *****************************************************************************************/
02514 
02515 void PrintMarksMan::ClipToBleed(RenderRegion* pRRegion,Spread *pSpread)
02516 {
02517     // if any of these are null we can't do the job
02518     if (pRRegion==NULL)
02519         return;
02520 
02521     // if there's no imagesetting rect to render around we can't position our marks
02522     if (ImagesettingRect.IsEmpty())
02523         return;
02524 
02525     // do we need to display our marks?
02526     if ( !ShowPrintMarks( (Document *) (pSpread->FindOwnerDoc()) ) )
02527         return;
02528 
02529 PORTNOTE("printing", "disabled print mark generation use of PrintPSRenderRegion")
02530 #ifndef EXCLUDE_FROM_XARALX
02531     // dont render to a none postscript region
02532     if ( !IS_A(pRRegion, PrintPSRenderRegion) )
02533         return;
02534 
02535     // BODGE ALERT...
02536     // Clip everything else to this imagesetting rectangle
02537 
02538     // Go get the adjusted bleed
02539     MILLIPOINT adjbleed = AdjustedBleed();
02540     DocRect Rect = ImagesettingRect;
02541     Rect.Inflate(adjbleed);
02542     PSPrintDC *pPrintDC = (PSPrintDC*)pRRegion->GetRenderDC();
02543     ((PrintPSRenderRegion*)pRRegion)->WriteClipRegion(pPrintDC, Rect);
02544 
02545     // BODGE ALERT
02546     // Mike 02/09/96 - We should be performing stacked clipping. This is not the place
02547     //                 to alter the postscript clip region but if will suffice for now.
02548 #endif
02549 }
02550 
02551 
02552 
02553 /*****************************************************************************************
02554 
02555 >   void PrintMarksMan::RenderCropMarksAroundRect( RenderRegion* pRRegion,
02556                                                    const Matrix &trans
02557                                                    const DocRect& Rect, 
02558                                                    MILLIPOINT bleed)
02559 
02560     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02561     Created:    10/08/96
02562     Inputs:     pRRegion= the render region to draw in
02563                 pSpread = the spread to draw
02564     Returns:
02565     Purpose:    Render all print marks contained in this doc component and the crop
02566                 marks if they are enabled around the given rectangle.
02567     
02568 *****************************************************************************************/
02569 
02570 void PrintMarksMan::RenderCropMarksAroundRect(RenderRegion* pRRegion,
02571                                               const Matrix *pTrans,
02572                                               const DocRect &Rect,
02573                                               MILLIPOINT bleed)
02574 {
02575     // create a cropline path and set it up
02576     Path CropLine;
02577     if (!CropLine.Initialise())
02578         return;
02579 
02580     // an extra bit we pust the marks out by if the bleed is zero       
02581     INT32 ExtraBit = 0;
02582     if (bleed==0)
02583         ExtraBit = 2384;
02584 
02585     // transform the rectangle if necessary
02586     DocRect TransformedRect(Rect);
02587     TransformedRect.Inflate(bleed+ExtraBit);
02588     if (pTrans)
02589     {
02590         pTrans->transform(&TransformedRect.lo);
02591         pTrans->transform(&TransformedRect.hi);
02592     }
02593 
02594     MILLIPOINT Tmp;
02595 
02596     if (TransformedRect.lo.x > TransformedRect.hi.x)
02597     {
02598         Tmp = TransformedRect.lo.x;
02599         TransformedRect.lo.x = TransformedRect.hi.x;
02600         TransformedRect.hi.x = Tmp;
02601     }
02602 
02603     if (TransformedRect.lo.y > TransformedRect.hi.y)
02604     {
02605         Tmp = TransformedRect.lo.y;
02606         TransformedRect.lo.y = TransformedRect.hi.y;
02607         TransformedRect.hi.y = Tmp;
02608     }
02609 
02610     // Calculate the inverse of the render matrix, this allows us to render
02611     // through a scaling render region and prevent our marks being scaled.
02612     Matrix ViewTrans = pRRegion->GetMatrix();
02613     ViewTrans = ViewTrans.Inverse();
02614 
02615     // get the cropmark length
02616     INT32 Length = CROPMARK_LENGTH;
02617     double Thickness = CROPMARK_THICKNESS;
02618 
02619     // now adjust it a little as we may be pushing the cropmarks out
02620     // by 1mm and taking 1mm off the length. This is only done when there
02621     // is no bleed set and means the cropmarks don't touch each other.
02622     Length -= ExtraBit;
02623     if (Length<1) Length=1;
02624 
02625     // ok we need to scale the thickness dependent on the current scale
02626     // facter within this render region otherwise, the region will scale it
02627     // for us which would be real bad stuff indeed.
02628     FIXED16 CurrScale;
02629     ViewTrans.Decompose(&CurrScale);
02630     double scale = CurrScale.MakeDouble();
02631     // Emulsion down does its stuff by getting the render matrix to flip about
02632     // the Y axis. This shows up in the scale as a negative value returned. We
02633     // need the absoulte scale.
02634     if (scale<0) scale = -scale;
02635     Thickness = Thickness*scale;
02636     INT32 Thick = (INT32)(Thickness+0.5);
02637     if (Thick<1) Thick=1;
02638 
02639     // start setting attributes in this render context
02640     pRRegion->SaveContext();
02641     pRRegion->SetLineColour(COLOUR_BLACK);
02642     pRRegion->SetLineWidth(Thick);
02643 
02644     // Set up some dummy data
02645     CropLine.AddMoveTo(DocCoord(0,0));
02646     CropLine.AddLineTo(DocCoord(72000,0));
02647     // Get the coords array in our cropline path
02648     DocCoord *Coords = CropLine.GetCoordArray();
02649 
02650     // go through all our registered page rectangles and generate
02651     DocCoord iLo = TransformedRect.lo;
02652     DocCoord iHi = TransformedRect.hi;
02653 
02654     // process all our page rectangles
02655     PageRect *pRect = PageRects.GetFirstPageRect();
02656     DocCoord p0,p1,rLo,rHi;
02657 
02658     // ok finally render them all
02659 #define LINEDRAW(p,q) \
02660         ViewTrans.transform(&p); \
02661         ViewTrans.transform(&q); \
02662         Coords[0]=p;  \
02663         Coords[1]=q;  \
02664         pRRegion->DrawPath(&CropLine);
02665     
02666     while (pRect)
02667     {
02668         rLo = pRect->Rect.lo;
02669         rHi = pRect->Rect.hi;
02670 
02671         p0.x = iLo.x; 
02672         p1.x = iLo.x - Length;
02673         p0.y = p1.y = rLo.y;
02674         LINEDRAW(p0,p1);
02675         p0.x = iLo.x; 
02676         p1.x = iLo.x - Length;
02677         p0.y = p1.y = rHi.y;
02678         LINEDRAW(p0,p1);
02679         
02680         p0.y = iHi.y;
02681         p1.y = iHi.y + Length;
02682         p0.x = p1.x = rLo.x;
02683         LINEDRAW(p0,p1);
02684         p0.y = iHi.y;
02685         p1.y = iHi.y + Length;
02686         p0.x = p1.x = rHi.x;
02687         LINEDRAW(p0,p1);
02688     
02689         p0.x = iHi.x;
02690         p1.x = iHi.x + Length;
02691         p0.y = p1.y = rHi.y;
02692         LINEDRAW(p0,p1);
02693         p0.x = iHi.x;
02694         p1.x = iHi.x + Length;
02695         p0.y = p1.y = rLo.y;
02696         LINEDRAW(p0,p1);
02697 
02698         p0.y = iLo.y;
02699         p1.y = iLo.y - Length;
02700         p0.x = p1.x = rHi.x;
02701         LINEDRAW(p0,p1);
02702         p0.y = iLo.y;
02703         p1.y = iLo.y - Length;
02704         p0.x = p1.x = rLo.x;
02705         LINEDRAW(p0,p1);
02706 
02707         pRect = PageRects.GetNextPageRect(pRect);
02708     }
02709 
02710 #undef LINEDRAW
02711 
02712     // pop the attribute context again
02713     pRRegion->RestoreContext();
02714 }
02715 
02716 
02717 
02718 
02719 
02720 /*****************************************************************************************
02721 
02722 >   void PrintMarksMan::RenderPrintMarksAroundRect(PrintMarksComponent *pComp,
02723                                                    RenderRegion* pRRegion,
02724                                                    const Matrix &trans
02725                                                    const DocRect& Rect, 
02726                                                    MILLIPOINT bleed)
02727 
02728     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02729     Created:    10/08/96
02730     Inputs:     pComp   = the document component containing the print marks
02731                 pRRegion= the render region to draw in
02732                 pSpread = the spread to draw
02733     Returns:
02734     Purpose:    Render all user print marks contained in this doc component 
02735     
02736 *****************************************************************************************/
02737 
02738 void PrintMarksMan::RenderPrintMarksAroundRect(PrintMarksComponent *pComp,
02739                                                RenderRegion* pRRegion,
02740                                                const Matrix *pTrans,
02741                                                const DocRect &Rect,
02742                                                MILLIPOINT bleed)
02743 {
02744     pRRegion->SaveContext();
02745 
02746     // transform the rectangle if necessary
02747     DocRect TransformedRect(Rect);
02748     if (pTrans)
02749     {
02750         pTrans->transform(&TransformedRect.lo);
02751         pTrans->transform(&TransformedRect.hi);
02752     }
02753 
02754     // construct all 16 regions around this page rect
02755     PageMarkRegions MyPageRegions;
02756     MyPageRegions.Initialise(TransformedRect,bleed);
02757     Matrix OuterTransform;
02758     if (EmulsionDown)
02759     {
02760         DocRect Rect = TransformedRect;
02761         Rect.Inflate(bleed);
02762         INT32 w = Rect.Width();
02763         OuterTransform *= Matrix(-Rect.lo);
02764         OuterTransform *= Matrix(FIXED16(-1), FIXED16(0), FIXED16(0), FIXED16(1), w, 0);
02765         OuterTransform *= Matrix(Rect.lo);
02766     }
02767 
02768     for (INT32 i=0; i<MAXPAGEREGIONS; i++)
02769     {
02770         if (MyPageRegions.Region[i].Valid)
02771         {
02772             // Make sure the formatting region is empty first
02773             MFRegion.Empty();
02774             MFRegion.SetPosition(MyPageRegions.Region[i].Pos);
02775             MFRegion.SetOrientation(MyPageRegions.Region[i].OrientX);
02776 //          MFRegion.SetFlipRender(EmulsionDown);
02777             CompileMarkRegion(pComp, (MarkRegion)i );
02778             MFRegion.Render(pRRegion,OuterTransform);
02779         }
02780     }   
02781     // pop the attribute context again
02782     pRRegion->RestoreContext();
02783 }
02784 
02785 
02786 
02787 
02788 /*
02789 
02790     {
02791         // there should be at least one page in this spread
02792         Page *pCurrPage = pSpread->FindFirstPageInSpread();
02793         if (!pCurrPage)
02794             return;
02795 
02796         // Create a full quality attr to render
02797         Quality Qual;
02798         Qual.SetQuality(QUALITY_MAX);
02799         QualityAttribute QualAttrVal(Qual);
02800         AttrQuality* pAttrQuality = (AttrQuality*)QualAttrVal.MakeNode();
02801         if (pAttrQuality != NULL)
02802         {
02803             // render it
02804             pAttrQuality->Render(pRRegion);
02805             delete pAttrQuality;
02806         }
02807 
02808         // We now need to examine the page structure in this spread
02809         // and also how it will be printed if we are printing. We may be
02810         // printing a double page spread either as two separate pages or
02811         // as a single spread. This makes a large difference to where the
02812         // marks format.
02813 
02814         DocRect CurrPageRect,PrevPageRect,NextPageRect;
02815         Page *pPrevPage, *pNextPage;
02816         pPrevPage=NULL;
02817 
02818         BOOL sl,sr,st,sb;
02819         sl=sr=sb=st=FALSE;
02820 
02821         while (pCurrPage)
02822         {
02823             // Get the page rect measured in millipoints
02824             PrevPageRect = CurrPageRect;
02825             CurrPageRect = pCurrPage->GetPageRect();
02826             pNextPage = pCurrPage->FindNextPage();
02827 
02828             if (pPrevPage)
02829             {
02830                 sl=(PrevPageRect.hi.x==CurrPageRect.lo.x);
02831                 sr=(PrevPageRect.lo.x==CurrPageRect.hi.x);
02832                 sb=(PrevPageRect.hi.y==CurrPageRect.lo.y);
02833                 st=(PrevPageRect.lo.y==CurrPageRect.hi.y);
02834             }
02835 
02836             if (pNextPage)
02837             {
02838                 NextPageRect=pNextPage->GetPageRect();
02839                 sl=sl || (NextPageRect.hi.x==CurrPageRect.lo.x);
02840                 sr=sr || (NextPageRect.lo.x==CurrPageRect.hi.x);
02841                 sb=sb || (NextPageRect.hi.y==CurrPageRect.lo.y);
02842                 st=st || (NextPageRect.lo.y==CurrPageRect.hi.y);
02843             }
02844 
02845             
02846             // construct all 16 regions around this page rect, we will itterate
02847             // through these later
02848 
02849 
02850             if (sl)
02851                 MyPageRegions.HideLeft();
02852             if (sr)
02853                 MyPageRegions.HideRight();
02854             if (sb)
02855                 MyPageRegions.HideBottom();
02856             if (st)
02857                 MyPageRegions.HideTop();
02858             
02859 
02860             RenderPrintMarksAroundRect(CurrPageRect, bleed, ViewTrans);
02861 
02862             pPrevPage=pCurrPage;
02863             pCurrPage=pNextPage;
02864             pNextPage=NULL;
02865         }
02866     }
02867     else
02868 
02869 
02870 */
02871 
02872 
02873 
02874 /*****************************************************************************************
02875 
02876 >   void PrintMarksMan::CompileMarkRegion(PrintMarksComponent *pComp, MarkRegion CurrRegion)
02877 
02878     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02879     Created:    10/08/96
02880     Inputs:     pComp      = the document component containing the print marks
02881                 CurrRegion = the current region we're formatting marks in
02882     Returns:    -
02883     Purpose:    Add all the marks which are supposedly in this region into the region
02884                 and format em before rendering. What happens is this. Each mark
02885                 reference in the doc component is found in the marks manager. The record
02886                 in the marks manager describes the regions the mark should be formatted
02887                 into. We add the mark if it happens to be the right region on entry.
02888                 Adding the mark to the formatting region adds a position record which
02889                 is used to render the mark when the region is rendered.
02890     
02891 *****************************************************************************************/
02892 
02893 void PrintMarksMan::CompileMarkRegion(PrintMarksComponent *pComp, MarkRegion CurrRegion)
02894 {
02895     UINT32 handle;
02896     // Dig the mark reference out of this doc component.
02897     DocPrintMark* pDocMark = pComp->GetFirstMark();
02898     while (pDocMark)
02899     {
02900         // retrieve the reference handle of this mark
02901         handle=pDocMark->GetHandle();
02902 
02903         // find the mark item in the print marks cache
02904         PrintMarkItem* pMarkItem = PMMCache.FindMark(handle);
02905         if (pMarkItem && pMarkItem->NeedsToRender())
02906         {
02907             // ok we have a pointer to the mark item. Scan through all its format
02908             // positions and add the mark if necessary
02909             PrintMark* pPrintMark = pMarkItem->GetPrintMark();
02910             if (pPrintMark)
02911             {
02912                 MarkPosition* pMarkPosition = pPrintMark->GetFirstPosition();
02913                 while (pMarkPosition!=NULL)
02914                 {
02915                     if (pMarkPosition->GetRegion()==CurrRegion)
02916                     {
02917                         MarkFormat LocalFormat = pMarkPosition->GetFormat();
02918                         MFRegion.AddMark(pMarkItem, &LocalFormat);
02919                     }
02920 
02921                     pMarkPosition = pPrintMark->GetNextPosition(pMarkPosition);
02922                 }
02923             }
02924         }
02925 
02926         // go onto format and render the next object
02927         pDocMark = pComp->GetNextMark(pDocMark);
02928     }
02929 }
02930 
02931 
02932 
02933 
02934 
02935 /*****************************************************************************************
02936 
02937 >   PageMarkRegions::PageMarkRegions(const DocRect& page, MILLIPOINT bleed)
02938 
02939     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02940     Created:    10/08/96
02941     Inputs:     page = the docrect containing the page coordinates.
02942                 bleed = the size of the bleed area (in page coordinates, ie millipoints)
02943     Returns:    -
02944     Purpose:    Creates 16 mark formatting regions around a given page, with a
02945                 specified bleed
02946     
02947 *****************************************************************************************/
02948 
02949 PageMarkRegion::PageMarkRegion()
02950 {
02951     OrientX=TRUE;
02952     Valid=FALSE;
02953 }
02954 
02955 
02956 PageMarkRegions::PageMarkRegions()
02957 {
02958 }
02959 
02960 
02961 void PageMarkRegions::Initialise(const DocRect& page, INT32 bleed)
02962 {
02963     // ok, we've been given a page rectangle, lets build our regions
02964     INT32 blox,bloy,bhix,bhiy;
02965     
02966     // calculate the bleed bbox
02967     blox = page.lo.x-bleed;
02968     bloy = page.lo.y-bleed;
02969     bhix = page.hi.x+bleed;
02970     bhiy = page.hi.y+bleed;
02971 
02972     INT32 hi = CROPAREA_SIZE;
02973     INT32 spc = CROPAREA_SIZE/4;
02974     INT32 slenx = (page.hi.x-page.lo.x-4*spc)/10;
02975     INT32 sleny = (page.hi.y-page.lo.y-4*spc)/10;
02976     INT32 wlenx = 8*slenx;
02977     INT32 wleny = 8*sleny;
02978     INT32 cx=(page.lo.x+page.hi.x)>>1;
02979     INT32 cy=(page.lo.y+page.hi.y)>>1;
02980     
02981     // top left corner
02982     Region[0].Pos = DocRect(blox-hi, bhiy, blox, bhiy+hi);
02983 
02984     // 3 along top edge 
02985     Region[1].Pos = DocRect(page.lo.x+spc, bhiy, page.lo.x+spc+slenx, bhiy+hi);
02986     Region[2].Pos = DocRect(cx-(wlenx>>1), bhiy, cx+(wlenx>>1), bhiy+hi);
02987     Region[3].Pos = DocRect(page.hi.x-spc-slenx, bhiy, page.hi.x-spc, bhiy+hi);
02988 
02989     // top right corner
02990     Region[4].Pos = DocRect(bhix, bhiy, bhix+hi, bhiy+hi);
02991 
02992     // 3 down right edge
02993     Region[5].Pos = DocRect(bhix, page.hi.y-spc-sleny, bhix+hi, page.hi.y-spc);
02994     Region[6].Pos = DocRect(bhix, cy-(wleny>>1), bhix+hi, cy+(wleny>>1));
02995     Region[7].Pos = DocRect(bhix, page.lo.y+spc, bhix+hi, page.lo.y+spc+sleny);
02996 
02997     // bottom right corner
02998     Region[8].Pos = DocRect(bhix, bloy-hi, bhix+hi, bloy);
02999 
03000     // 3 along bottom edge
03001     Region[9].Pos  = DocRect(page.hi.x-spc-slenx, bloy-hi, page.hi.x-spc, bloy);
03002     Region[10].Pos = DocRect(cx-(wlenx>>1), bloy-hi, cx+(wlenx>>1), bloy);
03003     Region[11].Pos = DocRect(page.lo.x+spc, bloy-hi, page.lo.x+spc+slenx, bloy);
03004 
03005     // bottom left corner
03006     Region[12].Pos = DocRect(blox-hi, bloy-hi, blox, bloy);
03007 
03008     // 3 up left edge
03009     Region[13].Pos = DocRect(blox-hi, page.lo.y+spc, blox, page.lo.y+spc+sleny);
03010     Region[14].Pos = DocRect(blox-hi, cy-(wleny>>1), blox, cy+(wleny>>1));
03011     Region[15].Pos = DocRect(blox-hi, page.hi.y-spc-sleny, blox, page.hi.y-spc);
03012 
03013     for (INT32 i=0; i<16; i++)
03014         Region[i].Valid=Region[i].OrientX=TRUE;
03015 
03016     Region[5].OrientX = FALSE;
03017     Region[6].OrientX = FALSE;
03018     Region[7].OrientX = FALSE;
03019     Region[13].OrientX = FALSE;
03020     Region[14].OrientX = FALSE;
03021     Region[15].OrientX = FALSE;
03022 }
03023 
03024 
03025 
03026 void PageMarkRegions::HideLeft()
03027 {
03028     Region[0].Valid=FALSE;
03029     Region[12].Valid=FALSE;
03030     Region[13].Valid=FALSE;
03031     Region[14].Valid=FALSE;
03032     Region[15].Valid=FALSE;
03033 }
03034 
03035 void PageMarkRegions::HideRight()
03036 {
03037     Region[4].Valid=FALSE;
03038     Region[5].Valid=FALSE;
03039     Region[6].Valid=FALSE;
03040     Region[7].Valid=FALSE;
03041     Region[8].Valid=FALSE;
03042 }
03043 
03044 void PageMarkRegions::HideTop()
03045 {
03046     Region[0].Valid=FALSE;
03047     Region[1].Valid=FALSE;
03048     Region[2].Valid=FALSE;
03049     Region[3].Valid=FALSE;
03050     Region[4].Valid=FALSE;
03051 }
03052 
03053 void PageMarkRegions::HideBottom()
03054 {
03055     Region[9].Valid=FALSE;
03056     Region[10].Valid=FALSE;
03057     Region[11].Valid=FALSE;
03058     Region[12].Valid=FALSE;
03059     Region[13].Valid=FALSE;
03060 }
03061 
03062 void PageMarkRegions::ShowLeft()
03063 {
03064     Region[0].Valid=TRUE;
03065     Region[12].Valid=TRUE;
03066     Region[13].Valid=TRUE;
03067     Region[14].Valid=TRUE;
03068     Region[15].Valid=TRUE;
03069 }
03070 
03071 void PageMarkRegions::ShowRight()
03072 {
03073     Region[4].Valid=TRUE;
03074     Region[5].Valid=TRUE;
03075     Region[6].Valid=TRUE;
03076     Region[7].Valid=TRUE;
03077     Region[8].Valid=TRUE;
03078 }
03079 
03080 void PageMarkRegions::ShowTop()
03081 {
03082     Region[0].Valid=TRUE;
03083     Region[1].Valid=TRUE;
03084     Region[2].Valid=TRUE;
03085     Region[3].Valid=TRUE;
03086     Region[4].Valid=TRUE;
03087 }
03088 
03089 void PageMarkRegions::ShowBottom()
03090 {
03091     Region[9].Valid=TRUE;
03092     Region[10].Valid=TRUE;
03093     Region[11].Valid=TRUE;
03094     Region[12].Valid=TRUE;
03095     Region[13].Valid=TRUE;
03096 }
03097 
03098 
03099 
03100 
03101 
03102 
03103 
03104 /*******************************************************************************
03105 >   MarkPosType::MarkPosType()
03106 *******************************************************************************/
03107 
03108 MarkPosType::MarkPosType()
03109 {
03110     pMarkItem=NULL;
03111     rotate=FALSE;
03112 }
03113 
03114 
03115 /*******************************************************************************
03116 >   MarkList::MarkList()
03117 *******************************************************************************/
03118 
03119 MarkList::MarkList()
03120 {
03121     count=size.x=size.y=0;
03122 }
03123 
03124 
03125 
03126 /*******************************************************************************
03127 >   MarkFormatRegion::MarkFormatRegion()
03128 *******************************************************************************/
03129 
03130 MarkFormatRegion::MarkFormatRegion()
03131 {
03132     Init();
03133 }
03134 
03135 MarkFormatRegion::MarkFormatRegion(const DocRect &Position)
03136 {
03137     Init();
03138     SetPosition(Position);
03139 }
03140 
03141 MarkFormatRegion::~MarkFormatRegion()
03142 {
03143     Empty();
03144 }
03145 
03146 void MarkFormatRegion::Init()
03147 {
03148     OrientX=TRUE;
03149     MkCx = MkCy = 0;
03150     BLeft = BCentre = BRight = NULL;
03151     MLeft = MCentre = MRight = NULL;
03152     TLeft = TCentre = TRight = NULL;
03153     OnRenderFlipX=FALSE;
03154 }
03155 
03156 void MarkFormatRegion::Empty()
03157 {
03158     if (BLeft)      delete BLeft;
03159     if (BCentre)    delete BCentre;
03160     if (BRight)     delete BRight;
03161 
03162     if (MLeft)      delete MLeft;
03163     if (MCentre)    delete MCentre;
03164     if (MRight)     delete MRight;
03165 
03166     if (TLeft)      delete TLeft;
03167     if (TCentre)    delete TCentre;
03168     if (TRight)     delete TRight;
03169 
03170     BLeft = BCentre = BRight = NULL;
03171     MLeft = MCentre = MRight = NULL;
03172     TLeft = TCentre = TRight = NULL;
03173 }
03174 
03175 
03176 void MarkFormatRegion::SetPosition(const DocRect &Position)
03177 {
03178     TheBounds = Position;
03179     MkCx = (TheBounds.lo.x + TheBounds.hi.x)>>1;
03180     MkCy = (TheBounds.lo.y + TheBounds.hi.y)>>1;
03181 }
03182 
03183 
03184 void MarkFormatRegion::SetOrientation(BOOL orientX)
03185 {
03186     OrientX=orientX;
03187 }
03188 
03189 void MarkFormatRegion::SetFlipRender(BOOL flip)
03190 {
03191     OnRenderFlipX=flip;
03192 }
03193 
03194 /***********************************************************************************************
03195 
03196 >   virtual BOOL MarkFormatRegion::AddMark(PrintMarkItem *pMark, MarkFormat *pForm)
03197 
03198     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
03199     Created:    10/08/96
03200     Inputs:     pMark = a print mark item pointer
03201                 pForm = a mark format object pointer
03202     Purpose:    
03203 
03204 ***********************************************************************************************/
03205 
03206 BOOL MarkFormatRegion::AddMark(PrintMarkItem *pMark, MarkFormat *pForm)
03207 {
03208     if (!pMark || !pForm)
03209         return FALSE;
03210     
03211     BOOL ok=TRUE;
03212 
03213     INT32 w = pMark->GetWidth();
03214     INT32 h = pMark->GetHeight();
03215     BOOL rt;
03216 
03217     rt = (( OrientX && pMark->GetOrient()==MO_Vertical) ||
03218           (!OrientX && pMark->GetOrient()==MO_Horizontal) );
03219 
03220     if (rt)
03221     {
03222         INT32 Tmp=w;    w=h; h=Tmp;
03223     }
03224 
03225     if (pForm->Left)
03226     {
03227         if (pForm->Top)
03228         {
03229             DocCoord anchor = DocCoord(TheBounds.lo.x,TheBounds.hi.y); 
03230             ok = MakeMark(pMark, anchor, FALSE, FALSE, TRUE, FALSE, 0, h, rt, &TLeft);
03231         }
03232         
03233         if (pForm->Middle)
03234         {
03235             DocCoord anchor = DocCoord(TheBounds.lo.x,MkCy);
03236             ok = MakeMark(pMark, anchor, FALSE, TRUE, TRUE, TRUE, 0, h>>1, rt, &MLeft);     
03237         }
03238         
03239         if (pForm->Bottom)
03240         {
03241             DocCoord anchor = DocCoord(TheBounds.lo.x,TheBounds.lo.y);
03242             ok = MakeMark(pMark, anchor, FALSE, FALSE, TRUE, TRUE, 0, 0, rt, &BLeft);
03243         }
03244     }
03245 
03246     if (pForm->Centre)
03247     {
03248         if (pForm->Top)
03249         {
03250             DocCoord anchor = DocCoord(MkCx,TheBounds.hi.y); 
03251             ok = MakeMark(pMark, anchor, TRUE, FALSE, TRUE, FALSE, w>>1, h, rt, &TCentre);
03252         }
03253         
03254         if (pForm->Middle)
03255         {
03256             DocCoord anchor = DocCoord(MkCx,MkCy);
03257             ok = MakeMark(pMark, anchor, TRUE, TRUE, TRUE, TRUE, w>>1, h>>1, rt, &MCentre);     
03258         }
03259         
03260         if (pForm->Bottom)
03261         {
03262             DocCoord anchor = DocCoord(MkCx,TheBounds.lo.y);
03263             ok = MakeMark(pMark, anchor, TRUE, FALSE, TRUE, TRUE, w>>1, 0, rt, &BCentre);
03264         }
03265     }
03266 
03267     if (pForm->Right)
03268     {
03269         if (pForm->Top)
03270         {
03271             DocCoord anchor = DocCoord(TheBounds.hi.x,TheBounds.hi.y); 
03272             ok = MakeMark(pMark, anchor, FALSE, FALSE, FALSE, FALSE, w, h, rt, &TRight);
03273         }
03274         
03275         if (pForm->Middle)
03276         {
03277             DocCoord anchor = DocCoord(TheBounds.hi.x,MkCy);
03278             ok = MakeMark(pMark, anchor, FALSE, TRUE, FALSE, TRUE, w, h>>1, rt, &MRight);       
03279         }
03280         
03281         if (pForm->Bottom)
03282         {
03283             DocCoord anchor = DocCoord(TheBounds.hi.x,TheBounds.lo.y);
03284             ok = MakeMark(pMark, anchor, FALSE, FALSE, FALSE, TRUE, w, 0, rt, &BRight);
03285         }
03286     }
03287 
03288     return ok;
03289 }
03290 
03291 
03292 /*******************************************************************************
03293 
03294 >   virtual BOOL MarkFormatRegion::MakeMark(PseudoMark *pMark, 
03295                                             DocCoord Anchor,
03296                                             BOOL cx,
03297                                             BOOL cy,
03298                                             BOOL posx,
03299                                             BOOL posy,
03300                                             INT32 shiftx,
03301                                             INT32 shifty,
03302                                             BOOL rotate,
03303                                             MarkList **pMarkList)
03304 
03305     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
03306     Created:    10/08/96
03307     Inputs:     pMark   - a pointer to a mark to add to the formatting region
03308                 Anchor  - An origin point to begin formatting to
03309                 cx      - TRUE then centre all added marks in X
03310                 cy      - TRUE then centre all added marks in Y
03311                 posx    - TRUE then increment anchor x pos by mark width else decrement
03312                 posy    - TRUE then increment anchor y pos by mark height else decrement
03313                 shiftx  - An amount to shift the positioned mark by in x.
03314                 shifty  - An amount to shift the positioned mark by in y.
03315     Outputs:    pMarkList, a pointer to a new mark list if on entry this pointer
03316                            points to a NULL value. Otherwise the list pointed to
03317                            on entry will contain another item and its count will
03318                            have increased by 1.
03319     Returns:    TRUE    - if a mark formating object was added to pMarkList.
03320                 FALSE   - then you've attempted to add more than MAXREGIONMARKS
03321                           to pMarkList.
03322     Purpose:    Invented to add a mark to a marklist. This function really is
03323                 a helper to AddMark and should not be used by itself unless you
03324                 really want to. Imagine an arbitrarily shaped box with 9 format
03325                 positions ie combinations of permutations of L,C,R,T,M,B. A
03326                 Mark list will keep track of marks added to any of these regions.
03327                 For instance, if you add a mark to TL ie top left, and then add
03328                 another mark to this region, the TLeft array in the constructed
03329                 marks list will contain two entries, holding the x,y positions
03330                 of where the marks should be positioned. Marks will be added ie
03331                 grow from the edges of the format region dependent on its orientation
03332                 ie
03333                 Vertical region orientation
03334                     bottom edge - marks grow bottom to top    left edge aligned at left
03335                     middle edge - marks grow centrally        right edge aligned at right
03336                     top edge    - marks grow top to bottom    central align in centre
03337                 Horizontal region orientation
03338                     left edge   - marks grow left to right
03339                     centre edge - marks grow centrally
03340                     right edge  - marks grow right to left
03341 
03342                 Anyway, the whole job is one of positioning child boxes in a parent
03343                 box region, where more than one child can occupy the same space.
03344 
03345 
03346 *******************************************************************************/
03347 
03348 BOOL MarkFormatRegion::MakeMark(PrintMarkItem *pMark, 
03349                                 DocCoord Anchor,
03350                                 BOOL cx,
03351                                 BOOL cy,
03352                                 BOOL posx,
03353                                 BOOL posy,
03354                                 INT32 shiftx,
03355                                 INT32 shifty,
03356                                 BOOL rotate,
03357                                 MarkList **pMarkList)
03358 {
03359     MarkList *pItem = (*pMarkList);
03360 
03361     if (pItem==NULL)
03362     {
03363         pItem = new MarkList;
03364         if (pItem==NULL)
03365             return FALSE;
03366         
03367         pItem->curpos = Anchor;
03368     }
03369 
03370     INT32 width = pMark->GetWidth();
03371     INT32 height = pMark->GetHeight();
03372     if (rotate)
03373     {
03374         INT32 Tmp=width; width=height; height=Tmp;
03375     }
03376 
03377     if (pItem->count<MAXREGIONMARKS)
03378     {
03379         pItem->MarkPos[pItem->count].pMarkItem = pMark;
03380         pItem->MarkPos[pItem->count].dim = DocCoord(width,height);
03381         pItem->MarkPos[pItem->count].rotate = rotate;
03382         pItem->count++;
03383         
03384         if (OrientX)
03385         {
03386             pItem->MarkPos[pItem->count-1].pos.y = pItem->curpos.y - shifty;
03387             if (cx)
03388             {
03389                 pItem->size.x += width;
03390                 INT32 x=0;
03391                 for (INT32 i=0; i<pItem->count; i++)
03392                 {
03393                     pItem->MarkPos[i].pos.x = MkCx - ((pItem->size.x)>>1) + x;
03394                     x+=pItem->MarkPos[i].dim.x;
03395                 }
03396             }
03397             else
03398             {
03399                 pItem->MarkPos[pItem->count-1].pos.x = pItem->curpos.x - shiftx;
03400                 pItem->curpos.x += ((posx) ? (+width) : (-width));
03401             }   
03402         }
03403         else
03404         {
03405             pItem->MarkPos[pItem->count-1].pos.x = pItem->curpos.x - shiftx;
03406             if (cy)
03407             {
03408                 pItem->size.y += height;
03409                 INT32 y=0;
03410                 for (INT32 i=0; i<pItem->count; i++)
03411                 {
03412                     pItem->MarkPos[i].pos.y = MkCy - ((pItem->size.y)>>1) + y;
03413                     y+=pItem->MarkPos[i].dim.y;
03414                 }
03415             }
03416             else
03417             {
03418                 pItem->MarkPos[pItem->count-1].pos.y = pItem->curpos.y - shifty;
03419                 pItem->curpos.y += ((posy) ? (+height) : (-height));
03420             }   
03421         }
03422     }
03423 
03424     if (*pMarkList==NULL)
03425         *pMarkList=pItem;
03426 
03427     return TRUE;
03428 }
03429 
03430 
03431 /*******************************************************************************
03432 void MarkFormatRegion::Render(RenderRegion *pRRegion, const Matrix& Transform)
03433 *******************************************************************************/
03434 
03435 void MarkFormatRegion::Render(RenderRegion *pRRegion, const Matrix& Transform)
03436 {
03437     if (BLeft)      Render(pRRegion, BLeft, Transform);
03438     if (BCentre)    Render(pRRegion, BCentre, Transform);
03439     if (BRight)     Render(pRRegion, BRight, Transform);
03440     if (MLeft)      Render(pRRegion, MLeft, Transform);
03441     if (MCentre)    Render(pRRegion, MCentre, Transform);
03442     if (MRight)     Render(pRRegion, MRight, Transform);
03443     if (TLeft)      Render(pRRegion, TLeft, Transform);
03444     if (TCentre)    Render(pRRegion, TCentre, Transform);
03445     if (TRight)     Render(pRRegion, TRight, Transform);
03446 }
03447 
03448 
03449 /*******************************************************************************
03450 void MarkFormatRegion::Render(RenderRegion *pRRegion, MarkList *pMarkLst)
03451 *******************************************************************************/
03452 
03453 void MarkFormatRegion::Render(RenderRegion *pRRegion, MarkList *pMarkLst, const Matrix& OuterTransform)
03454 {
03455     PrintMarkItem* pPMI;
03456     DocRect bounds;
03457     DocCoord pos,pos1;
03458     Trans2DMatrix Trans2DMat;
03459 
03460     // Calculate the inverse of the render matrix, this allows us to render
03461     // through a scaling render region and prevent our marks being scaled.
03462     Matrix ViewTrans = pRRegion->GetMatrix();
03463     ViewTrans = ViewTrans.Inverse();
03464 
03465     Matrix Transform;
03466     Matrix ITransform;
03467     Matrix Identity;
03468 
03469     for (INT32 i=0; i<pMarkLst->count; i++)
03470     {
03471         pPMI = pMarkLst->MarkPos[i].pMarkItem;
03472         pos = pPMI->GetOrigin();
03473         // Initialise to the identity
03474         Transform = Identity;
03475         // translation mark to origin
03476         Transform.SetTranslation(-pos.x, -pos.y);
03477 
03478         // spin the mark around if necessary
03479 
03480         INT32 w = pPMI->GetWidth();
03481         INT32 h = pPMI->GetHeight();
03482         if (pMarkLst->MarkPos[i].rotate)
03483         {
03484             Transform *= Matrix((ANGLE)270);
03485             Transform *= Matrix(0,w);
03486         }
03487 
03488         // Take into account any flipping
03489         if (OnRenderFlipX)
03490         {
03491             if (pMarkLst->MarkPos[i].rotate)
03492                 Transform *= Matrix(FIXED16(-1), FIXED16(0), FIXED16(0), FIXED16(1), h, 0);
03493             else
03494                 Transform *= Matrix(FIXED16(-1), FIXED16(0), FIXED16(0), FIXED16(1), w, 0);
03495         }
03496         
03497         // Now translate into the final position
03498         Transform = Transform * Matrix(pMarkLst->MarkPos[i].pos);
03499         // Finally apply the outer transform before rendering
03500         Transform = Transform * OuterTransform;
03501         // ok now we need to compensate for the render region matrix
03502         Transform = Transform * ViewTrans;
03503         // calculate the inverse for transforming back again.
03504         ITransform = Transform.Inverse();
03505 
03506         // Apply the transform to the mark, we need to make sure line widths get scaled
03507         Trans2DMat.SetTransform(Transform);
03508         Trans2DMat.TransLines = TRUE;
03509         pPMI->GetMarkGlyph()->Transform(Trans2DMat);
03510 
03511         // once transformed lets render it.
03512         RenderMark(pRRegion, pPMI);
03513 
03514         // now transform back again (without loss of accuracy ha!)
03515         Trans2DMat.SetTransform(ITransform);
03516         Trans2DMat.TransLines = TRUE;
03517         pPMI->GetMarkGlyph()->Transform(Trans2DMat);
03518     }
03519 }
03520 
03521 
03522 
03523 
03524 /***********************************************************************************************
03525 
03526 >   void MarkFormatRegion::RenderMark(RenderRegion* pRRegion, PrintMarkItem *pMark)
03527 
03528     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
03529     Created:    10/08/96
03530     Inputs:     pRRegion = pointer to a render region
03531                 pMark    = pointer to a print mark item
03532     Purpose:    Render the mark if it intersects the clip rect in the render region.
03533 
03534 ***********************************************************************************************/
03535 
03536 void MarkFormatRegion::RenderMark(RenderRegion* pRRegion, PrintMarkItem *pMark)
03537 {
03538     // Get the root node and render the entire subtree
03539     Node* pFirstNode = pMark->GetMarkGlyph();
03540     if (pFirstNode!=NULL)
03541         pRRegion->RenderTree(pFirstNode, FALSE, TRUE);      
03542 }

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