blobs.cpp

Go to the documentation of this file.
00001 // $Id: blobs.cpp 1601 2006-07-29 16:26: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 // Provides a class to help manage the various types of blobs available in Camelot
00099 
00100 /*
00101 */
00102 
00103 #include "camtypes.h"
00104 #include "blobs.h"
00105 //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 //#include "range.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 //#include "ink.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 #include "osrndrgn.h"
00111 //#include "docvmsg.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 //#include "tool.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00114 
00115 // Declare the source version number
00116 DECLARE_SOURCE("$Revision: 1601 $");
00117 
00118 //Give my name in memory dumps
00119 CC_IMPLEMENT_MEMDUMP(BlobManager, MessageHandler)
00120 
00121 // This will get Camelot to display the filename and linenumber of any memory allocations
00122 // that are not released at program exit
00123 // Declare smart memory handling in Debug builds
00124 #define new CAM_DEBUG_NEW
00125 
00126 //static BOOL CurrentCaretState = FALSE;
00127 
00128 
00129 /********************************************************************************************
00130 
00131 >   BlobStyle::BlobStyle()
00132 
00133     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00134     Created:    23/6/94
00135     Purpose:    Default constructor for the blob style which sets all the types of blob to
00136                 FALSE.
00137 
00138 ********************************************************************************************/
00139 
00140 BlobStyle::BlobStyle()
00141 {
00142     // Set all the blobs to false
00143     Object = Artistic = Fill = Tiny = Pen = ToolObject = Effect = FALSE;
00144 }
00145 
00146 
00147 
00148 /********************************************************************************************
00149 
00150 >   BlobStyle::BlobStyle(   BOOL BObject, BOOL BArtistic, BOOL BFill,
00151                             BOOL BTiny, BOOL BPen, BOOL BToolObject, BOOL BEffect )
00152     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00153     Created:    23/6/94
00154     Inputs:     BObject - TRUE if you want Object blobs in the Blob Style
00155                 BArtistic - TRUE if you want Artistic blobs in the Blob Style
00156                 BFill - TRUE if you want Fill blobs in the Blob Style
00157                 BTiny - TRUE if you want Tiny blobs in the Blob Style
00158                 BPen - TRUE if Pen blobs are wanted
00159                 BToolObject - TRUE if tool-specific object blobs are wanted.
00160                 BEffect - TRUE if effect attributes blobs are wanted
00161                 All these params default to FALSE.
00162     Purpose:    Constructor for the blob style flags that lets you specify which of the blob
00163                 types you want to use.
00164 
00165 ********************************************************************************************/
00166 
00167 BlobStyle::BlobStyle(   BOOL BObject, BOOL BArtistic, BOOL BFill,
00168                         BOOL BTiny, BOOL BPen, BOOL BToolObject, BOOL BEffect )
00169 {
00170     // Set the blobs that are required
00171     Object = BObject;
00172     Artistic = BArtistic;
00173     Fill = BFill;
00174     Tiny = BTiny;
00175     Pen = BPen;
00176     ToolObject = BToolObject;
00177     Effect = BEffect;
00178 }
00179 
00180 
00181 
00182 
00183 
00184 /********************************************************************************************
00185 
00186 >   BlobManager::BlobManager()
00187 
00188     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00189     Created:    23/6/94
00190     Purpose:    Default constructor for the blob manager, marks all the blobs as off
00191 
00192 ********************************************************************************************/
00193 
00194 BlobManager::BlobManager() : MessageHandler(CC_RUNTIME_CLASS(MessageHandler), TRUE)
00195 {
00196     // There are no blobs visible when we start
00197     IsFillBlob = FALSE;
00198     IsObjectBlob = FALSE;
00199     IsArtisticBlob = FALSE;
00200     IsTinyBlob = FALSE;
00201     IsPenBlob = FALSE;
00202     IsToolObjectBlob = FALSE;
00203     IsEffectBlob = FALSE;
00204 
00205     // Blob rendering is switched on by default
00206     DrawBlobsAtAll = TRUE;
00207 
00208     RemovingBlobs = FALSE;
00209 
00210     bToolBlobsAreOff = FALSE;
00211 }
00212 
00213 /********************************************************************************************
00214 
00215 >   void BlobManager::ToolInterest(BlobStyle Blobs)
00216 
00217     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00218     Created:    16/6/94
00219     Inputs:     -
00220     Outputs:    -
00221     Returns:    -
00222     Purpose:    
00223     Errors:     -
00224     SeeAlso:    BlobStyle
00225 
00226 ********************************************************************************************/
00227 
00228 void BlobManager::ToolInterest(BlobStyle Blobs)
00229 {
00230     BlobStyle BlobsToRemove;
00231 
00232     // Find all the blobs that are NOT selected
00233     BlobsToRemove.Object    = !Blobs.Object;
00234     BlobsToRemove.Artistic  = !Blobs.Artistic;
00235     BlobsToRemove.Fill      = !Blobs.Fill;
00236     BlobsToRemove.Tiny      = !Blobs.Tiny;
00237     BlobsToRemove.Pen       = !Blobs.Pen;
00238     BlobsToRemove.ToolObject= !Blobs.ToolObject;
00239     BlobsToRemove.Effect    = !Blobs.Effect;
00240 
00241     // and remove them
00242     RemoveInterest(BlobsToRemove);
00243 
00244     // Add the selected blobs
00245     AddInterest(Blobs);
00246 
00247 /*
00248     // Do we need to render Object Blobs
00249     BOOL DrawObject = FALSE;
00250     if ((Blobs.Object && !IsObjectBlob) || (!Blobs.Object && IsObjectBlob))
00251         DrawObject = TRUE;
00252 
00253     // Do we need to render Artistic Blobs
00254     BOOL DrawArtistic = FALSE;
00255     if ((Blobs.Artistic && !IsArtisticBlob) || (!Blobs.Artistic && IsArtisticBlob))
00256         DrawArtistic = TRUE;
00257 
00258     // Do we need to render Fill Blobs
00259     BOOL DrawFill = FALSE;
00260     if ((Blobs.Fill && !IsFillBlob) || (!Blobs.Fill && IsFillBlob))
00261         DrawFill = TRUE;
00262 
00263     // Do we need to render Tiny Blobs
00264     BOOL DrawTiny = FALSE;
00265     if ((Blobs.Tiny && !IsTinyBlob) || (!Blobs.Tiny && IsTinyBlob))
00266         DrawTiny = TRUE;
00267 
00268     // Do we need to render Tiny Blobs
00269     BOOL DrawPen = FALSE;
00270     if ((Blobs.Pen && !IsPenBlob) || (!Blobs.Pen && IsPenBlob))
00271         DrawPen = TRUE;
00272 
00273 
00274     // Find out about the selection
00275     SelRange* Selected = GetApplication()->FindSelection();
00276     Node* pNode = Selected->FindFirst();
00277 
00278     // was there a selection to render?
00279     if (pNode!=NULL && DrawBlobsAtAll)
00280     {
00281         // Find the parent spread
00282         Spread* pSpread = pNode->FindParentSpread();
00283 
00284         // Render what we need to
00285         RenderRegion* pRegion = DocView::RenderOnTop(NULL, pSpread, ClippedEOR);
00286         while (pRegion)
00287         {
00288             // Find the first selected object in the tree;
00289             Node* pNode = Selected->FindFirst();
00290             while(pNode)
00291             {
00292                 // Render only those blobs that are changing state (ie those appearing or disappearing)
00293                 RenderSpecificBlobs((NodeRenderable*)pNode, pRegion, DrawObject, DrawArtistic,
00294                                     DrawFill, DrawTiny, DrawPen);
00295 
00296                 // Find the next selected node to render
00297                 pNode = Selected->FindNext(pNode);
00298             }
00299 
00300             // Go find the next region
00301             pRegion = DocView::GetNextOnTop(NULL);
00302         }
00303     }
00304 
00305     // Now we have to set the flags to the appropraite value
00306     IsFillBlob      = Blobs.Fill;
00307     IsArtisticBlob  = Blobs.Artistic;
00308     IsObjectBlob    = Blobs.Object;
00309     IsTinyBlob      = Blobs.Tiny;
00310     IsPenBlob       = Blobs.Pen;
00311 
00312     // Bodge to stop fill meshes EOR each other out.
00313     AttrFillGeometry::LastRenderedMesh = NULL;
00314 */
00315 }
00316 
00317 
00318 /********************************************************************************************
00319 
00320 >   void BlobManager::AddInterest(BlobStyle Blobs)
00321 
00322     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00323     Created:    16/6/94
00324     Inputs:     Blobs - The blobs that you which to add to the ones currently displayed
00325     Purpose:    If the blobs specified are not already displayed, then they are rendered
00326                 onto the screen. The Flags that the blob manager maintains about which
00327                 blobs are on screen and which are not are also updated
00328     SeeAlso:    BlobManager::RemoveInterest; BlobStyle
00329 
00330 ********************************************************************************************/
00331 
00332 void BlobManager::AddInterest(BlobStyle Blobs)
00333 {
00334     RemovingBlobs = FALSE;
00335 
00336     // First we have to work out which bits of the we have to add.
00337     // Do we need Object blobs to be rendered
00338     BOOL DrawObject = FALSE;
00339     if (!IsObjectBlob && Blobs.Object)
00340     {
00341         DrawObject = TRUE;
00342         IsObjectBlob = TRUE;
00343     }
00344 
00345     // Do we need Artistic blobs to be rendered
00346     BOOL DrawArtistic = FALSE;
00347     if (!IsArtisticBlob && Blobs.Artistic)
00348     {
00349         DrawArtistic = TRUE;
00350         IsArtisticBlob = TRUE;
00351     }
00352 
00353     // Do we need Fill blobs to be rendered
00354     BOOL DrawFill = FALSE;
00355     if (!IsFillBlob && Blobs.Fill)
00356     {
00357         DrawFill = TRUE;
00358         IsFillBlob = TRUE;
00359     }
00360 
00361     // Do we need Effect blobs to be rendered
00362     BOOL DrawEffect = FALSE;
00363     if (!IsEffectBlob && Blobs.Effect)
00364     {
00365         DrawEffect = TRUE;
00366         IsEffectBlob = TRUE;
00367     }
00368 
00369     // Do we need Tiny blobs to be rendered
00370     BOOL DrawTiny = FALSE;
00371     if (!IsTinyBlob && Blobs.Tiny)
00372     {
00373         DrawTiny = TRUE;
00374         IsTinyBlob = TRUE;
00375     }
00376 
00377     // Do we need Pen blobs to be rendered
00378     BOOL DrawPen = FALSE;
00379     if (!IsPenBlob && Blobs.Pen)
00380     {
00381         DrawPen = TRUE;
00382         IsPenBlob = TRUE;
00383     }
00384 
00385     // Do we need ToolObject blobs to be rendered
00386     BOOL DrawToolObject = FALSE;
00387     if (!IsToolObjectBlob && Blobs.ToolObject)
00388     {
00389         DrawToolObject = TRUE;
00390         IsToolObjectBlob = TRUE;
00391     }
00392 
00393     if (!NeedToRenderSelectionBlobs(NULL))
00394         return;
00395 
00396     RenderSpecificBlobsOnSelection( NULL, DrawObject, DrawArtistic, 
00397                                     DrawFill, DrawTiny, DrawPen, DrawToolObject, DrawEffect);
00398 
00399     // Now EOR off in all the render regions that are still rendering,
00400     // so that the Blob rendering when the region is finished, 
00401     // will put them on
00402     RenderRegionList* pRegionList = GetApplication()->GetRegionList();
00403 
00404     if (!pRegionList->IsEmpty())
00405     {
00406         // Find out which spread the selection is on
00407         SelRange* Selected = GetApplication()->FindSelection();
00408         Node* pNode = Selected->FindFirst();
00409         
00410         if (pNode)  // Is there a Selection ?
00411         {
00412             Spread* pSpread = pNode->FindParentSpread();
00413 
00414             RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();  
00415 
00416             while (pRegion)
00417             {
00418                 // Check the RenderRegion is for the same spread.
00419                 if (pRegion->GetRenderSpread() == pSpread &&
00420                     pRegion->GetRenderView()==DocView::GetSelected() &&
00421                     (pRegion->IsInkRenderStarted || pRegion->NeedsOSPaper))
00422                 {
00423                     // Render the blobs 'clipped' to this Render Region.
00424                     DocRect ClipRect = pRegion->GetRegionRect();
00425                     RenderSpecificBlobsOnSelection( &ClipRect,
00426                                                     DrawObject, DrawArtistic, DrawFill,
00427                                                     DrawTiny, DrawPen, DrawToolObject, DrawEffect );
00428                 }
00429 
00430                 // Get the Next render region
00431                 pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
00432             }
00433         }
00434     }
00435 }
00436 
00437 
00438 
00439 
00440 /********************************************************************************************
00441 
00442 >   void BlobManager::RemoveInterest(BlobStyle Blobs)
00443 
00444     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00445     Created:    16/6/94
00446     Inputs:     Blobs - The blobs that you which to remove from the ones currently displayed
00447     Purpose:    If the blobs specified are already displayed, then they are rendered
00448                 onto the screen to get rid of them (EORing!). The Flags that the blob manager
00449                 maintains about which blobs are on screen and which are not are also updated
00450     SeeAlso:    BlobManager::AddInterest; BlobStyle
00451 
00452 ********************************************************************************************/
00453 
00454 void BlobManager::RemoveInterest(BlobStyle Blobs)
00455 {
00456     RemovingBlobs = TRUE;
00457 
00458     // First we have to work out which bits of the we have to add.
00459     // Do we need Object blobs to be rendered
00460     BOOL DrawObject = FALSE;
00461     if (IsObjectBlob && Blobs.Object)
00462     {
00463         DrawObject = TRUE;
00464         IsObjectBlob = FALSE;
00465     }
00466 
00467     // Do we need Artistic blobs to be rendered
00468     BOOL DrawArtistic = FALSE;
00469     if (IsArtisticBlob && Blobs.Artistic)
00470     {
00471         DrawArtistic = TRUE;
00472         IsArtisticBlob = FALSE;
00473     }
00474 
00475     // Do we need Fill blobs to be rendered
00476     BOOL DrawFill = FALSE;
00477     if (IsFillBlob && Blobs.Fill)
00478     {
00479         DrawFill = TRUE;
00480         IsFillBlob = FALSE;
00481     }
00482 
00483     // Do we need Fill blobs to be rendered
00484     BOOL DrawEffect = FALSE;
00485     if (IsEffectBlob && Blobs.Effect)
00486     {
00487         DrawEffect = TRUE;
00488         IsEffectBlob = FALSE;
00489     }
00490 
00491     // Do we need Tiny blobs to be rendered
00492     BOOL DrawTiny = FALSE;
00493     if (IsTinyBlob && Blobs.Tiny)
00494     {
00495         DrawTiny = TRUE;
00496         IsTinyBlob = FALSE;
00497     }
00498 
00499     // Do we need Pen blobs to be rendered
00500     BOOL DrawPen = FALSE;
00501     if (IsPenBlob && Blobs.Pen)
00502     {
00503         DrawPen = TRUE;
00504         IsPenBlob = FALSE;
00505     }
00506 
00507     // Do we need ToolObject blobs to be rendered
00508     BOOL DrawToolObject = FALSE;
00509     if (IsToolObjectBlob && Blobs.ToolObject)
00510     {
00511         DrawToolObject = TRUE;
00512         IsToolObjectBlob = FALSE;
00513     }
00514 
00515     if (!NeedToRenderSelectionBlobs(NULL))
00516         return;
00517 
00518     // EOR on in all the render regions that are still rendering,
00519     // so that the Blob rendering when the region is finished, 
00520     // will take them off
00521     RenderRegionList* pRegionList = GetApplication()->GetRegionList();
00522 
00523     if (!pRegionList->IsEmpty())
00524     {
00525         // Find out which spread the selection is on
00526         SelRange* Selected = GetApplication()->FindSelection();
00527         Node* pNode = Selected->FindFirst();
00528 
00529         if (pNode)  // Is there a Selection ?
00530         {
00531             Spread* pSpread = pNode->FindParentSpread();
00532 
00533             RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();  
00534 
00535             while (pRegion)
00536             {
00537                 // Check the RenderRegion is for the same spread.
00538                 if (pRegion->GetRenderSpread() == pSpread &&
00539                     pRegion->GetRenderView()==DocView::GetSelected() &&
00540                     (pRegion->IsInkRenderStarted || pRegion->NeedsOSPaper))
00541                 {
00542                     // Render the blobs 'clipped' to this Render Region.
00543                     DocRect ClipRect = pRegion->GetRegionRect();
00544                     RenderSpecificBlobsOnSelection( &ClipRect,
00545                                                     DrawObject, DrawArtistic, DrawFill,
00546                                                     DrawTiny, DrawPen, DrawToolObject, DrawEffect );
00547                 }
00548 
00549                 // Get the Next render region
00550                 pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
00551             }
00552         }
00553     }
00554 
00555     RenderSpecificBlobsOnSelection( NULL, DrawObject, DrawArtistic, 
00556                                     DrawFill, DrawTiny, DrawPen, DrawToolObject, DrawEffect);
00557 }
00558 
00559 /********************************************************************************************
00560 
00561 >   BlobStyle BlobManager::GetCurrentInterest(BOOL bIgnoreOffState = FALSE)
00562 
00563     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00564     Created:    15/8/94
00565     Inputs:     bIgnoreOffState - Flag for use by GetBlobBoundingRect functions so that
00566                 they can return correct bounds even when blob rendering is turned off
00567     Returns:    A 'BlobStyle' refecting the current blob interest
00568     Purpose:    Allows people other than the blobmanager to know what blob are currently
00569                 displayed.
00570     SeeAlso:    BlobManager::AddInterest; BlobStyle
00571 
00572 ********************************************************************************************/
00573 
00574 BlobStyle BlobManager::GetCurrentInterest(BOOL bIgnoreOffState)
00575 {
00576     // Make a default blob style with all interest off.
00577     BlobStyle CurrentBlobs;
00578 
00579     if (DrawBlobsAtAll || bIgnoreOffState)
00580     {
00581         // Update it with the current Interest
00582         CurrentBlobs.Fill       = IsFillBlob;
00583         CurrentBlobs.Effect     = IsEffectBlob;
00584         CurrentBlobs.Object     = IsObjectBlob;
00585         CurrentBlobs.Artistic   = IsArtisticBlob;
00586         CurrentBlobs.Tiny       = IsTinyBlob;
00587         CurrentBlobs.Pen        = IsPenBlob;
00588         CurrentBlobs.ToolObject = IsToolObjectBlob;
00589     }
00590 
00591     return CurrentBlobs;
00592 }
00593 
00594 /********************************************************************************************
00595 
00596 >   void BlobManager::BlobRenderingOff(BOOL Redraw)
00597 
00598     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00599     Created:    11/7/94
00600     Inputs:     Redraw - TRUE if you want the blob to be rendered before blob rendering is
00601                 turned off.
00602     Purpose:    After calling this function, any attempts to render blobs from anywhere in
00603                 Camelot will result in nothing appearing on screen. This is a dangerous
00604                 function to call if you are not sure what is going on.
00605                 Normally you should use this function if you are about to do something
00606                 that will involve the selection state becoming inconsistent with the
00607                 blobs on screen and you specifically do not want lots of blob rendering
00608                 going on until you have finished.
00609                 Here is an example way of using it
00610                 MonoOn
00611                     // Get rid of the blobs from the screen
00612                     BlobMgr->BlobRenderingOff(TRUE);
00613 
00614                     // Party on the selection and change lots of things
00615                     ...
00616 
00617                     // Invalidate the region of the blobs
00618                     ...
00619 
00620                     // Switch the blob manager back on again
00621                     // but leave the rendering of the blobs to the normal OnDraw loop
00622                     BlobMgr->BlobRenderingOn(FALSE)
00623                 MonoOff
00624     SeeAlso:    BlobManager::BlobRenderingOn()
00625 
00626 ********************************************************************************************/
00627 
00628 void BlobManager::BlobRenderingOff(BOOL Redraw)
00629 {
00630     RemovingBlobs = TRUE;
00631 
00632     if (Redraw && NeedToRenderSelectionBlobs(NULL))
00633     {
00634         // EOR on in all the render regions that are still rendering,
00635         // so that the Blob rendering when the region is finished, 
00636         // will take them off
00637         RenderRegionList* pRegionList = GetApplication()->GetRegionList();
00638 
00639         if (!pRegionList->IsEmpty())
00640         {
00641             // Find out which spread the selection is on
00642             SelRange* Selected = GetApplication()->FindSelection();
00643             Node* pNode = Selected->FindFirst();
00644 
00645             if (pNode)  // Is there a Selection ?
00646             {
00647                 Spread* pSpread = pNode->FindParentSpread();
00648 
00649                 RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();  
00650 
00651                 while (pRegion)
00652                 {
00653                     // Check the RenderRegion is for the same spread.
00654                     if (pRegion->GetRenderSpread() == pSpread &&
00655                         pRegion->GetRenderView()==DocView::GetSelected() &&
00656                         (pRegion->IsInkRenderStarted || pRegion->NeedsOSPaper))
00657                     {
00658                         // Render the blobs 'clipped' to this Render Region.
00659                         DocRect ClipRect = pRegion->GetRegionRect();
00660                         RenderRequiredBlobsOnSelection(&ClipRect);
00661                     }
00662 
00663                     // Get the Next render region
00664                     pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
00665                 }
00666             }
00667         }
00668 
00669         RenderRequiredBlobsOnSelection(NULL);
00670     }
00671 
00672     // Mark blob rendering to be off
00673     DrawBlobsAtAll = FALSE;
00674 
00675     // Bodge to stop fill meshes EOR each other out.
00676     AttrFillGeometry::LastRenderedMesh = NULL;
00677 }
00678 
00679 
00680 /********************************************************************************************
00681 
00682 >   void BlobManager::BlobRenderingOn(BOOL Redraw)
00683 
00684     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00685     Created:    11/7/94
00686     Inputs:     Redraw - TRUE if you want the blobs to be rendered before blob rendering is
00687                 turned on.
00688     Purpose:    If blob rendering has been turned off ( by calling BlobRenderinOff() )
00689                 then this function will re-enable it so that rendering can carry on
00690                 like normal. Ideally this should be called not very long after calling
00691                 BlobRenderingOff().
00692     SeeAlso:    BlobManager::BlobRenderingOn()
00693 
00694 ********************************************************************************************/
00695 
00696 void BlobManager::BlobRenderingOn(BOOL Redraw)
00697 {
00698     RemovingBlobs = FALSE;
00699 
00700     if (Redraw && NeedToRenderSelectionBlobs(NULL))
00701     {
00702         RenderRequiredBlobsOnSelection(NULL);
00703 
00704         // Now EOR off in all the render regions that are still rendering,
00705         // so that the Blob rendering when the region is finished, 
00706         // will put them on
00707         RenderRegionList* pRegionList = GetApplication()->GetRegionList();
00708 
00709         if (!pRegionList->IsEmpty())
00710         {
00711             // Find out which spread the selection is on
00712             SelRange* Selected = GetApplication()->FindSelection();
00713             Node* pNode = Selected->FindFirst();
00714 
00715             if (pNode)  // Is there a Selection ?
00716             {
00717                 Spread* pSpread = pNode->FindParentSpread();
00718 
00719                 RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();  
00720 
00721                 while (pRegion)
00722                 {
00723                     // Check the RenderRegion is for the same spread.
00724                     if (pRegion->GetRenderSpread() == pSpread &&
00725                         pRegion->GetRenderView()==DocView::GetSelected() &&
00726                         (pRegion->IsInkRenderStarted || pRegion->NeedsOSPaper))
00727                     {
00728                         // Render the blobs 'clipped' to this Render Region.
00729                         DocRect ClipRect = pRegion->GetRegionRect();
00730                         RenderRequiredBlobsOnSelection(&ClipRect);
00731                     }
00732 
00733                     // Get the Next render region
00734                     pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
00735                 }
00736             }
00737         }
00738     }
00739 
00740     // Mark blob rendering to be on
00741     DrawBlobsAtAll = TRUE;
00742 
00743     // Bodge to stop fill meshes EOR each other out.
00744     AttrFillGeometry::LastRenderedMesh = NULL;
00745 }
00746 
00747 
00748 
00749 
00750 /********************************************************************************************
00751 
00752 >   INT32 BlobManager::GetBlobSize()
00753 
00754     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00755     Created:    27/6/94
00756     Returns:    INT32 - The size (in DocCoords) of a blob.
00757     Purpose:    This function allows you to find out how wide a blob should be.
00758 
00759 ********************************************************************************************/
00760 
00761 INT32 BlobManager::GetBlobSize()
00762 {
00763     // To do this, we need to find out how big a blobs rect is
00764     DocRect Rect;
00765     GetBlobRect(DocCoord(0,0), &Rect);
00766 
00767     // return the width of the resulting rect
00768     return Rect.Width();
00769 }
00770 
00771 
00772 
00773 /********************************************************************************************
00774 
00775 >   void BlobManager::GetBlobRect(DocCoord& Centre, DocRect* Rect)
00776 
00777     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00778     Created:    27/6/94
00779     Inputs:     Centre - The coordinate to centre the blob on
00780                 MFill = Whether we should force this routine to use multi-stage fill routine
00781     Outputs:    Rect - The rect in DocCoords of the blobs
00782     Purpose:    Finds the rectangle of a blob that surrounds a given coord. This is to
00783                 replace the rather long winded method that had to be employed before. If
00784                 there is no selected document it will leave the rect unchanged.
00785 
00786                 Karim 22/05/2000 - modified this method to take a BlobType param. Note that
00787                 you *cannot* make use of this new param until the MFill param is removed and
00788                 all current instances of GetBlobRect() updated. The new param is currently
00789                 only checked against my ClipView blob type.
00790 
00791 ********************************************************************************************/
00792 
00793 void BlobManager::GetBlobRect( const DocCoord &Centre, DocRect *Rect, BOOL MFill /*= FALSE*/,
00794                                                                     BlobType eBlobType)
00795 {
00796     // We will be needing a view to do this
00797     DocView* pDocView = DocView::GetSelected();
00798 
00799     // Find out how big a rect is these days, if we have a view
00800     if (pDocView!=NULL)
00801     {
00802         switch (eBlobType)
00803         {
00804         case BT_CLIPVIEW:
00805             OSRenderRegion::GetBlobRect(pDocView->GetViewScale(), Centre, BT_CLIPVIEW, Rect);
00806             break;
00807 
00808         default:
00809             if (!MFill)
00810             {
00811                 OSRenderRegion::GetBlobRect(pDocView->GetViewScale(), Centre, BT_SELECTEDLARGEST, Rect);
00812             }
00813             else
00814             {
00815                 OSRenderRegion::GetBlobRect(pDocView->GetViewScale(), Centre, BT_MSTAGESELECTEDLARGEST, Rect);
00816             }
00817             break;
00818         }
00819     }
00820 }
00821 
00822 
00823 /********************************************************************************************
00824 
00825 >   void BlobManager::Render(DocRect Rect, Spread *pSpread)
00826 
00827     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00828     Created:    16/6/94
00829     Purpose:    This function will render all the blobs that are currently being displayed
00830                 for the given clipping rectangle.
00831 
00832 ********************************************************************************************/
00833 
00834 void BlobManager::Render(DocRect* Rect, Spread *pSpread)
00835 {
00836     // If we are not drawing blobs today, then return straight away
00837     if (!DrawBlobsAtAll)
00838         return;
00839 
00840     // Now render the sections that need to be rendered to get the corrent blobs on screen
00841     RenderRegion* pRegion = DocView::RenderOnTop(Rect, pSpread, ClippedEOR);
00842     while (pRegion)
00843     {
00844         // Find out the clipping rect of this region
00845         DocRect TestRect = pRegion->GetClipRect();
00846 
00847         // Find the first selected object in the tree;
00848         SelRange* Selected = GetApplication()->FindSelection();
00849 
00850         // Karim 29/06/2000
00851         //  PromoteToParent should never be set TRUE on the selection range, outside
00852         //  of code in which its modifications are required.
00853         //  I have included a TRACE statement here, as a 'quiet' note to programmers,
00854         //  should this occur.
00855         RangeControl rc = Selected->GetRangeControlFlags();
00856         if (rc.PromoteToParent)
00857         {
00858             TRACE( _T("BlobManager::Render; PromoteToParent is TRUE! Read inline comment for details.\n"));
00859             rc.PromoteToParent = FALSE;
00860             Selected->Range::SetRangeControl(rc);
00861         }
00862 
00863         Node* pNode = Selected->FindFirst();
00864         while(pNode)
00865         {
00866             // Render only the required blobs
00867             if (pNode->IsBounded())
00868             {
00869                 // This node is bounded, so see if we really need to render it
00870                 if (TestRect.IsIntersectedWith(((NodeRenderableBounded*)pNode)->GetBlobBoundingRect()))
00871                     RenderRequiredBlobs((NodeRenderable*)pNode, pRegion);
00872             }
00873             else
00874             {
00875                 // Always render it if it is not bounded (probably an Attribute)
00876                 RenderRequiredBlobs((NodeRenderable*)pNode, pRegion);
00877             }
00878 
00879             // Find the next selected node to render
00880             pNode = Selected->FindNext(pNode);
00881         }
00882 
00883         // Go find the next region
00884         pRegion = DocView::GetNextOnTop(Rect);
00885     }
00886 
00887     // Bodge to stop fill meshes EOR each other out.
00888     AttrFillGeometry::LastRenderedMesh = NULL;
00889 }
00890 
00891 /********************************************************************************************
00892 
00893 >   void BlobManager::RenderOn(DocRect Rect, Spread *pSpread)
00894 
00895     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00896     Created:    13/6/95
00897     Purpose:    This function will render on all the blobs that are currently being displayed
00898                 for the given clipping rectangle.
00899 
00900 ********************************************************************************************/
00901 
00902 void BlobManager::RenderOn(DocRect* Rect, Spread *pSpread)
00903 {
00904     RemovingBlobs = FALSE;
00905 
00906     // If we are not drawing blobs today, then return straight away
00907     if (!DrawBlobsAtAll)
00908         return;
00909 
00910     // Are we in the middle of a Background redraw ?
00911     RenderRegionList* pRegionList = GetApplication()->GetRegionList();
00912     if (pRegionList->IsEmpty())
00913     {
00914         // Nope, so do stuff as normal
00915 
00916         // Draw the blobs on
00917         Render(Rect, pSpread);
00918 
00919         // Stop fill meshes EORing each other out.
00920         AttrFillGeometry::LastRenderedMesh = NULL;
00921         return;
00922     }
00923 
00924     // We must be background rendering ...
00925     // So lets try a bit of an optimisation
00926 
00927     // If the Blob we are about to render, is completely contained
00928     // within a pending Render Region, then we don't need to
00929     // render anything
00930 
00931     if (!NeedToRenderSelectionBlobs(Rect))
00932         return;
00933 
00934     // Oh well, lets render some blobs then
00935 
00936     // Draw the blobs on
00937     Render(Rect, pSpread);
00938 
00939     // Stop fill meshes EORing each other out.
00940     AttrFillGeometry::LastRenderedMesh = NULL;
00941     
00942     // Now EOR off in all the render regions that are still rendering,
00943     // so that the Blob rendering when the region is finished, 
00944     // will put them on
00945     RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();  
00946 
00947     while (pRegion)
00948     {
00949         // Check the RenderRegion is for the same spread.
00950         if (pRegion->GetRenderSpread() == pSpread &&
00951             pRegion->GetRenderView()==DocView::GetSelected() &&
00952             (pRegion->IsInkRenderStarted || pRegion->NeedsOSPaper))
00953         {
00954             // Render the blobs 'clipped' to this Render Region.
00955             DocRect ClipRect = pRegion->GetRegionRect();
00956             Render(&ClipRect, pSpread);
00957         }
00958 
00959         // Get the Next render region
00960         pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
00961     }
00962 
00963     // Stop fill meshes EORing each other out.
00964     AttrFillGeometry::LastRenderedMesh = NULL;
00965 }
00966 
00967 /********************************************************************************************
00968 
00969 >   void BlobManager::RenderOff(DocRect Rect, Spread *pSpread)
00970 
00971     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00972     Created:    13/6/95
00973     Purpose:    This function will render off all the blobs that are currently being displayed
00974                 for the given clipping rectangle.
00975 
00976 ********************************************************************************************/
00977 
00978 void BlobManager::RenderOff(DocRect* Rect, Spread *pSpread)
00979 {
00980     RemovingBlobs = TRUE;
00981 
00982     // If we are not drawing blobs today, then return straight away
00983     if (!DrawBlobsAtAll)
00984         return;
00985 
00986     // Are we in the middle of a Background redraw ?
00987     RenderRegionList* pRegionList = GetApplication()->GetRegionList();
00988     if (pRegionList->IsEmpty())
00989     {
00990         // Nope, so do stuff as normal
00991 
00992         // Draw the blobs on
00993         Render(Rect, pSpread);
00994 
00995         // Stop fill meshes EORing each other out.
00996         AttrFillGeometry::LastRenderedMesh = NULL;
00997         return;
00998     }
00999 
01000     // We must be background rendering ...
01001     // So lets try a bit of an optimisation
01002 
01003     // If the Blob we are about to render, is completely contained
01004     // within a pending Render Region, then we don't need to
01005     // render anything
01006 
01007     if (!NeedToRenderSelectionBlobs(Rect))
01008         return;
01009 
01010     // Oh well, lets render some blobs then
01011 
01012     // EOR on in all the render regions that are still rendering,
01013     // so that the Blob rendering when the region is finished, 
01014     // will take them off
01015     RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();  
01016 
01017     while (pRegion)
01018     {
01019         // Check the RenderRegion is for the same spread.
01020         if (pRegion->GetRenderSpread() == pSpread &&
01021             pRegion->GetRenderView()==DocView::GetSelected() &&
01022             (pRegion->IsInkRenderStarted || pRegion->NeedsOSPaper))
01023         {
01024             // Render the blobs 'clipped' to this Render Region.
01025             DocRect ClipRect = pRegion->GetRegionRect();
01026             Render(&ClipRect, pSpread);
01027         }
01028 
01029         // Get the Next render region
01030         pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
01031     }
01032 
01033     // Stop fill meshes EORing each other out.
01034     AttrFillGeometry::LastRenderedMesh = NULL;
01035 
01036     // Draw the blobs off
01037     Render(Rect, pSpread);
01038 
01039     // Stop fill meshes EORing each other out.
01040     AttrFillGeometry::LastRenderedMesh = NULL;
01041 }
01042 
01043 /********************************************************************************************
01044 
01045 >   void BlobManager::RenderMyBlobs(NodeRenderable* pNode)
01046 
01047     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
01048     Created:    17/6/94
01049     Inputs:     pNode - The node to render the blobs of
01050     Purpose:    Renders the blobs for the given node. Only the required blobs are rendered
01051                 and since the blobs are EOR rendered, this function can be used to put
01052                 the blobs onto the screen or take them off the screen
01053 
01054 ********************************************************************************************/
01055 
01056 void BlobManager::RenderMyBlobs(DocRect* Rect, Spread *pSpread, NodeRenderable* pNode)
01057 {
01058     // If we are not drawing blobs today, then return straight away
01059     if (!DrawBlobsAtAll)
01060         return;
01061 
01062     // Now render the sections that need to be rendered to get the corrent blobs on screen
01063     RenderRegion* pRegion = DocView::RenderOnTop(Rect, pSpread, ClippedEOR);
01064     while (pRegion)
01065     {
01066         // Find out the clipping rect of this region
01067         DocRect TestRect = pRegion->GetClipRect();
01068 
01069         // Render only the blobs that need to be drawn
01070         if (pNode->IsBounded())
01071         {
01072             // This node is bounded, so see if we really need to render it
01073             if (TestRect.IsIntersectedWith(((NodeRenderableBounded*)pNode)->GetBlobBoundingRect()))
01074                 RenderRequiredBlobs(pNode, pRegion);
01075         }
01076         else
01077         {
01078             // Always render it if it is not bounded (probably an Attribute)
01079             RenderRequiredBlobs(pNode, pRegion);
01080         }
01081 
01082         // Go find the next region
01083         pRegion = DocView::GetNextOnTop(Rect);
01084     }
01085 }
01086 
01087 /********************************************************************************************
01088 
01089 >   void BlobManager::RenderMyBlobsOn(DocRect* Rect, Spread *pSpread, NodeRenderable* pNode)
01090 
01091     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01092     Created:    13/6/95
01093     Purpose:    This function will render on all the blobs that are currently being displayed
01094                 for the given clipping rectangle.
01095 
01096 ********************************************************************************************/
01097 
01098 void BlobManager::RenderMyBlobsOn(DocRect* Rect, Spread *pSpread, NodeRenderable* pNode)
01099 {
01100     RemovingBlobs = FALSE;
01101 
01102     // If we are not drawing blobs today, then return straight away
01103     if (!DrawBlobsAtAll)
01104         return;
01105 
01106     // Are we in the middle of a Background redraw ?
01107     RenderRegionList* pRegionList = GetApplication()->GetRegionList();
01108     if (pRegionList->IsEmpty())
01109     {
01110         // Nope, so do stuff as normal
01111 
01112         // Draw the blobs on
01113         RenderMyBlobs(Rect, pSpread, pNode);
01114         return;
01115     }
01116 
01117     // We must be background rendering ...
01118 
01119     // So lets try a bit of an optimisation
01120     if (!NeedToRenderNodeBlobs(Rect, pSpread, pNode))
01121         return;
01122 
01123     // Oh well, lets render some blobs then
01124     
01125     // Draw the blobs on
01126     RenderMyBlobs(Rect, pSpread, pNode);
01127 
01128     // Stop fill meshes EORing each other out.
01129     FillGeometryAttribute* pLastMesh = AttrFillGeometry::LastRenderedMesh;
01130     AttrFillGeometry::LastRenderedMesh = NULL;
01131     
01132     // Now EOR off in all the render regions that are still rendering,
01133     // so that the Blob rendering when the region is finished, 
01134     // will put them on
01135 
01136     RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();  
01137 
01138     while (pRegion)
01139     {
01140         // Check the RenderRegion is for the same spread.
01141         if (pRegion->GetRenderSpread() == pSpread &&
01142             pRegion->GetRenderView()==DocView::GetSelected() &&
01143             (pRegion->IsInkRenderStarted || pRegion->NeedsOSPaper))
01144         {
01145             // Render the blobs 'clipped' to this Render Region.
01146             DocRect ClipRect = pRegion->GetRegionRect();
01147             RenderMyBlobs(&ClipRect, pSpread, pNode);
01148         }
01149 
01150         // Get the Next render region
01151         pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
01152     }
01153 
01154     // Stop fill meshes EORing each other out.
01155     AttrFillGeometry::LastRenderedMesh = pLastMesh;
01156 }
01157 
01158 /********************************************************************************************
01159 
01160 >   void BlobManager::RenderMyBlobsOff(DocRect* Rect, Spread *pSpread, NodeRenderable* pNode)
01161 
01162     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01163     Created:    13/6/95
01164     Purpose:    This function will render off all the blobs that are currently being displayed
01165                 for the given clipping rectangle.
01166 
01167 ********************************************************************************************/
01168 
01169 void BlobManager::RenderMyBlobsOff(DocRect* Rect, Spread *pSpread, NodeRenderable* pNode)
01170 {
01171     RemovingBlobs = TRUE;
01172 
01173     // If we are not drawing blobs today, then return straight away
01174     if (!DrawBlobsAtAll)
01175         return;
01176 
01177     // Are we in the middle of a Background redraw ?
01178     RenderRegionList* pRegionList = GetApplication()->GetRegionList();
01179     if (pRegionList->IsEmpty())
01180     {
01181         // Nope, so do stuff as normal
01182 
01183         // Draw the blobs off
01184         RenderMyBlobs(Rect, pSpread, pNode);
01185         return;
01186     }
01187 
01188     // We must be background rendering ...
01189 
01190     // So lets try a bit of an optimisation
01191     if (!NeedToRenderNodeBlobs(Rect, pSpread, pNode))
01192         return;
01193 
01194     // Oh well, lets render some blobs then
01195 
01196     // EOR on in all the render regions that are still rendering,
01197     // so that the Blob rendering when the region is finished, 
01198     // will take them off
01199     RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();  
01200 
01201     while (pRegion)
01202     {
01203         // Check the RenderRegion is for the same spread.
01204         if (pRegion->GetRenderSpread() == pSpread &&
01205             pRegion->GetRenderView()==DocView::GetSelected() &&
01206             (pRegion->IsInkRenderStarted || pRegion->NeedsOSPaper))
01207         {
01208             // Render the blobs 'clipped' to this Render Region.
01209             DocRect ClipRect = pRegion->GetRegionRect();
01210             RenderMyBlobs(&ClipRect, pSpread, pNode);
01211         }
01212 
01213         // Get the Next render region
01214         pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
01215     }
01216 
01217     // Stop fill meshes EORing each other out.
01218     FillGeometryAttribute* pLastMesh = AttrFillGeometry::LastRenderedMesh;
01219     AttrFillGeometry::LastRenderedMesh = NULL;
01220 
01221     // Draw the blobs off
01222     RenderMyBlobs(Rect, pSpread, pNode);
01223 
01224     // Stop fill meshes EORing each other out.
01225     AttrFillGeometry::LastRenderedMesh = pLastMesh;
01226 }
01227 
01228 /********************************************************************************************
01229 
01230 >   void BlobManager::RenderObjectBlobsOn(DocRect* Rect, Spread *pSpread, NodeRenderable* pNode)
01231 
01232     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01233     Created:    13/6/95
01234     Purpose:    This function will render on all the blobs that are currently being displayed
01235                 for the given clipping rectangle.
01236 
01237 ********************************************************************************************/
01238 
01239 void BlobManager::RenderObjectBlobsOn(DocRect* Rect, Spread *pSpread, NodeRenderable* pNode)
01240 {
01241     RemovingBlobs = FALSE;
01242 
01243     // Are we in the middle of a Background redraw ?
01244     RenderRegionList* pRegionList = GetApplication()->GetRegionList();
01245     if (pRegionList->IsEmpty())
01246     {
01247         // Nope, so do stuff as normal
01248 
01249         // Draw the blobs on
01250         RenderObjectBlobs(Rect, pSpread, pNode);
01251         return;
01252     }
01253 
01254     // We must be background rendering ...
01255 
01256     // So lets try a bit of an optimisation
01257     if (!NeedToRenderNodeBlobs(Rect, pSpread, pNode))
01258         return;
01259 
01260     // Oh well, lets render some blobs then
01261 
01262     // Draw the blobs on
01263     RenderObjectBlobs(Rect, pSpread, pNode);
01264 
01265     // EOR off in all the render regions that are still rendering,
01266     // so that the Blob rendering when the region is finished, 
01267     // will put them on
01268     RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();  
01269 
01270     while (pRegion)
01271     {
01272         // Check the RenderRegion is for the same spread.
01273         if (pRegion->GetRenderSpread() == pSpread &&
01274             pRegion->GetRenderView()==DocView::GetSelected() &&
01275             (pRegion->IsInkRenderStarted || pRegion->NeedsOSPaper))
01276         {
01277             // Render the blobs 'clipped' to this Render Region.
01278             DocRect ClipRect = pRegion->GetRegionRect();
01279 
01280             // Render what we need to
01281             RenderObjectBlobs(&ClipRect, pSpread, pNode);
01282         }
01283 
01284         // Get the Next render region
01285         pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
01286     }
01287 }
01288 
01289 /********************************************************************************************
01290 
01291 >   void BlobManager::RenderObjectBlobsOff(DocRect* Rect, Spread *pSpread, NodeRenderable* pNode)
01292 
01293     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01294     Created:    13/6/95
01295     Purpose:    This function will render off all the blobs that are currently being displayed
01296                 for the given clipping rectangle.
01297 
01298 ********************************************************************************************/
01299 
01300 void BlobManager::RenderObjectBlobsOff(DocRect* Rect, Spread *pSpread, NodeRenderable* pNode)
01301 {
01302     RemovingBlobs = TRUE;
01303 
01304     // Are we in the middle of a Background redraw ?
01305     RenderRegionList* pRegionList = GetApplication()->GetRegionList();
01306     if (pRegionList->IsEmpty())
01307     {
01308         // Nope, so do stuff as normal
01309 
01310         // Draw the blobs off
01311         RenderObjectBlobs(Rect, pSpread, pNode);
01312         return;
01313     }
01314 
01315     // We must be background rendering ...
01316 
01317     // So lets try a bit of an optimisation
01318     if (!NeedToRenderNodeBlobs(Rect, pSpread, pNode))
01319         return;
01320 
01321     // Oh well, lets render some blobs then
01322 
01323     // EOR on in all the render regions that are still rendering,
01324     // so that the Blob rendering when the region is finished, 
01325     // will take them off
01326     RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();  
01327 
01328     while (pRegion)
01329     {
01330         // Check the RenderRegion is for the same spread.
01331         if (pRegion->GetRenderSpread() == pSpread &&
01332             pRegion->GetRenderView()==DocView::GetSelected() &&
01333             (pRegion->IsInkRenderStarted || pRegion->NeedsOSPaper))
01334         {
01335             // Render the blobs 'clipped' to this Render Region.
01336             DocRect ClipRect = pRegion->GetRegionRect();
01337 
01338             // Render what we need to
01339             RenderObjectBlobs(&ClipRect, pSpread, pNode);
01340         }
01341 
01342         // Get the Next render region
01343         pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
01344     }
01345 
01346     // Draw the blobs off
01347     RenderObjectBlobs(Rect, pSpread, pNode);
01348 }
01349 
01350 /********************************************************************************************
01351 
01352 >   void BlobManager::RenderObjectBlobs(DocRect* Rect, Spread *pSpread, NodeRenderable* pNode)
01353 
01354     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01355     Created:    13/6/95
01356     Purpose:    This function will render all the blobs that are currently being displayed
01357                 for the given clipping rectangle.
01358 
01359 ********************************************************************************************/
01360 
01361 void BlobManager::RenderObjectBlobs(DocRect* Rect, Spread *pSpread, NodeRenderable* pNode)
01362 {
01363     RenderRegion* pOnTopRegion = DocView::RenderOnTop(Rect, pSpread, ClippedEOR);
01364     while (pOnTopRegion)
01365     {
01366         pNode->RenderObjectBlobs(pOnTopRegion);
01367 
01368         // Go find the next region
01369         pOnTopRegion = DocView::GetNextOnTop(Rect);
01370     }
01371 }
01372 
01373 /********************************************************************************************
01374 
01375 >   void BlobManager::RenderRequiredBlobs(NodeRenderable* pNode, RenderRegion* pRegion)
01376 
01377     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
01378     Created:    22/6/94
01379     Inputs:     pNode - The Node whos blobs need rendering
01380                 pRegion - The render region to draw into
01381     Purpose:    Renders the required blobs for the given node into the given render region.
01382                 The required blobs are specified by the tool when it is activated.
01383 
01384 ********************************************************************************************/
01385 
01386 void BlobManager::RenderRequiredBlobs(NodeRenderable* pNode, RenderRegion* pRegion)
01387 {
01388     // We know that the node is a renderable ink as it is selected
01389     ENSURE( pNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)), "Selected object was not Renderable!");
01390 
01391     // Render the Object Blobs of this node
01392     if (IsObjectBlob)
01393         pNode->RenderObjectBlobs(pRegion);
01394 
01395     // Render the Artistic blobs of this node
01396     if (IsArtisticBlob)
01397         pNode->RenderArtisticBlobs(pRegion);
01398 
01399     // Render the Fill blobs of this node
01400     if (IsFillBlob)
01401         pNode->RenderAppliedFillBlobs(pRegion);
01402 
01403     // Render the Fill blobs of this node
01404     if (IsEffectBlob)
01405         pNode->RenderEffectBlobs(pRegion);
01406 
01407     // Render the tiny blobs of this node
01408     if (IsTinyBlob)
01409         pNode->RenderTinyBlobs(pRegion);
01410 
01411     // Render the pen blobs of this node
01412     if (IsPenBlob)
01413         pNode->RenderPenBlobs(pRegion);
01414 
01415     // Render the ToolObject blobs of this node
01416     if (IsToolObjectBlob)
01417         pNode->RenderToolObjectBlobs(pRegion);
01418 }
01419 
01420 /********************************************************************************************
01421 
01422 >   void BlobManager::RenderRequiredBlobsOnSelection(DocRect* Rect)
01423 
01424     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01425     Created:    14/6/95
01426     Inputs:     pNode - The Node whos blobs need rendering
01427                 pRegion - The render region to draw into
01428     Purpose:    Renders the required blobs for the given node into the given render region.
01429                 The required blobs are specified by the tool when it is activated.
01430 
01431 ********************************************************************************************/
01432 
01433 void BlobManager::RenderRequiredBlobsOnSelection(DocRect* Rect)
01434 {
01435     // Find out which spread the selection is on
01436     SelRange* Selected = GetApplication()->FindSelection();
01437     Node* pNode = Selected->FindFirst();
01438 
01439     // go and render the blobs if there are any selected nodes
01440     if (pNode!=NULL && DrawBlobsAtAll)
01441     {
01442         Spread* pSpread = pNode->FindParentSpread();
01443 
01444         // Render what we need to
01445         RenderRegion* pRegion = DocView::RenderOnTop(Rect, pSpread, ClippedEOR);
01446         while (pRegion)
01447         {
01448             // Find the first selected object in the tree;
01449             Node* pNode = Selected->FindFirst();
01450             while(pNode)
01451             {
01452                 // Render only those blobs that are changing state (ie those appearing or disappearing)
01453                 RenderRequiredBlobs((NodeRenderable*) pNode, pRegion);
01454 
01455                 // Find the next selected node to render
01456                 pNode = Selected->FindNext(pNode);
01457             }
01458 
01459             // Go find the next region
01460             pRegion = DocView::GetNextOnTop(Rect);
01461         }
01462     }
01463 
01464     // Bodge to stop fill meshes EOR each other out.
01465     AttrFillGeometry::LastRenderedMesh = NULL;
01466 }
01467 
01468 /********************************************************************************************
01469 
01470 >   void BlobManager::RenderSpecificBlobs(NodeRenderable* pNode, RenderRegion* pRegion, 
01471                   BOOL DrawObject, BOOL DrawArtistic, BOOL DrawFill, BOOL DrawTiny,
01472                   BOOL DrawPen, BOOL DrawToolObject, BOOL DrawEffect)
01473 
01474     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
01475     Created:    22/6/94
01476     Inputs:     pNode - The node to draw the blobs for
01477                 pRegion - The region to render them into
01478                 DrawObject - Do we want to draw the Object Blobs
01479                 DrawArtistic - Do we want to draw the Artistic Blobs
01480                 DrawFill - Do we want to draw the Fill Blobs
01481                 DrawTiny - Do we want to draw the Tiny Blobs
01482                 DrawPen -  Do we want to draw the Pen Blobs
01483                 DrawToolObject - Do we want to draw the ToolObject Blobs
01484     Purpose:    Renders only the blobs specified. This is called from the Add and Remove
01485                 Interest Functions to add new types of blob to the display or take types of
01486                 blob that are no longer needed off the display.
01487 
01488 ********************************************************************************************/
01489 
01490 void BlobManager::RenderSpecificBlobs(NodeRenderable* pNode, RenderRegion* pRegion, 
01491                   BOOL DrawObject, BOOL DrawArtistic, BOOL DrawFill, BOOL DrawTiny,
01492                   BOOL DrawPen, BOOL DrawToolObject, BOOL DrawEffect)
01493 {
01494     // We know that the node is a renderable ink as it is selected
01495     ENSURE( pNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableInk)), "Selected object was not Renderable!");
01496 
01497     // Render the Object Blobs of this node
01498     if (DrawObject)
01499         pNode->RenderObjectBlobs(pRegion);
01500 
01501     // Render the Artistic blobs of this node
01502     if (DrawArtistic)
01503         pNode->RenderArtisticBlobs(pRegion);
01504 
01505     // Render the Fill blobs of this node
01506     if (DrawFill)
01507         pNode->RenderAppliedFillBlobs(pRegion);
01508 
01509     // Render the tiny blobs of this node
01510     if (DrawTiny)
01511         pNode->RenderTinyBlobs(pRegion);
01512 
01513     // Render the Pen blobs of this node
01514     if (DrawPen)
01515         pNode->RenderPenBlobs(pRegion);
01516 
01517     // Render the ToolObject blobs of this node
01518     if (DrawToolObject)
01519         pNode->RenderToolObjectBlobs(pRegion);
01520 
01521     // Render the Effect blobs of this node
01522     if (DrawEffect)
01523         pNode->RenderEffectBlobs(pRegion);
01524 }
01525 
01526 /********************************************************************************************
01527 
01528 >   void BlobManager::RenderSpecificBlobsOnSelection(BOOL DrawObject, BOOL DrawArtistic, 
01529                                                      BOOL DrawFill, BOOL DrawTiny,
01530                                                      BOOL DrawPen, BOOL DrawToolObject, BOOL DrawEffect)
01531 
01532     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01533     Created:    13/6/95
01534     Inputs:     pNode - The node to draw the blobs for
01535                 pRegion - The region to render them into
01536                 DrawObject - Do we want to draw the Object Blobs
01537                 DrawArtistic - Do we want to draw the Artistic Blobs
01538                 DrawFill - Do we want to draw the Fill Blobs
01539                 DrawTiny - Do we want to draw the Tiny Blobs
01540                 DrawPen -  Do we want to draw the Pen Blobs
01541                 DrawToolObject - Do we want to draw the ToolObject Blobs
01542     Purpose:    Renders only the blobs specified. This is called from the Add and Remove
01543                 Interest Functions to add new types of blob to the display or take types of
01544                 blob that are no longer needed off the display.
01545 
01546 ********************************************************************************************/
01547 
01548 void BlobManager::RenderSpecificBlobsOnSelection(   DocRect* Rect, BOOL DrawObject,
01549                                                     BOOL DrawArtistic, BOOL DrawFill,
01550                                                     BOOL DrawTiny, BOOL DrawPen,
01551                                                     BOOL DrawToolObject, BOOL DrawEffect )
01552 {
01553     // Find out which spread the selection is on
01554     SelRange* Selected = GetApplication()->FindSelection();
01555     Node* pNode = Selected->FindFirst();
01556 
01557     // go and render the blobs if there are any selected nodes
01558     if (pNode!=NULL && DrawBlobsAtAll)
01559     {
01560         Spread* pSpread = pNode->FindParentSpread();
01561 
01562         // Render what we need to
01563         RenderRegion* pRegion = DocView::RenderOnTop(Rect, pSpread, ClippedEOR);
01564         while (pRegion)
01565         {
01566             // Find the first selected object in the tree;
01567             Node* pNode = Selected->FindFirst();
01568             while(pNode)
01569             {
01570                 // Render only those blobs that are changing state (ie those appearing or disappearing)
01571                 RenderSpecificBlobs((NodeRenderable*)pNode, pRegion, DrawObject, DrawArtistic,
01572                                     DrawFill, DrawTiny, DrawPen, DrawToolObject, DrawEffect);
01573 
01574                 // Find the next selected node to render
01575                 pNode = Selected->FindNext(pNode);
01576             }
01577 
01578             // Go find the next region
01579             pRegion = DocView::GetNextOnTop(Rect);
01580         }
01581     }
01582 
01583     // Bodge to stop fill meshes EOR each other out.
01584     AttrFillGeometry::LastRenderedMesh = NULL;
01585 }
01586 
01587 /********************************************************************************************
01588 
01589 >   MsgResult BlobManager::Message(Msg* Message)
01590 
01591     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
01592     Created:    29/6/94
01593     Inputs:     Message - the message to examine
01594     Returns:    -
01595     Purpose:    Handles the View Changing message, and makes sure that the blobs are
01596                 removed from the old view and drawn onto the new view
01597 
01598 ********************************************************************************************/
01599 
01600 MsgResult BlobManager::Message(Msg* Message)
01601 {
01602     if (MESSAGE_IS_A(Message, DocViewMsg))
01603     {
01604         // Get a version of the message in the right type
01605         DocViewMsg* pDocViewMsg = (DocViewMsg*) Message;
01606 
01607         switch (pDocViewMsg->State)
01608         {
01609             // respond to messages that arrive just before and just after the view has changed.
01610             case DocViewMsg::SELABOUTTOCHANGE:
01611             case DocViewMsg::SELCHANGED:
01612             {
01613                 // rub blobs off old view or draw them in on the new one
01614                 if (DocView::GetSelected()!=NULL)
01615                 {
01616                     // go find the selection
01617                     SelRange* Selected = GetApplication()->FindSelection();
01618                     
01619                     // Have to be sure that the selection is correct for the view
01620                     Selected->Update();
01621                     Node* pNode = Selected->FindFirst();
01622             
01623                     // If there is something selected
01624                     if (pNode!=NULL)
01625                     {
01626                         // Find its spread
01627                         Spread* pSpread = pNode->FindParentSpread();
01628                         if (pSpread!=NULL)
01629                         {
01630                             // and render the blobs
01631                             Render(NULL, pSpread);
01632                         }
01633                     }
01634                 }
01635                 break;
01636             }
01637 
01638 
01639             default:
01640                 break;
01641         }
01642     }
01643 
01644     return OK; 
01645 }      
01646 
01647 /********************************************************************************************
01648 
01649 >   void BlobManager::RenderToolBlobsOn(Tool_v1* pTool, Spread* pSpread, DocRect* pClipRect)
01650 
01651     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01652     Created:    13/6/95
01653     Purpose:    This function will render on the specified tools blobs.
01654 
01655 ********************************************************************************************/
01656 
01657 void BlobManager::RenderToolBlobsOn(Tool_v1* pTool, Spread* pSpread, DocRect* pClipRect)
01658 {
01659     // If we are not drawing blobs today, then return straight away
01660     if (!DrawBlobsAtAll)
01661         return;
01662 
01663     // Put the tool blobs on
01664     pTool->RenderToolBlobs(pSpread, pClipRect);
01665 
01666     // Now EOR off in all the render regions that are still rendering,
01667     // so that the Blob rendering when the region is finished, 
01668     // will put them on
01669     RenderRegionList* pRegionList = GetApplication()->GetRegionList();
01670 
01671     if (!pRegionList->IsEmpty())
01672     {
01673         RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();  
01674 
01675         while (pRegion)
01676         {
01677             // Check the RenderRegion is for the same spread.
01678             if (pRegion->GetRenderSpread() == pSpread && pRegion->GetRenderView()==DocView::GetSelected())
01679             {
01680                 // Render the blobs 'clipped' to this Render Region.
01681                 DocRect ClipRect = pRegion->GetRegionRect();
01682                 pTool->RenderToolBlobs(pSpread, &ClipRect);
01683             }
01684 
01685             // Get the Next render region
01686             pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
01687         }
01688     }
01689     bToolBlobsAreOff = FALSE;
01690 }
01691 
01692 /********************************************************************************************
01693 
01694 >   void BlobManager::RenderToolBlobsOff(Tool_v1* pTool, Spread* pSpread, DocRect* pClipRect)
01695 
01696     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01697     Created:    13/6/95
01698     Purpose:    This function will render off the specified tools blobs.
01699 
01700 ********************************************************************************************/
01701 
01702 void BlobManager::RenderToolBlobsOff(Tool_v1* pTool, Spread* pSpread, DocRect* pClipRect)
01703 {
01704     // If we are not drawing blobs today, then return straight away
01705     if (!DrawBlobsAtAll)
01706         return;
01707 
01708 //  if (bToolBlobsAreOff)
01709 //      return;
01710 
01711     // EOR on in all the render regions that are still rendering,
01712     // so that the Blob rendering when the region is finished, 
01713     // will take them off
01714     RenderRegionList* pRegionList = GetApplication()->GetRegionList();
01715 
01716     if (!pRegionList->IsEmpty())
01717     {
01718         RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();  
01719 
01720         while (pRegion)
01721         {
01722             // Check the RenderRegion is for the same spread.
01723             if (pRegion->GetRenderSpread() == pSpread && pRegion->GetRenderView()==DocView::GetSelected())
01724             {
01725                 // Render the blobs 'clipped' to this Render Region.
01726                 DocRect ClipRect = pRegion->GetRegionRect();
01727                 pTool->RenderToolBlobs(pSpread, &ClipRect);
01728             }
01729 
01730             // Get the Next render region
01731             pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
01732         }
01733     }
01734 
01735     // Take the tool blobs off
01736     pTool->RenderToolBlobs(pSpread, pClipRect);
01737     bToolBlobsAreOff = TRUE;
01738 }
01739 
01740 /********************************************************************************************
01741 
01742 >   BOOL BlobManager::NeedToRenderSelectionBlobs(DocRect* Rect)
01743 
01744     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01745     Created:    15/6/95
01746     Purpose:    Check to make sure we need to render some blobs.
01747 
01748 ********************************************************************************************/
01749 
01750 BOOL BlobManager::NeedToRenderSelectionBlobs(DocRect* Rect)
01751 {
01752     RenderRegionList* pRegionList = GetApplication()->GetRegionList();
01753     if (pRegionList->IsEmpty())
01754         return TRUE;
01755 
01756     // Find the first selected object in the tree;
01757     SelRange* Selected = GetApplication()->FindSelection();
01758 
01759     if (Selected->Count() == 0)
01760         return FALSE;       // Nothing to render
01761 
01762     Node* pNode = Selected->FindFirst();
01763     Spread* pSpread = pNode->FindParentSpread();
01764 
01765     // Find out the blob rect of the selection
01766     DocRect SelRect = Selected->GetBlobBoundingRect();
01767     
01768     // If a clip rect was given, and it doesn't completely contain the sel bounds,
01769     // then we'll have to use that
01770     if (Rect && !Rect->ContainsRect(SelRect))
01771         SelRect = *Rect;
01772 
01773     if (!SelRect.IsEmpty())
01774     {
01775         // So lets check the pending regions
01776         RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();  
01777 
01778         while (pRegion)
01779         {
01780             // Check the RenderRegion is for the same spread.
01781             if (pRegion->GetRenderSpread() == pSpread &&
01782                 pRegion->GetRenderView()==DocView::GetSelected() &&
01783                 (pRegion->IsInkRenderStarted || pRegion->NeedsOSPaper))
01784             {
01785                 // Get the 'clip' rect of this Render Region.
01786                 DocRect ClipRect = pRegion->GetRegionRect();
01787 
01788                 // If any of the RenderRegions completely contain the rect
01789                 // then there is no point in rendering anything
01790 
01791                 if (ClipRect.ContainsRect(SelRect))
01792                     return FALSE;       // We don't need to render any blobs
01793             }
01794 
01795             // Get the Next render region
01796             pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
01797         }
01798     } 
01799     return TRUE;
01800 }
01801 
01802 /********************************************************************************************
01803 
01804 >   BOOL BlobManager::NeedToRenderNodeBlobs(DocRect* Rect, Spread *pSpread, NodeRenderable* pNode)
01805 
01806     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01807     Created:    15/6/95
01808     Purpose:    Check to make sure we need to render some blobs.
01809 
01810 ********************************************************************************************/
01811 
01812 BOOL BlobManager::NeedToRenderNodeBlobs(DocRect* Rect, Spread *pSpread, NodeRenderable* pNode)
01813 {
01814     RenderRegionList* pRegionList = GetApplication()->GetRegionList();
01815     if (pRegionList->IsEmpty())
01816         return TRUE;
01817 
01818     if (Rect != NULL || pNode->IsBounded())
01819     {
01820         // If the Blob we are about to render, is completely contained
01821         // within a pending Render Region, then we don't need to
01822         // render anything
01823 
01824         // Find out the blob rect of this node, if we can
01825         DocRect NodeRect = DocRect(0,0,0,0);
01826         
01827         if (pNode->IsBounded())
01828         {
01829             // Use the node's blob bounds
01830             NodeRect = ((NodeRenderableBounded*)pNode)->GetBlobBoundingRect();
01831         }
01832 
01833         // If a clip rect was given, and it doesn't completely contain the node rect,
01834         // then we'll have to use that
01835         if (Rect && !Rect->ContainsRect(NodeRect))
01836             NodeRect = *Rect;
01837 
01838         if (!NodeRect.IsEmpty())
01839         {
01840             // So lets check the pending regions
01841             RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();  
01842 
01843             while (pRegion)
01844             {
01845                 // Check the RenderRegion is for the same spread.
01846                 if (pRegion->GetRenderSpread() == pSpread &&
01847                     pRegion->GetRenderView()==DocView::GetSelected() &&
01848                     (pRegion->IsInkRenderStarted || pRegion->NeedsOSPaper))
01849                 {
01850                     // Get the 'clip' rect of this Render Region.
01851                     DocRect ClipRect = pRegion->GetRegionRect();
01852 
01853                     // If any of the RenderRegions completely contain the rect
01854                     // then there is no point in rendering anything
01855 
01856                     if (ClipRect.ContainsRect(NodeRect))
01857                         return FALSE;       // We don't need to render this node's blobs
01858                 }
01859 
01860                 // Get the Next render region
01861                 pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
01862             }
01863         }
01864     }
01865     return TRUE;
01866 }

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