xpfrgn.cpp

Go to the documentation of this file.
00001 // $Id: xpfrgn.cpp 1708 2006-08-17 17:13:38Z gerry $
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 
00100 /*
00101 */
00102 
00103 #include "camtypes.h"
00104 #include "xpfrgn.h"
00105 
00106 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 #include "xpfilter.h"
00108 #include "xpfcaps.h"
00109 //#include "rrcaps.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 #include "insertnd.h"
00111 //#include "becomea.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 #include "opcntr.h"
00113 #include "lineattr.h"
00114 #include "strkattr.h"
00115 #include "brshattr.h"
00116 #include "vstate.h"
00117 #include "nodepath.h"
00118 #include "nodetxts.h"
00119 #include "nodetext.h"
00120 #include "nodetxtl.h"
00121 #include "grndbmp.h"
00122 
00123 // The implements to match the declares in the .h file.
00124 
00125 CC_IMPLEMENT_DYNAMIC(SpanListItem, ListItem);
00126 CC_IMPLEMENT_DYNAMIC(NodeThreeBoolListItem, ListItem);
00127 CC_IMPLEMENT_DYNAMIC(XPFRenderRegion, RenderRegion);
00128 CC_IMPLEMENT_DYNAMIC(XPFView, View);
00129 
00130 // Proper memory dumps
00131 #define new CAM_DEBUG_NEW
00132 
00133 
00134 
00135 
00136 /********************************************************************************************
00137 
00138 >   XPFRenderRegion::XPFRenderRegion(PluginNativeFilter* pFilter, 
00139                                         CapabilityTree* pPlugCaps, 
00140                                         CommonTransInfo* pTransInfo)
00141 
00142     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00143     Created:    6/4/95
00144     Purpose:    The Scanning Render Regions constructor. This sets all the member vars of
00145                 the class to default values (usually 0 or NULL).
00146 
00147 ********************************************************************************************/
00148 
00149 XPFRenderRegion::XPFRenderRegion(PluginNativeFilter* pFilter, CapabilityTree* pPlugCaps, CommonTransInfo* pTransInfo)
00150 {
00151     m_pFilter = pFilter;
00152     m_PixelsPerInch = pPlugCaps ? pPlugCaps->GetRasteriseDPI() : 96.0;
00153     m_pTransInfo = pTransInfo;
00154 }
00155 
00156 
00157 
00158 /********************************************************************************************
00159 
00160 >   XPFRenderRegion::~XPFRenderRegion()
00161 
00162     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00163     Created:    6/4/95
00164     Purpose:    Destructor - It will do something if it needs to but at present this function
00165                 is empty
00166 
00167 ********************************************************************************************/
00168 
00169 XPFRenderRegion::~XPFRenderRegion()
00170 {
00171 }
00172 
00173 
00174 BOOL XPFRenderRegion::AttachDevice(View* ViewToAttach, CNativeDC* DCToAttach,
00175                                 Spread* SpreadToAttach)
00176 {
00177     BOOL ok = RenderRegion::AttachDevice(ViewToAttach, DCToAttach, SpreadToAttach);
00178     if (ok)
00179     {
00180         
00181 
00182     }
00183 
00184     return(ok);
00185 }
00186 
00187 
00188 
00189 /********************************************************************************************
00190 
00191 >   virtual BOOL XPFRenderRegion::StartRender()
00192 
00193     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00194     Created:    6/4/95
00195     Returns:    TRUE if everything went OK, FALSE if there was a problem
00196     Purpose:    Called to start the rendering process. Allows the render region to get
00197                 ready to start rendering
00198     SeeAlso:    XPFRenderRegion::StopRender
00199 
00200 ********************************************************************************************/
00201 
00202 BOOL XPFRenderRegion::StartRender()
00203 {
00204     // Call base class first
00205     if (!RenderRegion::StartRender())
00206         return FALSE;
00207 
00208     // All worked
00209     return TRUE;
00210 }
00211 
00212 
00213 /********************************************************************************************
00214 
00215 >   virtual BOOL XPFRenderRegion::StopRender()
00216 
00217     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00218     Created:    6/4/95
00219     Purpose:    Called to stop rendering.
00220 
00221 ********************************************************************************************/
00222 
00223 BOOL XPFRenderRegion::StopRender()
00224 {
00225     return(TRUE);
00226 }
00227 
00228 
00229 
00230 /********************************************************************************************
00231 
00232 >   virtual void XPFRenderRegion::DrawPathToOutputDevice(Path* pPathToRender)
00233 
00234     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00235     Created:    6/4/95
00236     Inputs:     pPathToRender - The path that we want to try and render
00237     Purpose:    There is no actual rendering, as this class does not actually render anything
00238                 to a device.
00239 
00240 ********************************************************************************************/
00241 
00242 void XPFRenderRegion::DrawPathToOutputDevice(Path* pPathToRender, PathShape)
00243 {
00244     if (m_pTransInfo && m_pTransInfo->IsCommonType())
00245     {
00246         // Path rendering happens in two parts, the fill and the stroke
00247         // so these must be checked separately
00248 
00249         if (pPathToRender->IsFilled)
00250         {
00251             // Get the fill attribute
00252             FillGeometryAttribute* pFillAttr = (FillGeometryAttribute*) CurrentAttrs[ATTR_FILLGEOMETRY].pAttr;
00253             
00254             // If it is not a no-colour flat fill then
00255 
00256             if (!IS_A(pFillAttr, FlatFillAttribute) || !(RR_FILLCOLOUR().IsTransparent()))
00257             {
00258                 // Get the current Transparency Fill Geometry
00259                 TranspFillAttribute* pTransAttr = RR_FILLTRANSP();
00260 
00261                 // And update the common type object
00262                 m_pTransInfo->UpdateCommonType(pTransAttr->GetTranspType());
00263             }
00264         }
00265 
00266         if (pPathToRender->IsStroked)
00267         {
00268             // If the stroke colour is not transparent
00269             if (!(RR_STROKECOLOUR().IsTransparent()))
00270             {
00271                 // Get the current Transparency Fill Geometry
00272                 StrokeTranspAttribute* pTransAttr = RR_STROKETRANSP();
00273 
00274                 // And update the common type object
00275                 m_pTransInfo->UpdateCommonType(pTransAttr->GetTranspType());
00276             }
00277         }
00278     }
00279 }
00280 
00281 
00282 /********************************************************************************************
00283 
00284 >   virtual void XPFRenderRegion::DrawRect(DocRect* pRectToRender)
00285 
00286     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00287     Created:    6/4/95
00288     Inputs:     pRectToRender - The Rectangle that we need to render
00289     Purpose:    There is no actual rendering, as this class does not actually render anything
00290                 to a device.
00291 
00292 ********************************************************************************************/
00293 
00294 void XPFRenderRegion::DrawRect(DocRect* pRectToRender)
00295 {
00296 }
00297 
00298 
00299 /********************************************************************************************
00300 
00301 >   virtual void XPFRenderRegion::DrawLine(const DocCoord &StartPoint,
00302                                                 const DocCoord &EndPoint)
00303 
00304     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00305     Created:    6/4/95
00306     Inputs:     StartPoint, EndPoint - the coords to draw a line between
00307     Purpose:    There is no actual rendering, as this class does not actually render anything
00308                 to a device.
00309 
00310 ********************************************************************************************/
00311 
00312 void XPFRenderRegion::DrawLine(const DocCoord &StartPoint, const DocCoord &EndPoint)
00313 {
00314 }
00315 
00316 
00317 /********************************************************************************************
00318 
00319 >   virtual void XPFRenderRegion::DrawPixel(const DocCoord &Point)
00320 
00321     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00322     Created:    6/4/95
00323     Inputs:     Point - the coord to draw the pixel in
00324     Purpose:    There is no actual rendering, as this class does not actually render anything
00325                 to a device.
00326 
00327 ********************************************************************************************/
00328 
00329 void XPFRenderRegion::DrawPixel(const DocCoord &Point)
00330 {
00331 }
00332 
00333 
00334 /********************************************************************************************
00335 
00336 >   virtual void XPFRenderRegion::DrawBitmap(const DocCoord &Point, KernelBitmap* pBitmap)
00337 
00338     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00339     Created:    6/4/95
00340     Inputs:     Point - The position to draw the bitmap at
00341                 pBitmap - the bitmap that needs drawing
00342     Purpose:    There is no actual rendering, as this class does not actually render anything
00343                 to a device.
00344 
00345 ********************************************************************************************/
00346 
00347 void XPFRenderRegion::DrawBitmap(const DocCoord &Point, KernelBitmap* pBitmap)
00348 {
00349 }
00350 
00351 
00352 /********************************************************************************************
00353 
00354 >   virtual void XPFRenderRegion::DrawBitmap(const DocCoord &Point, UINT32 BitmapID,
00355                                                 UINT32 ToolID)
00356 
00357     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00358     Created:    6/4/95
00359     Inputs:     Point - the position to draw the bitmap at
00360                 BitmapID - The ID of the bitmap to render
00361                 ToolID - the ID of the tool that the bitmap belongs to
00362     Purpose:    There is no actual rendering, as this class does not actually render anything
00363                 to a device.
00364 
00365 ********************************************************************************************/
00366 
00367 void XPFRenderRegion::DrawBitmap(const DocCoord &Point, UINT32 BitmapID, UINT32 ToolID)
00368 {
00369 }
00370 
00371 
00372 /********************************************************************************************
00373 
00374 >   BOOL XPFRenderRegion::DrawTransformedBitmap(NodeBitmap *pNodeBitmap)
00375 
00376     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00377     Created:    24/7/95
00378     Inputs:     pNodeBitmap - The bitmap to render
00379     Returns:    TRUE if it worked, FLASE if not
00380     Purpose:    Works out if it can draw a Transformed bitmap.
00381 
00382 ********************************************************************************************/
00383 
00384 BOOL XPFRenderRegion::DrawTransformedBitmap(NodeBitmap *pNodeBitmap)
00385 {
00386     return TRUE;
00387 }
00388 
00389 
00390 /********************************************************************************************
00391 
00392 >   virtual void XPFRenderRegion::DrawDragRect(DocRect *RectToRender)
00393 
00394     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00395     Created:    6/4/95
00396     Inputs:     RectToRender - The Rectangle
00397     Purpose:    None - I just had to overide this function as it is pure virtual. Does nothing
00398 
00399 ********************************************************************************************/
00400 
00401 void XPFRenderRegion::DrawDragRect(DocRect *RectToRender)
00402 {
00403 }
00404 
00405 
00406 /********************************************************************************************
00407 
00408 >   virtual void XPFRenderRegion::DrawBlob(DocCoord p, BlobType type)
00409 
00410     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00411     Created:    6/4/95
00412     Inputs:     p - A coord
00413                 type - The type of blob
00414     Purpose:    None - I just had to overide this function as it is pure virtual. Does nothing
00415 
00416 ********************************************************************************************/
00417 
00418 void XPFRenderRegion::DrawBlob(DocCoord p, BlobType type)
00419 {
00420 }
00421 
00422 
00423 /********************************************************************************************
00424 
00425 >   virtual void XPFRenderRegion::DrawCross(const DocCoord &Point, const UINT32 Size)
00426 
00427     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00428     Created:    6/4/95
00429     Inputs:     Point - a Coord
00430                 Size - the size of the cross
00431     Purpose:    None - I just had to overide this function as it is pure virtual. Does nothing
00432 
00433 ********************************************************************************************/
00434 
00435 void XPFRenderRegion::DrawCross(const DocCoord &Point, const UINT32 Size)
00436 {
00437 }
00438 
00439 
00440 /********************************************************************************************
00441 
00442 >   virtual void XPFRenderRegion::DrawBitmapBlob(const DocCoord &Point,
00443                                                     KernelBitmap* BlobShape)
00444 
00445     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00446     Created:    6/4/95
00447     Inputs:     Point - A Coord
00448                 BlobShape - the bitmap to use
00449     Purpose:    None - I just had to overide this function as it is pure virtual. Does nothing
00450 
00451 ********************************************************************************************/
00452 
00453 void XPFRenderRegion::DrawBitmapBlob(const DocCoord &Point, KernelBitmap* BlobShape)
00454 {
00455 }
00456 
00457 
00458 /********************************************************************************************
00459 
00460 >   virtual void XPFRenderRegion::DrawBitmapBlob(const DocCoord &Point, ResourceID resID)
00461 
00462     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00463     Created:    6/4/95
00464     Inputs:     Point - A coord
00465                 ResourceID - the ID of a bitmap
00466     Purpose:    None - I just had to overide this function as it is pure virtual. Does nothing
00467 
00468 ********************************************************************************************/
00469 
00470 void XPFRenderRegion::DrawBitmapBlob(const DocCoord &Point, ResourceID resID)
00471 {
00472 }
00473 
00474 
00475 
00476 /********************************************************************************************
00477 
00478 >   virtual void XPFRenderRegion::GetRenderRegionCaps(RRCaps* pCaps)
00479 
00480     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00481     Created:    10/4/95
00482     Outputs:    pCaps - The details about what types of thing this render region can render
00483     Purpose:    This function allows render regions to admit to what they can and can not
00484                 render. This allows other areas of the program to come in and help render
00485                 regions out in some situations, if they are unable to render everything.
00486                 eg. an OSRenderRegion can not render transparancy.
00487 
00488 ********************************************************************************************/
00489 
00490 void XPFRenderRegion::GetRenderRegionCaps(RRCaps* pCaps)
00491 {
00492     pCaps->CanDoAll();
00493 }
00494 
00495 
00496 
00497 /********************************************************************************************
00498 
00499 >   virtual void XPFRenderRegion::InitClipping()
00500 
00501     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00502     Created:    6/4/95
00503     Purpose:    Sets up the clipping - does nothing in this class
00504 
00505 ********************************************************************************************/
00506 
00507 void XPFRenderRegion::InitClipping()
00508 {
00509 }
00510 
00511 
00512 /********************************************************************************************
00513 
00514 >   virtual void XPFRenderRegion::InitAttributes()
00515 
00516     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00517     Created:    6/4/95
00518     Purpose:    Sets up the attributes. Does nothing in this class
00519 
00520 ********************************************************************************************/
00521 
00522 void XPFRenderRegion::InitAttributes()
00523 {
00524 }
00525 
00526 
00527 /********************************************************************************************
00528 
00529 >   virtual void XPFRenderRegion::SetLineAttributes()
00530 
00531     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00532     Created:    6/4/95
00533     Purpose:    Does nothing in this class
00534 
00535 ********************************************************************************************/
00536 
00537 void XPFRenderRegion::SetLineAttributes()
00538 {
00539 }
00540 
00541 
00542 /********************************************************************************************
00543 
00544 >   virtual void XPFRenderRegion::SetOSDrawingMode()
00545 
00546     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00547     Created:    6/4/95
00548     Purpose:    Does nothing in this class
00549 
00550 ********************************************************************************************/
00551 
00552 void XPFRenderRegion::SetOSDrawingMode()
00553 {
00554 }
00555 
00556 
00557 /********************************************************************************************
00558 
00559 >   virtual void XPFRenderRegion::SetQualityLevel()
00560 
00561     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00562     Created:    6/4/95
00563     Purpose:    Does nothing in this class
00564 
00565 ********************************************************************************************/
00566 
00567 void XPFRenderRegion::SetQualityLevel()
00568 {
00569 }
00570 
00571 
00572 /********************************************************************************************
00573 
00574 >   virtual MILLIPOINT XPFRenderRegion::CalcPixelWidth()
00575 
00576     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00577     Created:    6/4/95
00578     Purpose:    Does nothing in this class
00579 
00580 ********************************************************************************************/
00581 
00582 MILLIPOINT XPFRenderRegion::CalcPixelWidth()
00583 {
00584     return MILLIPOINT( 72000.0 / m_PixelsPerInch);
00585 }
00586 
00587 
00588 /********************************************************************************************
00589 
00590 >   virtual MILLIPOINT XPFRenderRegion::CalcScaledPixelWidth()
00591 
00592     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00593     Created:    6/4/95
00594     Purpose:    Does nothing in this class
00595 
00596 ********************************************************************************************/
00597 
00598 MILLIPOINT XPFRenderRegion::CalcScaledPixelWidth()
00599 {
00600     const double dpi = 72000.0 / m_PixelsPerInch;
00601 
00602     return (MILLIPOINT)( (dpi / ScaleFactor.MakeDouble()) + 0.5 );
00603 }
00604 
00605 
00606 
00607 
00608 
00609 /****************************************************************************
00610 
00611 >   XPFRenderCallback::XPFRenderCallback(PluginNativeFilter* pFilter, XPFRenderRegion* pXPFRegion, CapabilityTree* pCapTree, INT32 ConvertPass)
00612 
00613     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00614     Created:    31/10/2005
00615 
00616     Inputs:     pFilter     - pointer to a PluginNativeFilter
00617                 pXPFRegion  - pointer to a XPFRenderRegion
00618                 pCapTree    - pointer to a CapabilityTree
00619                 ConvertPass - conversion pass
00620     Purpose:    Constructs an XPFRenderCallback object to control the 
00621                 rendering loop for each phase of the conversion mechanism
00622 
00623 ****************************************************************************/
00624 
00625 XPFRenderCallback::XPFRenderCallback(PluginNativeFilter* pFilter, XPFRenderRegion* pXPFRegion, CapabilityTree* pCapTree, INT32 ConvertPass)
00626 {
00627     m_pFilter = pFilter;
00628     m_pXPFRegion = pXPFRegion;
00629     m_pCapTree = pCapTree;
00630     m_ConvertPass = ConvertPass;
00631     m_pNewSpread = NULL;
00632     m_pContextNode = NULL;
00633     m_Direction = FIRSTCHILD;
00634     m_pSpanParent = NULL;
00635 }
00636 
00637 
00638 
00639 /****************************************************************************
00640 
00641 >   XPFRenderCallback::~XPFRenderCallback()
00642 
00643     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00644     Created:    31/10/2005
00645 
00646     Purpose:    Destructor
00647 
00648 ****************************************************************************/
00649 
00650 XPFRenderCallback::~XPFRenderCallback()
00651 {
00652     m_ConvertList.DeleteAll();
00653     m_ParentList.DeleteAll();
00654 }
00655 
00656 
00657 
00658 /****************************************************************************
00659 
00660 >   BOOL XPFRenderCallback::BeforeNode(RenderRegion* pRegion, Node* pNode)
00661 
00662     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00663     Created:    31/10/2005
00664 
00665     Inputs:     pRegion     - pointer to a RenderRegion
00666                 pNode       - pointer to a Node
00667     Returns:    TRUE if ok, FALSE if bother
00668     Purpose:    
00669 
00670 ****************************************************************************/
00671 
00672 BOOL XPFRenderCallback::BeforeNode(RenderRegion* pRegion, Node* pNode)
00673 {
00674 //  TRACEUSER( "Gerry", _T("XPFRC# BeforeNode    0x%08x - %s\n"), pNode, pNode->GetRuntimeClass()->m_lpszClassName);
00675 
00676     if (pNode->IsNodeHidden() || pNode->IsAnInsertionNode())
00677         return(FALSE);
00678 
00679     // Move code for each pass into separate functions
00680     switch (m_ConvertPass)
00681     {
00682         case 1:
00683         {
00684             // All of the children of pNode have been passed to BeforeSubtree and BeforeNode
00685             if (m_Direction == FIRSTCHILD)
00686             {
00687 //              TRACEUSER( "Gerry", _T("XPFRC# Was child, attach next node as sibling of %s\n"), m_pContextNode->GetRuntimeClass()->m_lpszClassName);
00688                 // If the next node will be attached as first child then set it to attach as
00689                 // as next sibling instead
00690                 m_Direction = NEXT;
00691             }
00692             else if (m_Direction == NEXT)
00693             {
00694                 // If already set to next sibling then set the context node to its parent
00695                 m_pContextNode = m_pContextNode->FindParent();
00696 //              TRACEUSER( "Gerry", _T("XPFRC# Was next, attach next node as sibling of %s\n"), m_pContextNode->GetRuntimeClass()->m_lpszClassName);
00697             }
00698         }
00699         break;
00700 
00701         case 2:
00702         {
00703             // If the node is a renderable object but not a compound then get the conversion type for pass 2
00704             if (pNode->IsAnObject() && !pNode->IsCompound())
00705             {
00706                 // Get the convert type of this node
00707                 XPFConvertType ConvertType = m_pCapTree->GetConvertTypePass2(pNode, m_pXPFRegion);
00708                 
00709                 // If it specifies stroked then set a pending stroked conversion for this node
00710                 if (ConvertType == XPFCONVTYPE_STROKED)
00711                 {
00712 //                  TRACEUSER( "Gerry", _T("XPFRC# Setting pending stroked conversion for %s\n"), pNode->GetRuntimeClass()->m_lpszClassName);
00713                     NodeListItem* pItem = new NodeListItem(pNode);
00714                     m_ConvertList.AddTail(pItem);
00715                 }
00716             }
00717         }
00718         break;
00719 
00720         case 3:
00721         {
00722             // If the node is a renderable object then get the conversion type for pass 2
00723             // This used to also check for non-compund nodes but that breaks group transparency
00724             // It may be necessary to modify GetConvertTypePass3 to correctly distinguish
00725             // compound objects that can and can't support group transparency
00726             if (pNode->IsAnObject())
00727             {
00728                 // Get the convert type of this node
00729                 BOOL bFill = FALSE;
00730                 BOOL bTrans = FALSE;
00731                 BOOL bFillTrans = FALSE;
00732                 m_pCapTree->GetConvertTypePass3(pNode, m_pXPFRegion, &bFill, &bTrans, &bFillTrans);
00733                 
00734                 // If it specifies bitmapfill then set a pending bitmapfill conversion for this node
00735                 if (bFill || bTrans || bFillTrans)
00736                 {
00737 //                  TRACEUSER( "Gerry", _T("XPFRC# Setting pending bitmapfill conversion for %s\n"), pNode->GetRuntimeClass()->m_lpszClassName);
00738                     NodeThreeBoolListItem* pItem = new NodeThreeBoolListItem(pNode, bFill, bTrans, bFillTrans);
00739                     m_ConvertList.AddTail(pItem);
00740                 }
00741             }
00742         }
00743         break;
00744 
00745         case 4:
00746         {
00747             // If the node is a renderable object but not a compound then get the conversion type for pass 4
00748             if (pNode->IsAnObject())
00749             {
00750                 // Get the convert type of this node
00751                 XPFConvertType ConvertType = m_pCapTree->GetConvertTypePass4(pNode, m_pXPFRegion);
00752                 
00753                 // If it specifies bitmap then add the node to the convert list
00754                 if (ConvertType == XPFCONVTYPE_BITMAP)
00755                 {
00756 //                  TRACEUSER( "Gerry", _T("XPFRC# Setting pending bitmap conversion for %s\n"), pNode->GetRuntimeClass()->m_lpszClassName);
00757                     NodeListItem* pItem = new NodeListItem(pNode);
00758                     m_ConvertList.AddTail(pItem);
00759                 }
00760             }
00761         }
00762         break;
00763 
00764         case 5:
00765         {
00766             // If the node is a renderable object then get the conversion type for pass 5
00767             if (pNode->IsAnObject())
00768             {
00769                 // Get the parent
00770                 Node* pParent = pNode->FindParent();
00771 
00772                 // Get the convert type of this node and
00773                 // update the span list appropriately
00774                 XPFConvertType ConvertType = m_pCapTree->GetConvertTypePass5(pNode, m_pXPFRegion);
00775 
00776                 // If this node has children
00777                 if (pNode->FindFirstChild())
00778                 {
00779                     // If this node should be converted
00780                     if (ConvertType == XPFCONVTYPE_BITMAPSPAN)
00781                     {
00782                         // Remove all items from ConvertList that refer to this as the parent
00783                         while (TRUE)
00784                         {
00785                             SpanListItem* pChildSpanItem = (SpanListItem*)m_ConvertList.GetTail();
00786                             if (pChildSpanItem && pChildSpanItem->m_pFirstNode && 
00787                                 pChildSpanItem->m_pFirstNode->FindParent() == pNode)
00788                             {
00789 //                              TRACEUSER( "Gerry", _T("XPFRC# Removing span item for 0x%08x (%s)\n"), pChildSpanItem->m_pFirstNode, pChildSpanItem->m_pFirstNode->GetRuntimeClass()->m_lpszClassName);
00790                                 delete m_ConvertList.RemoveTail();
00791                             }
00792                             else
00793                             {
00794                                 break;
00795                             }
00796                         }
00797                     }
00798                     
00799                     // Get the last item from the parent list
00800                     NodeThreeBoolListItem* pItem = (NodeThreeBoolListItem*)m_ParentList.RemoveTail();
00801 //                  TRACEUSER( "Gerry", _T("XPFRC# Removed parent list item for 0x%08x (%s)\n"), pItem->m_pNode, pItem->m_pNode->GetRuntimeClass()->m_lpszClassName);
00802                     if (pItem)
00803                     {
00804                         // Check to make sure it is the correct one
00805                         if (pItem->m_pNode == pNode)
00806                         {
00807                             // If all the children were complex then
00808                             // we delete the last complex span of the children 
00809                             // and force this node to be treated as complex
00810                             if (pItem->m_bSecond && !(pItem->m_bFirst))
00811                             {
00812                                 SpanListItem* pChildSpanItem = (SpanListItem*)m_ConvertList.GetTail();
00813                                 if (pChildSpanItem && pChildSpanItem->m_pFirstNode &&
00814                                     pChildSpanItem->m_pFirstNode->FindParent() == pNode)
00815                                 {
00816 //                                  TRACEUSER( "Gerry", _T("XPFRC# Removing span item for 0x%08x (%s)\n"), pChildSpanItem->m_pFirstNode, pChildSpanItem->m_pFirstNode->GetRuntimeClass()->m_lpszClassName);
00817                                     delete m_ConvertList.RemoveTail();
00818                                 }
00819                                 // We must reset the parent of the current span here
00820                                 SpanListItem* pCurItem = (SpanListItem*)m_ConvertList.GetTail();
00821                                 // If the last node in the last span was the previous one
00822                                 if (pCurItem && pCurItem->m_pLastNode == pNode->FindPrevious())
00823                                 {
00824                                     // Then we are still in the span at the moment
00825                                     m_pSpanParent = pCurItem->m_pLastNode->FindParent();
00826                                 }
00827                                 else
00828                                 {
00829                                     // Otherwise we aren't in a span at the moment
00830                                     m_pSpanParent = NULL;
00831                                 }
00832 //                              TRACEUSER( "Gerry", _T("XPFRC# Current span parent set to 0x%08x (%s)\n", m_pSpanParent, m_pSpanParent?m_pSpanParent->GetRuntimeClass()->m_lpszClassName:"NULL"));
00833                                 ConvertType = XPFCONVTYPE_BITMAPSPAN;
00834                             }
00835                         }
00836                         delete pItem;
00837                     }
00838                 }
00839 
00840                 // If this node should be in a span
00841                 if (ConvertType == XPFCONVTYPE_BITMAPSPAN)
00842                 {
00843                     SpanListItem* pItem = NULL;
00844                     // If we are currently in a span and the parent is the same
00845                     if (m_pSpanParent == pParent)
00846                     {
00847 //                      TRACEUSER( "Gerry", _T("XPFRC# Adding to current span 0x%08x (%s)\n"), pNode, pNode->GetRuntimeClass()->m_lpszClassName);
00848                         // Make this node the last node in the current span
00849                         pItem = (SpanListItem*)m_ConvertList.GetTail();
00850                         if (pItem)
00851                             pItem->m_pLastNode = pNode;
00852                     }
00853                     else
00854                     {
00855 //                      TRACEUSER( "Gerry", _T("XPFRC# Starting new span with 0x%08x (%s)\n"), pNode, pNode->GetRuntimeClass()->m_lpszClassName);
00856                         // Make this node the first node in a new span
00857                         pItem = new SpanListItem(pNode);
00858                         m_ConvertList.AddTail(pItem);
00859                         m_pSpanParent = pParent;
00860                     }
00861 
00862                     // If this span doesn't have non-alpha transparency yet
00863                     if (!pItem->m_bNonAlphaTrans)
00864                     {
00865                         // Check the current attributes in the render region for
00866                         // non-alpha transparency types
00867                         StrokeTranspAttribute* pStroke = (StrokeTranspAttribute*)(pRegion->GetCurrentAttribute(ATTR_STROKETRANSP));
00868                         UINT32 Type = pStroke->GetTranspType();
00869                         if (Type != TT_NoTranspType &&
00870                             Type != TT_Mix &&
00871                             Type != TT_DARKEN &&
00872                             Type != TT_LIGHTEN &&
00873                             Type != TT_BRIGHTNESS &&
00874                             Type != TT_BEVEL)
00875                         {
00876 //                          TRACEUSER( "Gerry", _T("XPFRC# Found non-alpha stroke transparency\n"));
00877                             pItem->m_bNonAlphaTrans = TRUE;
00878                         }
00879                         
00880                         if (!pItem->m_bNonAlphaTrans)
00881                         {
00882                             TranspFillAttribute* pFill = (TranspFillAttribute*)(pRegion->GetCurrentAttribute(ATTR_TRANSPFILLGEOMETRY));
00883                             UINT32 Type = pFill->GetTranspType();
00884                             if (Type != TT_NoTranspType &&
00885                                 Type != TT_Mix &&
00886                                 Type != TT_DARKEN &&
00887                                 Type != TT_LIGHTEN &&
00888                                 Type != TT_BRIGHTNESS &&
00889                                 Type != TT_BEVEL)
00890                             {
00891 //                              TRACEUSER( "Gerry", _T("XPFRC# Found non-alpha fill transparency\n"));
00892                                 pItem->m_bNonAlphaTrans = TRUE;
00893                             }
00894                         }
00895                     }
00896                 }
00897                 else
00898                 {
00899 //                  TRACEUSER( "Gerry", _T("XPFRC# Stopping current span\n"));
00900                     // Stop the current span
00901                     m_pSpanParent = NULL;
00902                 }
00903 
00904                 NodeThreeBoolListItem* pParentItem = (NodeThreeBoolListItem*)m_ParentList.GetTail();
00905                 if (pParentItem)
00906                 {
00907                     if (ConvertType == XPFCONVTYPE_BITMAPSPAN)
00908                         pParentItem->m_bSecond = TRUE;
00909                     else
00910                         pParentItem->m_bFirst = TRUE;
00911                 }
00912             }
00913         }
00914         break;
00915 
00916         default:
00917         {
00918             TRACEUSER( "Gerry", _T("Unimplemented Pass (%d)\n"), m_ConvertPass);
00919         }
00920         break;
00921     }
00922     
00923     return(TRUE);
00924 }
00925 
00926 
00927 
00928 /****************************************************************************
00929 
00930 >   BOOL XPFRenderCallback::BeforeSubtree(RenderRegion* pRegion, Node* pNode, Node** ppNextNode, BOOL bClip, SubtreeRenderState* pState)
00931 
00932     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00933     Created:    31/10/2005
00934 
00935     Inputs:     pRegion     - pointer to a RenderRegion
00936                 pNode       - pointer to a Node
00937                 ppNextNode  - pointer to a pointer to a Node
00938                 bClip       - 
00939                 pState      - pointer to a SubtreeRenderState
00940     Returns:    TRUE if ok, FALSE if bother
00941     Purpose:    
00942 
00943 ****************************************************************************/
00944 
00945 BOOL XPFRenderCallback::BeforeSubtree(RenderRegion* pRegion, Node* pNode, Node** ppNextNode, BOOL bClip, SubtreeRenderState* pState)
00946 {
00947 //  if (pNode->FindFirstChild())
00948 //  {
00949 //      TRACEUSER( "Gerry", _T("XPFRC# BeforeSubtree 0x%08x - %s\n"), pNode, pNode->GetRuntimeClass()->m_lpszClassName);
00950 //  }
00951 
00952     if (pNode->IsNodeHidden() || pNode->IsAnInsertionNode())
00953         return(FALSE);
00954 
00955     BOOL ok;
00956     BOOL bSetState = TRUE;
00957     SubtreeRenderState RenderState = SUBTREE_ROOTANDCHILDREN;
00958 
00959     // Move code for each pass into separate functions
00960     switch (m_ConvertPass)
00961     {
00962         case 1:
00963         {
00964             // If we are doing selection only, this node is an object 
00965             // and this node is not selected and doesn't have a selected 
00966             // parent or child then skip it
00967             if (m_pCapTree->GetSelection() && pNode->IsAnObject() && 
00968                 !(pNode->IsChildOfSelected() || pNode->HasSelectedChildren()))
00969             {
00970                 RenderState = SUBTREE_NORENDER;
00971                 bSetState = TRUE;
00972             }
00973             else
00974             {
00975                 // This pass can handle native, simple, bitmap, reformat and remove conversions
00976                 // Create a copy of the tree doing the relevant conversions on-the-fly
00977                 
00978                 // Get the convert type of this node
00979                 XPFConvertType ConvertType = m_pCapTree->GetConvertTypePass1(pNode, m_pXPFRegion);
00980 
00981                 if (ConvertType == XPFCONVTYPE_NATIVE)
00982                 {
00983                     // If it is native then:
00984                     //  create a shallow copy of the node
00985                     //  attach it at the current context position
00986                     //  update the context to the first child of this node
00987                     //  continue the render into the subtree
00988 
00989                     Node* pNodeToAttach = pNode->PublicCopy();
00990                     // TODOG: Check for NULL
00991 
00992                     // If we have a context node then attach to it otherwise set m_pNewSpread
00993                     if (m_pContextNode)
00994                     {
00995     /*                  if (m_Direction == FIRSTCHILD)
00996                         {
00997                             TRACEUSER( "Gerry", _T("XPFRC# Attaching %s as child of %s\n"), pNodeToAttach->GetRuntimeClass()->m_lpszClassName, m_pContextNode->GetRuntimeClass()->m_lpszClassName);
00998                         }
00999                         else if (m_Direction == LASTCHILD)
01000                         {
01001                             TRACEUSER( "Gerry", _T("XPFRC# Attaching %s as last child of %s\n"), pNodeToAttach->GetRuntimeClass()->m_lpszClassName, m_pContextNode->GetRuntimeClass()->m_lpszClassName);
01002                         }
01003                         else if (m_Direction == NEXT)
01004                         {
01005                             TRACEUSER( "Gerry", _T("XPFRC# Attaching %s as sibling of %s\n"), pNodeToAttach->GetRuntimeClass()->m_lpszClassName, m_pContextNode->GetRuntimeClass()->m_lpszClassName);
01006                         }*/
01007                         pNodeToAttach->AttachNode(m_pContextNode, m_Direction);
01008                     }
01009 
01010                     // Update context node
01011                     m_pContextNode = pNodeToAttach;
01012                     m_Direction = FIRSTCHILD;
01013                 }
01014                 else if (ConvertType == XPFCONVTYPE_SIMPLE)
01015                 {
01016                     // If it is simple then:
01017                     //  create a deep copy of the node
01018                     //  attach it at the current context position
01019                     //  convert it to editable shapes (become a path)
01020                     //  update the context to the next sibling
01021                     //  skip the render of this subtree
01022 
01023                     TRACEUSER( "Gerry", _T("XPFRC# Converting %s to simple\n"), pNode->GetRuntimeClass()->m_lpszClassName);
01024                     // Create a deep copy of this subtree
01025                     Node* pNodeToAttach = NULL;
01026                     ok = pNode->NodeCopy(&pNodeToAttach);
01027                     if (ok && pNodeToAttach)
01028                     {
01029                         // Attach the copy into the output tree
01030     /*                  if (m_Direction == FIRSTCHILD)
01031                         {
01032                             TRACEUSER( "Gerry", _T("XPFRC# Attaching %s as child of %s\n"), pNodeToAttach->GetRuntimeClass()->m_lpszClassName, m_pContextNode->GetRuntimeClass()->m_lpszClassName);
01033                         }
01034                         else if (m_Direction == LASTCHILD)
01035                         {
01036                             TRACEUSER( "Gerry", _T("XPFRC# Attaching %s as last child of %s\n"), pNodeToAttach->GetRuntimeClass()->m_lpszClassName, m_pContextNode->GetRuntimeClass()->m_lpszClassName);
01037                         }
01038                         else if (m_Direction == NEXT)
01039                         {
01040                             TRACEUSER( "Gerry", _T("XPFRC# Attaching %s as sibling of %s\n"), pNodeToAttach->GetRuntimeClass()->m_lpszClassName, m_pContextNode->GetRuntimeClass()->m_lpszClassName);
01041                         }*/
01042                         pNodeToAttach->AttachNode(m_pContextNode, m_Direction);
01043 
01044                         // We must convert this subtree to simple shapes
01045                         BecomeA BecomeAPath(BECOMEA_REPLACE, CC_RUNTIME_CLASS(NodePath), NULL);
01046                         BecomeAPath.SetResultsStayInPlace(TRUE);
01047                         ok = pNodeToAttach->DoBecomeA(&BecomeAPath);
01048     //                  TRACEUSER( "Gerry", _T("BecomeAPath returned %s\n", ok ? "true" : "false"));
01049 
01050                         if (m_Direction == NEXT)
01051                             m_pContextNode = m_pContextNode->FindNext();
01052                         else
01053                             m_pContextNode = m_pContextNode->FindFirstChild();
01054                         m_Direction = NEXT;
01055 
01056                         // And we must skip this subtree
01057                         RenderState = SUBTREE_NORENDER;
01058                         bSetState = TRUE;
01059                     }
01060                 }
01061                 else if (ConvertType == XPFCONVTYPE_BITMAP)
01062                 {
01063                     // If it is bitmap then:
01064                     //  render the node into a new bitmap node
01065                     //  attach it at the current context position
01066                     //  update the context to the next sibling
01067                     //  skip the render of this subtree
01068 
01069                     BOOL bNonAlphaTrans = DoesNodeUseNonAlphaTrans(pNode);
01070                     TRACEUSER("Gerry", _T("XPFRC# Converting %s to bitmap (%s)\n"), pNode->GetRuntimeClass()->m_lpszClassName, bNonAlphaTrans ? _T("NonAlpha") : _T("Alpha"));
01071 
01072                     Node* pNodeToAttach = RenderNodesToBitmap(pNode, pNode, bNonAlphaTrans);
01073                     if (pNodeToAttach)
01074                     {
01075                         // Attach the new node into the output tree
01076     /*                  if (m_Direction == FIRSTCHILD)
01077                         {
01078                             TRACEUSER( "Gerry", _T("XPFRC# Attaching %s as child of %s\n"), pNodeToAttach->GetRuntimeClass()->m_lpszClassName, m_pContextNode->GetRuntimeClass()->m_lpszClassName);
01079                         }
01080                         else if (m_Direction == LASTCHILD)
01081                         {
01082                             TRACEUSER( "Gerry", _T("XPFRC# Attaching %s as last child of %s\n"), pNodeToAttach->GetRuntimeClass()->m_lpszClassName, m_pContextNode->GetRuntimeClass()->m_lpszClassName);
01083                         }
01084                         else if (m_Direction == NEXT)
01085                         {
01086                             TRACEUSER( "Gerry", _T("XPFRC# Attaching %s as sibling of %s\n"), pNodeToAttach->GetRuntimeClass()->m_lpszClassName, m_pContextNode->GetRuntimeClass()->m_lpszClassName);
01087                         }*/
01088                         pNodeToAttach->AttachNode(m_pContextNode, m_Direction);
01089 
01090                         // The next node must be the NEXT sibling of this one
01091                         m_pContextNode = pNodeToAttach;
01092                         m_Direction = NEXT;
01093                     }       
01094                     
01095                     RenderState = SUBTREE_NORENDER;
01096                     bSetState = TRUE;
01097                 }
01098                 else if (ConvertType == XPFCONVTYPE_REFORMAT)
01099                 {
01100                     // If it is reformat then:
01101                     //  create a reformatted copy of the text story
01102                     //  attach it at the current context position
01103                     //  update the context to the next sibling
01104                     //  skip the render of this subtree
01105 
01106                     TRACEUSER( "Gerry", _T("XPFRC# Reformatting %s\n"), pNode->GetRuntimeClass()->m_lpszClassName);
01107 
01108                     Node* pNodeToAttach = NULL;
01109                     if (IS_A(pNode, TextStory))
01110                     {
01111                         // Reformat the copy of the story
01112                         TextStory* pStory = (TextStory*)pNode;
01113                         pNodeToAttach = ReformatTextStory(pStory);
01114                         if (pNodeToAttach)
01115                         {
01116                             pNodeToAttach->AttachNode(m_pContextNode, m_Direction);
01117 
01118                             // Update context node
01119                             m_pContextNode = pNodeToAttach;
01120                             m_Direction = NEXT;
01121                         }
01122                     }
01123 
01124                     RenderState = SUBTREE_NORENDER;
01125                     bSetState = TRUE;
01126                 }
01127                 else if (ConvertType == XPFCONVTYPE_REMOVE)
01128                 {
01129                     // If it is remove then:
01130                     //  skip the render of this subtree
01131 
01132 //                  TRACEUSER( "Gerry", _T("XPFRC# Ignoring %s\n"), pNode->GetRuntimeClass()->m_lpszClassName);
01133                     RenderState = SUBTREE_NORENDER;
01134                     bSetState = TRUE;
01135                 }
01136             }
01137         }
01138         break;
01139 
01140         case 2:
01141         {
01142             // Don't do anything in here for now
01143         }
01144         break;
01145 
01146         case 3:
01147         {
01148             // Don't do anything in here for now
01149         }
01150         break;
01151 
01152         case 4:
01153         {
01154             // Get the convert type of this node
01155             XPFConvertType ConvertType = m_pCapTree->GetConvertTypePass4(pNode, m_pXPFRegion);
01156             // If it specifies bitmap then add the node to the convert list
01157             if (ConvertType == XPFCONVTYPE_BITMAP)
01158             {
01159                 TRACEUSER( "Gerry", _T("XPFRC# Setting pending bitmap conversion for %s\n"), pNode->GetRuntimeClass()->m_lpszClassName);
01160                 NodeListItem* pItem = new NodeListItem(pNode);
01161                 m_ConvertList.AddTail(pItem);
01162                 RenderState = SUBTREE_NORENDER;
01163                 bSetState = TRUE;
01164             }
01165         }
01166         break;
01167 
01168         case 5:
01169         {
01170             // If the node is a renderable object and has children
01171             if (pNode->IsAnObject() && pNode->FindFirstChild())
01172             {
01173 //              TRACEUSER( "Gerry", _T("XPFRC# Creating parent list item for 0x%08x (%s)\n"), pNode, pNode->GetRuntimeClass()->m_lpszClassName);
01174                 // Create a new NodeThreeBoolListItem for this node
01175                 NodeThreeBoolListItem* pItem = new NodeThreeBoolListItem(pNode);
01176                 m_ParentList.AddTail(pItem);
01177             }
01178         }
01179         break;
01180         
01181         default:
01182         {
01183             TRACEUSER( "Gerry", _T("Unimplemented Pass (%d)\n"), m_ConvertPass);
01184         }
01185         break;
01186     }
01187 
01188     if (bSetState)
01189         *pState = RenderState;
01190 
01191     return(bSetState);
01192 }
01193 
01194 
01195 
01196 /****************************************************************************
01197 
01198 >   TextStory* XPFRenderCallback::ReformatTextStory(TextStory* pStory)
01199 
01200     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01201     Created:    31/10/2005
01202 
01203     Inputs:     pStory      - pointer to a TextStory
01204     Returns:    NULL in times of grief
01205     Purpose:    Creates a copy of a TextStory where the copy is manually 
01206                 kerned and only uses left justification
01207 
01208 ****************************************************************************/
01209 
01210 TextStory* XPFRenderCallback::ReformatTextStory(TextStory* pStory)
01211 {
01212     // Create a FormatRegion to track text attributes
01213     FormatRegion FormattingRegion;
01214     if (FormattingRegion.Init(pStory) == FALSE)
01215         return(NULL);
01216 
01217     // Create a copy of the TextStory node
01218     TextStory* pNewStory = (TextStory*)(pStory->PublicCopy());
01219     if (pNewStory == NULL)
01220         return(NULL);
01221 
01222     // Keep track of where we are attaching new nodes
01223     Node* pContextNode = pNewStory;
01224     AttachNodeDirection Direction = FIRSTCHILD;
01225 
01226     // Loop through all the children of the story
01227     Node* pNode = pStory->FindFirstChild();
01228     while (pNode != NULL)
01229     {
01230         Node* pNewNode = NULL;
01231         if (IS_A(pNode, TextLine))              // If it is a TextLine
01232         {
01233             // Then create a reformatted copy
01234             pNewNode = ReformatTextLine((TextLine*)pNode, &FormattingRegion);
01235         }
01236         else if (!pNode->IsNodeHidden())        // Otherwise if it isn't a hidden node
01237         {
01238             // If it is a text attribute then render it into the FormatRegion
01239             if (pNode->IsKindOfTextAttribute())
01240                 pNode->Render(&FormattingRegion);
01241 
01242             // If it isn't a justification or tracking attribute then copy it
01243             if (!IS_A(pNode, AttrTxtJustification) && !IS_A(pNode, AttrTxtTracking))
01244                 pNewNode = pNode->PublicCopy();
01245         }
01246 
01247         // If we created a new node then attach it
01248         if (pNewNode)
01249         {
01250             pNewNode->AttachNode(pContextNode, Direction, FALSE, FALSE);
01251 
01252             // Next node will always be attached as the next sibling of this one
01253             pContextNode = pNewNode;
01254             Direction = NEXT;
01255         }
01256         
01257         pNode = pNode->FindNext();
01258     }
01259 
01260     // Make sure the auto-kerning is turned off
01261     pNewStory->SetAutoKerning(FALSE);
01262 
01263     // May have to cause the new story to reformat itself here
01264 
01265     return(pNewStory);
01266 }
01267 
01268 
01269 
01270 /****************************************************************************
01271 
01272 >   Node* XPFRenderCallback::ReformatTextLine(TextLine* pLineNode, FormatRegion* pFormatRegion)
01273 
01274     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01275     Created:    31/10/2005
01276 
01277     Inputs:     pLineNode   - pointer to a TextLine
01278                 pFormatRegion- pointer to a FormatRegion
01279     Returns:    NULL in times of grief
01280     Purpose:    Creates a left justified and manually kerned copy of a text 
01281                 line by inserting manual kern codes where necessary
01282 
01283 ****************************************************************************/
01284 
01285 Node* XPFRenderCallback::ReformatTextLine(TextLine* pLineNode, FormatRegion* pFormatRegion)
01286 {
01287 //  TRACE( _T("ReformatTextLine 0x%08x\n"), pLineNode);
01288     
01289     BOOL ok = TRUE;
01290 
01291     // Copy the line
01292     Node* pNewRoot = pLineNode->PublicCopy();
01293 
01294     // Kepp track of where we are attaching copies
01295     Node* pContextNode = pNewRoot;
01296     AttachNodeDirection Direction = FIRSTCHILD;
01297 
01298     pFormatRegion->SaveContext();
01299 
01300     // Keep track of the current pos on the line
01301     MILLIPOINT CurrentPosMP = 0;
01302 
01303     // scan immediate children rendering any text attrs, and copying any text nodes
01304     Node* pNode = pLineNode->FindFirstChild();
01305     while (pNode != NULL)
01306     {
01307 //      TRACE( _T("Node at 0x%08x (%s)\n"), pNode, pNode->GetRuntimeClass()->m_lpszClassName);
01308         Node* pNewNode = NULL;
01309         if (pNode->IsAnAbstractTextChar())
01310         {
01311             VisibleTextNode* pVTN=(VisibleTextNode*)pNode;
01312             AbstractTextChar* pATC=(AbstractTextChar*)pNode;
01313 
01314             // Save the context and render all the child text attributes
01315             // into the FormatRegion
01316             pFormatRegion->SaveContext();
01317 
01318             Node* pChildNode = pNode->FindFirstChild();
01319             while (pChildNode != NULL)
01320             {
01321                 if (pChildNode->IsKindOfTextAttribute())
01322                     pChildNode->Render(pFormatRegion);
01323 
01324                 pChildNode = pChildNode->FindNext();
01325             }
01326 
01327             // Get the metrics of the character
01328 //          MILLIPOINT EMWidth = 0;
01329             CharMetrics CharMet;
01330             ok = pFormatRegion->GetCharMetrics(&CharMet, pATC->GetUnicodeValue());
01331 
01332             // If this character isn't a space
01333             // (have to do this or we get problems at the ends of lines)
01334             if (!pVTN->IsASpace())
01335             {
01336                 // Check the line position and insert a KernCode
01337                 MILLIPOINT PosMP = pVTN->GetPosInLine();
01338 //              TRACE( _T("PosInLine = %d\n"), PosMP);
01339 //              TRACE( _T("Current   = %d\n"), CurrentPosMP);
01340                 if (PosMP != CurrentPosMP)                  // If we aren't at the correct position in the line
01341                 {
01342                     // Calculate the required kern width in em/1000
01343                     INT32 PosEM1000 = MulDiv(PosMP - CurrentPosMP, 1000, CharMet.FontEmWidth);
01344 
01345                     // Convert the em/1000 size back to millipoints
01346                     INT32 KernSizeMP = MulDiv(PosEM1000, CharMet.FontEmWidth, 1000);
01347 //                  TRACE( _T("Inserting justify kern of %d\n"), PosMP - CurrentPosMP);
01348 //                  TRACE( _T("Real size %d\n"), KernSizeMP);
01349                     // If the millipoint size is larger than it should be then
01350                     // subtract 1 from the em/1000 size
01351                     if (KernSizeMP > (PosMP - CurrentPosMP))
01352                         PosEM1000 -= 1;
01353 
01354                     // Create and insert a KernCode with the same attributes as pNode
01355                     DocCoord TempCoord(PosEM1000, 0);
01356                     KernCode* pKern = new KernCode(TempCoord);
01357                     if (pKern)
01358                     {
01359                         ok = CopyAttributesFromNode(pKern, pNode);
01360                         pKern->AttachNode(pContextNode, Direction, FALSE, FALSE);
01361                         pContextNode = pKern;
01362                         Direction = NEXT;
01363                     }
01364                     CurrentPosMP = PosMP;
01365                 }
01366             }
01367 
01368 //          TRACE( _T("Inserting node width %d\n"), pATC->GetCharWidth());
01369             // Advance the current pos by the character width (note, not the CharAdvance)
01370             CurrentPosMP += pATC->GetCharWidth();
01371 
01372             // Create a deep copy of this Node
01373             pNewNode = pNode->PublicCopy();
01374             if (pNewNode)
01375             {
01376                 ok = CopyAttributesFromNode(pNewNode, pNode);
01377                 pNewNode->AttachNode(pContextNode, Direction, FALSE, FALSE);
01378                 pContextNode = pNewNode;
01379                 Direction = NEXT;
01380                 pNewNode = NULL;
01381             }
01382 
01383             pFormatRegion->RestoreContext();
01384         }
01385         else if(!pNode->IsNodeHidden())
01386         {
01387             if (pNode->IsKindOfTextAttribute())
01388                 pNode->Render(pFormatRegion);
01389 
01390             if (!IS_A(pNode, AttrTxtJustification) && !IS_A(pNode, AttrTxtTracking))
01391                 pNewNode = pNode->PublicCopy();
01392 
01393             if (pNewNode)
01394             {
01395                 ok = CopyAttributesFromNode(pNewNode, pNode);
01396                 pNewNode->AttachNode(pContextNode, Direction, FALSE, FALSE);
01397                 pContextNode = pNewNode;
01398                 Direction = NEXT;
01399             }
01400         }
01401 
01402         pNode = pNode->FindNext();
01403     }
01404 
01405     pFormatRegion->RestoreContext();
01406 
01407     return(pNewRoot);
01408 }
01409 
01410 
01411 
01412 /****************************************************************************
01413 
01414 >   BOOL XPFRenderCallback::CopyAttributesFromNode(Node* pDestNode, Node* pSrcNode)
01415 
01416     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01417     Created:    31/10/2005
01418 
01419     Inputs:     pDestNode   - pointer to a Node
01420                 pSrcNode    - pointer to a Node
01421     Returns:    TRUE if ok, FALSE if bother
01422     Purpose:    Copies all attributes except justification and tracking 
01423                 from one node to another
01424 
01425 ****************************************************************************/
01426 
01427 BOOL XPFRenderCallback::CopyAttributesFromNode(Node* pDestNode, Node* pSrcNode)
01428 {
01429     Node* pChildNode = pSrcNode->FindFirstChild();
01430     Node* pContextNode = pDestNode;
01431     AttachNodeDirection Direction = FIRSTCHILD;
01432     while (pChildNode)
01433     {
01434         if (!pChildNode->IsNodeHidden() && !IS_A(pChildNode, AttrTxtJustification) && !IS_A(pChildNode, AttrTxtTracking))
01435         {
01436             Node* pNewChild = pChildNode->PublicCopy();     
01437             if (pNewChild)
01438             {
01439                 pNewChild->AttachNode(pContextNode, Direction, FALSE, FALSE);
01440                 pContextNode = pNewChild;
01441                 Direction = NEXT;
01442             }
01443         }
01444 
01445         pChildNode = pChildNode->FindNext();
01446     }
01447 
01448     return(TRUE);
01449 }
01450 
01451 
01452 
01453 /****************************************************************************
01454 
01455 >   void XPFRenderCallback::RemoveChildAttrs(Node* pNode, CCRuntimeClass* pClass)
01456 
01457     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01458     Created:    31/10/2005
01459 
01460     Inputs:     pNode       - pointer to a Node
01461                 pClass      - pointer to a CCRuntimeClass
01462     Purpose:    Removes all child attributes of a particular attribute type
01463 
01464 ****************************************************************************/
01465 
01466 void XPFRenderCallback::RemoveChildAttrs(Node* pNode, CCRuntimeClass* pClass)
01467 {
01468     Node* pChild = pNode->FindFirstChild();
01469     while (pChild)
01470     {
01471         Node* pNextChild = pChild->FindNext();
01472         if (pChild->IsAnAttribute())
01473         {
01474             NodeAttribute* pAttr = (NodeAttribute*)pChild;
01475             if (pAttr->GetAttributeType() == pClass)
01476             {
01477                 pChild->CascadeDelete();
01478                 delete pChild;
01479             }
01480         }
01481         pChild = pNextChild;
01482     }
01483 }
01484 
01485 
01486 
01487 /****************************************************************************
01488 
01489 >   NodeAttribute* XPFRenderCallback::FindChildAttr(Node* pNode, CCRuntimeClass* pClass)
01490 
01491     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01492     Created:    31/10/2005
01493 
01494     Inputs:     pNode       - pointer to a Node
01495                 pClass      - pointer to a CCRuntimeClass
01496     Returns:    NULL in times of grief
01497     Purpose:    Finds the last child attr of the specified attribute type
01498 
01499 ****************************************************************************/
01500 
01501 NodeAttribute* XPFRenderCallback::FindChildAttr(Node* pNode, CCRuntimeClass* pClass)
01502 {
01503     Node* pChild = pNode->FindLastChild();
01504     while (pChild)
01505     {
01506         if (pChild->IsAnAttribute())
01507         {
01508             NodeAttribute* pAttr = (NodeAttribute*)pChild;
01509             if (pAttr->GetAttributeType() == pClass)
01510             {
01511                 return(pAttr);
01512             }
01513         }
01514         pChild = pChild->FindPrevious();
01515     }
01516     return(NULL);
01517 }
01518 
01519 
01520 
01521 /****************************************************************************
01522 
01523 >   BOOL XPFRenderCallback::DoesNodeUseNonAlphaTrans(Node* pRootNode)
01524 
01525     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01526     Created:    31/10/2005
01527 
01528     Inputs:     pRootNode   - pointer to a Node
01529     Returns:    TRUE if ok, FALSE if bother
01530     Purpose:    Determines if a node has any attributes that use non-alpha 
01531                 transparency
01532 
01533 ****************************************************************************/
01534 
01535 BOOL XPFRenderCallback::DoesNodeUseNonAlphaTrans(Node* pRootNode)
01536 {
01537     // This function determines if the specified node uses any non-alpha compatible 
01538     // transparency types (anywhere in its subtree)
01539 
01540     // If this isn't a renderable ink node then get out
01541     // It might be a layer or spread which are paper nodes!
01542 //  if (!pRootNode->IS_KIND_OF(NodeRenderableInk))
01543 //      return(FALSE);
01544 
01545     if (pRootNode->IsAnObject())
01546     {
01547         NodeRenderableInk* pInkNode = (NodeRenderableInk*)pRootNode;
01548         // Basically, it just needs to check any transparency attributes
01549         // First it needs to check the attributes applied above this node in the tree
01550 
01551         AttrStrokeTransp* pStrkAttr = (AttrStrokeTransp*)(pInkNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeTransp), TRUE));
01552         if (pStrkAttr)
01553         {
01554             UINT32 Type = pStrkAttr->GetTranspType();
01555             if (Type != TT_NoTranspType &&
01556                 Type != TT_Mix &&
01557                 Type != TT_DARKEN &&
01558                 Type != TT_LIGHTEN &&
01559                 Type != TT_BRIGHTNESS &&
01560                 Type != TT_BEVEL)
01561             {
01562                 return(TRUE);
01563             }
01564         }
01565 
01566         AttrFillGeometry* pFillAttr = (AttrFillGeometry*)(pInkNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrTranspFillGeometry), TRUE));
01567         if (pFillAttr)
01568         {
01569             UINT32 Type = pFillAttr->GetTranspType();
01570             if (Type != TT_NoTranspType &&
01571                 Type != TT_Mix &&
01572                 Type != TT_DARKEN &&
01573                 Type != TT_LIGHTEN &&
01574                 Type != TT_BRIGHTNESS &&
01575                 Type != TT_BEVEL)
01576             {
01577                 return(TRUE);
01578             }
01579         }
01580     }
01581 
01582     // Now we scan through the tree looking for all AttrFillGeometry nodes
01583     Node* pNode = pRootNode->FindFirstDepthFirst();
01584     while (pNode)
01585     {
01586         // Check this node
01587         if (pNode->IsAnAttribute() && pNode->IS_KIND_OF(AttrFillGeometry))
01588         {
01589             AttrFillGeometry* pAttr = (AttrFillGeometry*)pNode;
01590             UINT32 Type = pAttr->GetTranspType();
01591             if (Type != TT_NoTranspType &&
01592                 Type != TT_Mix &&
01593                 Type != TT_DARKEN &&
01594                 Type != TT_LIGHTEN &&
01595                 Type != TT_BRIGHTNESS &&
01596                 Type != TT_BEVEL)
01597             {
01598                 return(TRUE);
01599             }
01600         }
01601 
01602         // Move on to the next node
01603         pNode = pNode->FindNextDepthFirst(pRootNode);
01604     }
01605 
01606     return(FALSE);
01607 }
01608 
01609 
01610 
01611 /****************************************************************************
01612 
01613 >   BOOL XPFRenderCallback::ConvertNodes()
01614 
01615     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01616     Created:    31/10/2005
01617 
01618     Returns:    TRUE if ok, FALSE if bother
01619     Purpose:    Performs the required conversion on the stored list of nodes
01620 
01621 ****************************************************************************/
01622 
01623 BOOL XPFRenderCallback::ConvertNodes()
01624 {
01625     BOOL ok = TRUE;
01626     switch (m_ConvertPass)
01627     {
01628         case 2:
01629             ok = ConvertNodesForPass2();
01630             break;
01631 
01632         case 3:
01633             ok = ConvertNodesForPass3();
01634             break;
01635 
01636         case 4:
01637             ok = ConvertNodesForPass4();
01638             break;
01639 
01640         case 5:
01641             ok = ConvertNodesForPass5();
01642             break;
01643 
01644         default:
01645             break;
01646     }
01647 
01648     // And empty the list
01649     m_ConvertList.DeleteAll();
01650 
01651     return(ok);
01652 }
01653 
01654 
01655 
01656 /****************************************************************************
01657 
01658 >   BOOL XPFRenderCallback::ConvertNodesForPass2()
01659 
01660     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01661     Created:    31/10/2005
01662 
01663     Returns:    TRUE if ok, FALSE if bother
01664     Purpose:    Performs the "stroked" conversion on the convert list
01665 
01666 ****************************************************************************/
01667 
01668 BOOL XPFRenderCallback::ConvertNodesForPass2()
01669 {
01670     TRACEUSER( "Gerry", _T("ConvertNodesForPass2 (%d)\n"), m_ConvertList.GetCount());
01671 
01672     double dProgress = 0.0;
01673     double dInc = 100.0 / (double)m_ConvertList.GetCount();
01674 
01675     BOOL ok = TRUE;
01676     NodeListItem* pItem = (NodeListItem*)m_ConvertList.GetHead();
01677     while (pItem)
01678     {
01679         Node* pNode = pItem->pNode;
01680         NodeRenderableInk* pInkNode = (NodeRenderableInk*)pNode;
01681 
01682         TRACEUSER( "Gerry", _T("ConvertStroked 0x%08x (%s) \n"), pNode, pNode->GetRuntimeClass()->m_lpszClassName);
01683 
01684         // First we need to check if there is any line colour on the object
01685         // If there isn't then we don't do anything
01686         NodeAttribute* pStrokeCol = NULL;
01687         pInkNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeColour), &pStrokeCol);
01688         if (pStrokeCol && !((AttrStrokeColour*)pStrokeCol)->Value.GetStartColour()->IsTransparent())
01689         {
01690             // Now we need to check if there is any fill on this object.
01691             // If there is then we need to create a group to represent this node
01692             // This will hold this node with the stroke attributes removed and 
01693             // a copy of this node to represent the stroke which will have the 
01694             // conversion done on it
01695             // Otherwise we can just do the conversion on the original node
01696 
01697             BOOL bHasFill = TRUE;
01698             if (pNode->IsKindOf(CC_RUNTIME_CLASS(NodePath)))
01699             {
01700                 NodePath* pPath = (NodePath*)pNode;
01701                 if (!pPath->InkPath.IsFilled)
01702                     bHasFill = FALSE;
01703             }
01704 
01705             if (bHasFill)
01706             {
01707                 NodeAttribute* pAppliedAttr = NULL;
01708                 pInkNode->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillGeometry), &pAppliedAttr);
01709                 if (pAppliedAttr != NULL && IS_A(pAppliedAttr, AttrFlatColourFill))
01710                 {
01711                     DocColour* pLineColour = ((AttrFlatColourFill*)pAppliedAttr)->GetStartColour();
01712                     if (pLineColour != NULL)
01713                         if (pLineColour->IsTransparent())
01714                             bHasFill = FALSE;
01715                 }
01716             }
01717 
01718             if (bHasFill)
01719             {
01720                 // Create a group node and insert it into the tree as next
01721                 NodeGroup* pGroup = new NodeGroup(pNode, NEXT);
01722                 if (pGroup == NULL)
01723                 {
01724                     // Set the error
01725                     return(FALSE);
01726                 }
01727 
01728                 Node* pFillNode = NULL;
01729 
01730                 // Create a copy of the node and attach it as first child of the group
01731                 ok = pNode->NodeCopy((Node**)&pFillNode);
01732                 if (!ok)
01733                 {
01734                     // Set the error
01735                     return(ok);
01736                 }
01737 
01738                 pFillNode->AttachNode(pGroup, FIRSTCHILD);
01739 
01740                 // Move the node to convert to be next sibling of the copy
01741                 pNode->MoveNode(pFillNode, NEXT);
01742 
01743                 // Convert the node
01744                 ok = OpConvertPathToShapes::ConvertPathToShapes(NULL, (NodeRenderableInk*)pNode);
01745                 TRACEUSER( "Gerry", _T("ConvertPathToShapes returned %s\n"), ok ? _T("true") : _T("false"));
01746                 if (!ok)
01747                 {
01748                     // Report error
01749                     return(ok);
01750                 }
01751 
01752                 // Remove the stroke attributes from the fill object
01753                 pGroup->LocaliseCommonAttributes(FALSE, TRUE, NULL);
01754 
01755                 // Remove all the stroke based attributes
01756                 RemoveChildAttrs(pFillNode, CC_RUNTIME_CLASS(AttrStrokeColour));
01757                 RemoveChildAttrs(pFillNode, CC_RUNTIME_CLASS(AttrStrokeTransp));
01758                 RemoveChildAttrs(pFillNode, CC_RUNTIME_CLASS(AttrDashPattern));
01759                 RemoveChildAttrs(pFillNode, CC_RUNTIME_CLASS(AttrStartArrow));
01760                 RemoveChildAttrs(pFillNode, CC_RUNTIME_CLASS(AttrEndArrow));
01761                 RemoveChildAttrs(pFillNode, CC_RUNTIME_CLASS(AttrStartCap));
01762                 RemoveChildAttrs(pFillNode, CC_RUNTIME_CLASS(AttrLineWidth));
01763                 RemoveChildAttrs(pFillNode, CC_RUNTIME_CLASS(AttrVariableWidth));
01764                 RemoveChildAttrs(pFillNode, CC_RUNTIME_CLASS(AttrBrushType));
01765                 RemoveChildAttrs(pFillNode, CC_RUNTIME_CLASS(AttrStrokeType));
01766 
01767                 // Apply a no stroke colour attribute
01768                 AttrStrokeColour* pTranspAttr = new AttrStrokeColour(pFillNode, FIRSTCHILD);
01769                 if (pTranspAttr)
01770                 {
01771                     StrokeColourAttribute* pTranspVal = (StrokeColourAttribute*)(pTranspAttr->GetAttributeValue());
01772                     pTranspVal->Colour = DocColour(COLOUR_NONE);
01773                 }
01774 
01775                 pGroup->FactorOutCommonChildAttributes(TRUE, (AttrTypeSet*)NULL);
01776             }
01777             else
01778             {
01779                 ok = OpConvertPathToShapes::ConvertPathToShapes(NULL, (NodeRenderableInk*)pNode);
01780                 TRACEUSER( "Gerry", _T("ConvertPathToShapes returned %s\n"), ok ? _T("true") : _T("false"));
01781                 if (!ok)
01782                 {
01783                     return(ok);
01784                 }
01785             }
01786         }
01787         else
01788         {
01789             TRACEUSER( "Gerry", _T("No line colour\n"));
01790         }
01791 
01792         // Get the next span item
01793         pItem = (NodeListItem*)m_ConvertList.GetNext(pItem);
01794 
01795         dProgress += dInc;
01796         if (!m_pFilter->SetProgressBarCount((UINT32)dProgress))
01797         {
01798             Error::SetError(_R(IDN_USER_CANCELLED),0);          // Expects error set
01799             return(FALSE);
01800         }
01801     }
01802 
01803     return(TRUE);
01804 }
01805 
01806 
01807 
01808 /****************************************************************************
01809 
01810 >   BOOL XPFRenderCallback::ConvertNodesForPass3()
01811 
01812     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01813     Created:    31/10/2005
01814 
01815     Returns:    TRUE if ok, FALSE if bother
01816     Purpose:    Performs the bitmapfill, bitmaptrans and bitmapfilltrans 
01817                 conversions on the convert list
01818 
01819 ****************************************************************************/
01820 
01821 BOOL XPFRenderCallback::ConvertNodesForPass3()
01822 {
01823     TRACEUSER( "Gerry", _T("ConvertNodesForPass3 (%d)\n"), m_ConvertList.GetCount());
01824 
01825     double dProgress = 0.0;
01826     double dInc = 100.0 / (double)m_ConvertList.GetCount();
01827 
01828     NodeCompound* pLastParent = NULL;
01829     NodeThreeBoolListItem* pItem = (NodeThreeBoolListItem*)m_ConvertList.GetHead();
01830     while (pItem)
01831     {
01832         TRACEUSER( "Gerry", _T("ConvertFillAttrs 0x%08x (%s) %s%s\n"), pItem->m_pNode, pItem->m_pNode->GetRuntimeClass()->m_lpszClassName, pItem->m_bFirst ? _T("fill ") : _T(""), pItem->m_bSecond ? _T("trans") : _T(""));
01833         Node* pNode = pItem->m_pNode;
01834         Node* pParentNode = pNode->FindParent();
01835         ERROR2IF(!pParentNode, FALSE, "Node has no parent in ConvertNodesForPass3");
01836 
01837         NodeCompound* pParent = NULL;
01838         if (pParentNode->IsCompound())
01839         {
01840             pParent = (NodeCompound*)pParentNode;
01841             if (pParent != pLastParent)
01842             {
01843                 if (pLastParent)
01844                     pLastParent->FactorOutCommonChildAttributes(TRUE, (AttrTypeSet*)NULL);
01845 
01846                 pParent->LocaliseCommonAttributes(TRUE, TRUE, NULL);
01847                 pLastParent = pParent;
01848             }
01849         }
01850 
01851         NodeRenderableBounded* pTheNode = (NodeRenderableBounded*)pNode;
01852         DocRect BoundsRect = pTheNode->GetBoundingRect(TRUE, FALSE);
01853 
01854         if (pItem->m_bThird)
01855         {
01856             // We need to combine the fill and transparency into a bitmap fill
01857             // and then create a bitmap fill attribute to replace the existing fill with
01858             // All of the fill attributes must be set to sensible values
01859             KernelBitmap* pBmp = RenderFillAndTransToBitmap(pNode, BoundsRect);
01860             if (!pBmp)
01861                 return(FALSE);
01862 
01863             // Remove any existing fill and transparency attributes
01864             RemoveChildAttrs(pNode, CC_RUNTIME_CLASS(AttrFillGeometry));
01865             RemoveChildAttrs(pNode, CC_RUNTIME_CLASS(AttrFillMapping));
01866             RemoveChildAttrs(pNode, CC_RUNTIME_CLASS(AttrFillEffect));
01867             RemoveChildAttrs(pNode, CC_RUNTIME_CLASS(AttrTranspFillMapping));
01868             RemoveChildAttrs(pNode, CC_RUNTIME_CLASS(AttrTranspFillGeometry));
01869 
01870             // Apply a bitmap fill
01871             AttrBitmapColourFill* pBmpFill = new AttrBitmapColourFill(pNode, FIRSTCHILD);
01872             if (!pBmpFill)
01873             {
01874                 delete pBmp;
01875                 return(FALSE);
01876             }
01877 
01878             BitmapFillAttribute* pBmpVal = (BitmapFillAttribute*)(pBmpFill->GetAttributeValue());
01879             pBmpVal->BitmapRef.Attach(pBmp);
01880             DocCoord BottomLeft(BoundsRect.lo);
01881             DocCoord BottomRight(BoundsRect.hi.x, BoundsRect.lo.y);
01882             DocCoord TopLeft(BoundsRect.lo.x, BoundsRect.hi.y);
01883             pBmpVal->SetStartPoint(&BottomLeft);
01884             pBmpVal->SetEndPoint(&BottomRight);
01885             pBmpVal->SetEndPoint2(&TopLeft);
01886 
01887             // Apply a simple fill mapping
01888             AttrFillMappingLinear* pFillMap = new AttrFillMappingLinear(pNode, FIRSTCHILD);
01889             if (!pFillMap)
01890             {
01891                 delete pBmpFill;
01892                 return(FALSE);
01893             }
01894 
01895             FillMappingLinearAttribute* pMapVal = (FillMappingLinearAttribute*)(pFillMap->GetAttributeValue());
01896             pMapVal->Repeat = 1;    // Set no repeat
01897         }
01898         else
01899         {
01900             if (pItem->m_bFirst)
01901             {
01902                 // We need to render the fill of the object into a bitmap ignoring any transparency
01903                 // and then create a bitmap fill attribute to replace the existing fill with
01904                 // All of the fill attributes must be set to sensible values
01905                 KernelBitmap* pBmp = RenderFillToBitmap(pNode, BoundsRect);
01906                 if (!pBmp)
01907                     return(FALSE);
01908 
01909                 // Remove any existing fill attributes
01910                 RemoveChildAttrs(pNode, CC_RUNTIME_CLASS(AttrFillGeometry));
01911                 RemoveChildAttrs(pNode, CC_RUNTIME_CLASS(AttrFillMapping));
01912                 RemoveChildAttrs(pNode, CC_RUNTIME_CLASS(AttrFillEffect));
01913 
01914                 // Apply a bitmap fill
01915                 AttrBitmapColourFill* pBmpFill = new AttrBitmapColourFill(pNode, FIRSTCHILD);
01916                 if (!pBmpFill)
01917                 {
01918                     delete pBmp;
01919                     return(FALSE);
01920                 }
01921 
01922                 BitmapFillAttribute* pBmpVal = (BitmapFillAttribute*)(pBmpFill->GetAttributeValue());
01923                 pBmpVal->BitmapRef.Attach(pBmp);
01924                 DocCoord BottomLeft(BoundsRect.lo);
01925                 DocCoord BottomRight(BoundsRect.hi.x, BoundsRect.lo.y);
01926                 DocCoord TopLeft(BoundsRect.lo.x, BoundsRect.hi.y);
01927                 pBmpVal->SetStartPoint(&BottomLeft);
01928                 pBmpVal->SetEndPoint(&BottomRight);
01929                 pBmpVal->SetEndPoint2(&TopLeft);
01930 
01931                 // Apply a simple fill mapping
01932                 AttrFillMappingLinear* pFillMap = new AttrFillMappingLinear(pNode, FIRSTCHILD);
01933                 if (!pFillMap)
01934                 {
01935                     delete pBmpFill;
01936                     return(FALSE);
01937                 }
01938 
01939                 FillMappingLinearAttribute* pMapVal = (FillMappingLinearAttribute*)(pFillMap->GetAttributeValue());
01940                 pMapVal->Repeat = 1;    // Set no repeat
01941             }
01942 
01943             if (pItem->m_bSecond)
01944             {
01945                 // We need to render the transparency of the object as a greyscale graduated fill 
01946                 // and then create a bitmap transparency attribute to replace the existing one with
01947                 // All of the transparency attributes must be set to sensible values
01948 
01949                 UINT32 TransType = 0;
01950                 KernelBitmap* pBmp = RenderTransToBitmap(pNode, BoundsRect, &TransType);
01951                 if (!pBmp)
01952                     return(FALSE);
01953 
01954                 // Find the last child AttrTranspFillGeometry
01955                 // Apply a bitmap transparency as the next node to the one found
01956                 NodeAttribute* pOldGeometry = FindChildAttr(pNode, CC_RUNTIME_CLASS(AttrTranspFillGeometry));
01957 
01958                 // Apply a bitmap transparency
01959                 AttrBitmapTranspFill* pBmpTrans = NULL;
01960                 if (pOldGeometry)
01961                     pBmpTrans = new AttrBitmapTranspFill(pOldGeometry, NEXT);
01962                 else
01963                     pBmpTrans = new AttrBitmapTranspFill(pNode, FIRSTCHILD);
01964                 if (!pBmpTrans)
01965                 {
01966                     delete pBmp;
01967                     return(FALSE);
01968                 }
01969 
01970                 BitmapTranspFillAttribute* pBmpVal = (BitmapTranspFillAttribute*)(pBmpTrans->GetAttributeValue());
01971                 pBmpVal->BitmapRef.Attach(pBmp);
01972                 DocCoord BottomLeft(BoundsRect.lo);
01973                 DocCoord BottomRight(BoundsRect.hi.x, BoundsRect.lo.y);
01974                 DocCoord TopLeft(BoundsRect.lo.x, BoundsRect.hi.y);
01975                 pBmpVal->SetStartPoint(&BottomLeft);
01976                 pBmpVal->SetEndPoint(&BottomRight);
01977                 pBmpVal->SetEndPoint2(&TopLeft);
01978                 UINT32 Val = 0;
01979                 pBmpVal->SetStartTransp(&Val);
01980                 Val = 255;
01981                 pBmpVal->SetEndTransp(&Val);
01982                 pBmpVal->SetTranspType(TransType);
01983 
01984                 // Find the last child AttrTranspFillMappingLinear
01985                 NodeAttribute* pOldMapping = FindChildAttr(pNode, CC_RUNTIME_CLASS(AttrTranspFillMapping));
01986 
01987                 // If we have found an old geometry attr
01988                 if (pOldGeometry)
01989                 {
01990                     // And we have found an old mapping attr and they don't match Effects
01991                     if (pOldMapping && pOldMapping->IsEffectAttribute() != pOldGeometry->IsEffectAttribute())
01992                         pOldMapping = NULL;     // Flag that we haven't found an old mapping
01993                 }
01994 
01995                 // Apply a simple fill mapping
01996                 AttrTranspFillMappingLinear* pTransMap = NULL;
01997                 if (pOldMapping)
01998                     pTransMap = new AttrTranspFillMappingLinear(pOldMapping, NEXT);
01999                 else if (pOldGeometry)
02000                     pTransMap = new AttrTranspFillMappingLinear(pOldGeometry, NEXT);
02001                 else
02002                     pTransMap = new AttrTranspFillMappingLinear(pNode, FIRSTCHILD);
02003                 if (!pTransMap)
02004                 {
02005                     delete pBmpTrans;
02006                     return(FALSE);
02007                 }
02008 
02009                 TranspFillMappingLinearAttribute* pMapVal = (TranspFillMappingLinearAttribute*)(pTransMap->GetAttributeValue());
02010                 pMapVal->Repeat = 1;    // Set no repeat
02011 
02012                 // Delete the old attributes
02013                 if (pOldGeometry)
02014                 {
02015                     pOldGeometry->CascadeDelete();
02016                     delete pOldGeometry;
02017                 }
02018                 if (pOldMapping)
02019                 {
02020                     pOldMapping->CascadeDelete();
02021                     delete pOldMapping;
02022                 }
02023             }
02024         }
02025 
02026         dProgress += dInc;
02027         if (!m_pFilter->SetProgressBarCount((UINT32)dProgress))
02028         {
02029             Error::SetError(_R(IDN_USER_CANCELLED),0);          // Expects error set
02030             return(FALSE);
02031         }
02032 
02033         pItem = (NodeThreeBoolListItem*)m_ConvertList.GetNext(pItem);
02034     }
02035 
02036     if (pLastParent)
02037         pLastParent->FactorOutCommonChildAttributes(TRUE, (AttrTypeSet*)NULL);
02038 
02039     return(TRUE);
02040 }
02041 
02042 
02043 
02044 /****************************************************************************
02045 
02046 >   BOOL XPFRenderCallback::ConvertNodesForPass4()
02047 
02048     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
02049     Created:    31/10/2005
02050 
02051     Returns:    TRUE if ok, FALSE if bother
02052     Purpose:    Performs the bitmap conversion on the convert list
02053 
02054 ****************************************************************************/
02055 
02056 BOOL XPFRenderCallback::ConvertNodesForPass4()
02057 {
02058     TRACEUSER( "Gerry", _T("ConvertNodesForPass4 (%d)\n"), m_ConvertList.GetCount());
02059 
02060     double dProgress = 0.0;
02061     double dInc = 100.0 / (double)m_ConvertList.GetCount();
02062 
02063     NodeListItem* pItem = (NodeListItem*)m_ConvertList.GetHead();
02064     while (pItem)
02065     {
02066         Node* pNode = pItem->pNode;
02067         if (pNode)
02068         {
02069             TRACEUSER( "Gerry", _T("NodeListItem 0x%08x (%s)\n"), pNode, pNode->GetRuntimeClass()->m_lpszClassName);
02070 
02071             // Render the node span to a bitmap
02072             BOOL bNonAlphaTrans = DoesNodeUseNonAlphaTrans(pNode);
02073             Node* pNewNode = RenderNodesToBitmap(pNode, pNode, bNonAlphaTrans);
02074             if (!pNewNode)
02075                 return(FALSE);
02076 
02077             // Attach the new node as the previous of the first in the span
02078             pNewNode->AttachNode(pNode, PREV);
02079 
02080             // Delete the node we have just replaced
02081             pNode->CascadeDelete();
02082             delete pNode;
02083         }
02084 
02085         dProgress += dInc;
02086         if (!m_pFilter->SetProgressBarCount((UINT32)dProgress))
02087         {
02088             Error::SetError(_R(IDN_USER_CANCELLED),0);          // Expects error set
02089             return(FALSE);
02090         }
02091 
02092         // Get the next item
02093         pItem = (NodeListItem*)m_ConvertList.GetNext(pItem);
02094     }
02095 
02096     return(TRUE);
02097 }
02098 
02099 
02100 
02101 /****************************************************************************
02102 
02103 >   BOOL XPFRenderCallback::ConvertNodesForPass5()
02104 
02105     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
02106     Created:    31/10/2005
02107 
02108     Returns:    TRUE if ok, FALSE if bother
02109     Purpose:    Performs the bitmapspan conversion on the convert list
02110 
02111 ****************************************************************************/
02112 
02113 BOOL XPFRenderCallback::ConvertNodesForPass5()
02114 {
02115     TRACEUSER( "Gerry", _T("ConvertNodesForPass5 (%d)\n"), m_ConvertList.GetCount());
02116 
02117     double dProgress = 0.0;
02118     double dInc = 100.0 / (double)m_ConvertList.GetCount();
02119     
02120     SpanListItem* pItem = (SpanListItem*)m_ConvertList.GetHead();
02121     while (pItem)
02122     {
02123         TRACEUSER( "Gerry", _T("SpanListItem 0x%08x (%s) to 0x%08x (%s)\n"), pItem->m_pFirstNode, pItem->m_pFirstNode->GetRuntimeClass()->m_lpszClassName, pItem->m_pLastNode, pItem->m_pLastNode->GetRuntimeClass()->m_lpszClassName);
02124 
02125         // Render the node span to a bitmap
02126         Node* pNewNode = RenderNodesToBitmap(pItem->m_pFirstNode, pItem->m_pLastNode, pItem->m_bNonAlphaTrans);
02127         if (!pNewNode)
02128             return(FALSE);
02129 
02130         // Attach the new node as the previous of the first in the span
02131         pNewNode->AttachNode(pItem->m_pFirstNode, PREV);
02132 
02133         // Delete all the nodes in the span
02134         Node* pNode = pItem->m_pFirstNode;
02135         while (pNode)
02136         {
02137             Node* pNextNode = (pNode == pItem->m_pLastNode) ? NULL : pNode->FindNext();
02138 
02139             pNode->CascadeDelete();
02140             delete pNode;
02141 
02142             pNode = pNextNode;
02143         }
02144 
02145         dProgress += dInc;
02146         if (!m_pFilter->SetProgressBarCount((UINT32)dProgress))
02147         {
02148             Error::SetError(_R(IDN_USER_CANCELLED),0);          // Expects error set
02149             return(FALSE);
02150         }
02151 
02152         // Get the next span item
02153         pItem = (SpanListItem*)m_ConvertList.GetNext(pItem);
02154     }
02155 
02156     return(TRUE);
02157 }
02158 
02159 
02160 /****************************************************************************
02161 
02162 >   BOOL XPFRenderCallback::FindCommonTransTypeToApply(Node* pFirstNode, Node* pLastNode, UINT32* pCommonType)
02163 
02164     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
02165     Created:    15/06/2006
02166 
02167     Inputs:     pFirstNode  - pointer to a Node
02168                 pLastNode   - pointer to a Node
02169                 pCommonType - pointer to a UINT32
02170     Returns:    TRUE if ok, FALSE if bother
02171     Purpose:    
02172 
02173 ****************************************************************************/
02174 
02175 BOOL XPFRenderCallback::FindCommonTransTypeToApply(Node* pFirstNode, Node* pLastNode, UINT32* pCommonType)
02176 {
02177     // If CommonTrans isn't set then return false
02178     if (!m_pCapTree->HasRasteriseCommonTrans())
02179         return(FALSE);
02180     
02181     // Render the node span using an XPFRenderRegion and XPFSpanRenderCallback
02182     // to track the transparency used
02183     View *pView = View::GetCurrent();
02184     Spread* pSpread = pFirstNode->FindParentSpread();;
02185 
02186     CommonTransInfo TransInfo;
02187     
02188     // Create and set up a new XPFRenderRegion
02189     XPFRenderRegion XPFRegion(NULL, NULL, &TransInfo);
02190 
02191     // Attach a device to the scanning render region
02192     // Since this rr does no real rendering, it does not need a Device context
02193     XPFRegion.AttachDevice(pView, NULL, pSpread);
02194 
02195     // Start the render region and return if it fails
02196     if (XPFRegion.StartRender())
02197     {           
02198         TRACEUSER( "Gerry", _T("Rendering nodes from 0x%08x to 0x%08x\n"), pFirstNode, pLastNode);
02199         XPFSpanRenderCallback SpanCallback(pFirstNode, pLastNode, FALSE);
02200         // Call RenderTree to do the rendering
02201         XPFRegion.RenderTree(pSpread, FALSE, FALSE, &SpanCallback);
02202 
02203         // Thats all the nodes rendered, so stop rendering
02204         XPFRegion.StopRender();
02205 
02206         // Check the CommonTransInfo
02207         if (TransInfo.IsCommonType())
02208         {
02209             UINT32 CommonType = TransInfo.GetCommonType();
02210             if (CommonType != TT_Mix)
02211             {
02212                 *pCommonType = CommonType;
02213                 return(TRUE);
02214             }
02215         }
02216         else
02217         {
02218             if (TransInfo.UsesNonAlpha())
02219             {
02220                 if (pFirstNode == pLastNode && IS_A(pFirstNode, Layer))
02221                 {
02222                     Layer* pLayer = (Layer*)pFirstNode;
02223                     String_256 LayerName = pLayer->GetLayerID();
02224                     String_256 WarningMsg;
02225                     WarningMsg.MakeMsg(_R(IDS_XPF_MIXEDTRANSLAYER), &LayerName);
02226                     Error::SetError(_R(IDS_XPF_MIXEDTRANSLAYER),WarningMsg,0);
02227                     InformWarning();        
02228                 }
02229             }
02230         }
02231     }
02232     else
02233     {
02234         ERROR2(FALSE, "StartRender failed");
02235     }
02236 
02237     return(FALSE);
02238 }
02239 
02240 
02241 /****************************************************************************
02242 
02243 >   Node* XPFRenderCallback::RenderNodesToBitmap(Node* pFirstNode, Node* pLastNode, BOOL bNonAlphaTrans)
02244 
02245     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
02246     Created:    31/10/2005
02247 
02248     Inputs:     pFirstNode  - pointer to a Node
02249                 pLastNode   - pointer to a Node
02250                 bNonAlphaTrans- if TRUE then node span uses non-alpha trans
02251     Returns:    NULL in times of grief
02252     Purpose:    Renders a range of nodes into a bitmap.  If it uses non-alpha 
02253                 trans then a 24bpp bitmap is generated including all the 
02254                 objects before the span.  If it doesn't use non-alpha trans 
02255                 then a 32bpp RGBA bitmap of just the node span is generated
02256 
02257 ****************************************************************************/
02258 
02259 Node* XPFRenderCallback::RenderNodesToBitmap(Node* pFirstNode, Node* pLastNode, BOOL bNonAlphaTrans)
02260 {
02261     // First we detect the single layer case for various bits of special handling
02262     BOOL bOldLayerVisibility = FALSE;
02263     Layer* pSingleLayer = NULL;
02264     Spread* pSingleSpread = NULL;
02265     NodeBitmap* pSingleBitmap = NULL;
02266     if (pFirstNode == pLastNode)
02267     {
02268         if (pFirstNode->IsLayer())
02269         {
02270             pSingleLayer = (Layer*)pFirstNode;
02271             bOldLayerVisibility = pSingleLayer->GetVisibleFlagState();
02272             pSingleLayer->SetVisible(TRUE);
02273         }
02274         else if (pFirstNode->IsSpread())
02275         {
02276             pSingleSpread = (Spread*)pFirstNode;
02277         }
02278         else if (pFirstNode->IsABitmap())
02279         {
02280             pSingleBitmap = (NodeBitmap*)pFirstNode;
02281         }
02282     }
02283     
02284     // Find the bounding rect of the nodes and determine if the background needs
02285     // to be rendered
02286     DocRect SpanBounds;
02287     BOOL bBackground = FALSE;
02288     BOOL bForceMix = FALSE;
02289     BOOL bAlpha = m_pCapTree->GetRasteriseAlpha();
02290     UINT32 TransToApply = TT_NoTranspType;
02291     if (!bAlpha)
02292     {
02293         bBackground = TRUE;
02294     }
02295     else
02296     {
02297         if (FindCommonTransTypeToApply(pFirstNode, pLastNode, &TransToApply))
02298         {
02299             bBackground = FALSE;
02300             bForceMix = TRUE;
02301         }
02302         else
02303         {
02304             bBackground = bNonAlphaTrans;
02305         }
02306     }
02307 
02308     Node* pNode = pFirstNode;
02309     while (pNode)
02310     {
02311         if (pNode->IsBounded())
02312         {
02313             DocRect ObjectRect = ((NodeRenderableBounded*)pNode)->GetBoundingRect(FALSE, FALSE);
02314             SpanBounds = SpanBounds.Union(ObjectRect);
02315         }
02316         
02317         if (pNode == pLastNode)
02318             break;
02319 
02320         pNode = pNode->FindNext();
02321     }
02322 
02323     View* pView = View::GetCurrent();
02324     Spread* pSpread = pFirstNode->FindParentSpread();
02325 
02326     Matrix ViewTrans;
02327     FIXED16 TempScale(1.0);
02328     double Dpi = m_pCapTree->GetRasteriseDPI();
02329 
02330     // Make sure that SpanBounds is an exact multiple of pixels and is at 
02331     // pixel multiples and is not zero-sized
02332     double MPPerPix = 72000.0 / Dpi;
02333 
02334     INT32 IntVal = (INT32)floor((double)SpanBounds.lo.x / MPPerPix);
02335     SpanBounds.lo.x = (INT32)floor((double)IntVal * MPPerPix);
02336     IntVal = (INT32)floor((double)SpanBounds.lo.y / MPPerPix);
02337     SpanBounds.lo.y = (INT32)floor((double)IntVal * MPPerPix);
02338     IntVal = (INT32)ceil((double)SpanBounds.hi.x / MPPerPix);
02339     SpanBounds.hi.x = (INT32)ceil((double)IntVal * MPPerPix);
02340     IntVal = (INT32)ceil((double)SpanBounds.hi.y / MPPerPix);
02341     SpanBounds.hi.y = (INT32)ceil((double)IntVal * MPPerPix);
02342 
02343     if (SpanBounds.Width() < MPPerPix)
02344         SpanBounds.hi.x = (INT32)ceil((double)SpanBounds.lo.x + MPPerPix);
02345     if (SpanBounds.Height() < MPPerPix)
02346         SpanBounds.hi.y = (INT32)ceil((double)SpanBounds.lo.y + MPPerPix);
02347 
02348     // Create a full 32bpp RGBA for the mask
02349     // This is so that the antialiased pixels are handled correctly in the mask
02350     // Rendering into a 1bpp mask only sets half of the edge pixels that an 
02351     // anti-aliased render does and the mask spreading feature doesn't correctly 
02352     // account for the difference
02353     GRenderBitmap MaskBitmap(SpanBounds, ViewTrans, TempScale, 32, Dpi);
02354     if (bBackground && bAlpha)
02355     {
02356         MaskBitmap.m_DoCompression = TRUE;
02357         MaskBitmap.AttachDevice(pView, NULL, pSpread);
02358 
02359         if (MaskBitmap.StartRender())
02360         {
02361             // Save the context here so we can clear everything up later
02362             MaskBitmap.SaveContext();
02363 
02364             // Best quality please
02365             QualityAttribute *pQualAttr = new QualityAttribute();
02366             pQualAttr->QualityValue.SetQuality(QUALITY_MAX);
02367             MaskBitmap.SetQuality(pQualAttr, TRUE);
02368 
02369             XPFSpanRenderCallback MaskCallback(pFirstNode, pLastNode, FALSE);
02370             MaskBitmap.RenderTree(pSpread, FALSE, FALSE, &MaskCallback);
02371 
02372             // Save the context here so we can clear everything up later
02373             MaskBitmap.RestoreContext();
02374 
02375             // Tell the render region we are done rendering
02376             MaskBitmap.StopRender();
02377         }
02378     }
02379 
02380     GRenderBitmap BitmapRR(SpanBounds, ViewTrans, TempScale, 32, Dpi);
02381     if (!bBackground)
02382         BitmapRR.m_DoCompression = TRUE;
02383     BitmapRR.SetForceMixTransparency(bForceMix);
02384     BitmapRR.SetUsingSmoothedBitmaps(TRUE);     // Make sure we do high quality
02385     BitmapRR.AttachDevice(pView, NULL, pSpread);
02386 
02387     // Start rendering into the bitmap
02388     if (BitmapRR.StartRender())
02389     {
02390         // Save the context here so we can clear everything up later
02391         BitmapRR.SaveContext();
02392 
02393         if (bBackground)
02394         {
02395             // Draw required background
02396             DocRect DrawRect = SpanBounds;
02397             // Inflate the rect by 2 pixels
02398             DrawRect.Inflate( (INT32)(2*72000.0/Dpi + 0.5) );
02399 
02400             BitmapRR.SaveContext();
02401             DocColour White(255,255,255);
02402             BitmapRR.SetFillColour(White);
02403             BitmapRR.DrawRect(&DrawRect);
02404             BitmapRR.RestoreContext();
02405         }
02406 
02407         // Best quality please
02408         QualityAttribute *pQualAttr = new QualityAttribute();
02409         pQualAttr->QualityValue.SetQuality(QUALITY_MAX);
02410         BitmapRR.SetQuality(pQualAttr, TRUE);
02411 
02412         // Render the relevant span of the tree
02413         TRACEUSER("Gerry", _T("Rendering nodes from 0x%08x to 0x%08x%s\n"), pFirstNode, pLastNode, bBackground ? _T(" with background") : _T(""));
02414         XPFSpanRenderCallback SpanCallback(pFirstNode, pLastNode, bBackground);
02415         BitmapRR.RenderTree(pSpread, FALSE, FALSE, &SpanCallback);
02416 
02417         // This should stop any captures
02418         BitmapRR.RestoreContext();
02419 
02420         // Stop rendering
02421         BitmapRR.StopRender();
02422 
02423         // Reset the layer visiblity to the correct value
02424         if (pSingleLayer)
02425             pSingleLayer->SetVisible(bOldLayerVisibility);
02426     }
02427     else
02428     {
02429         ERROR2(NULL, "StartRender failed in RenderNodesToBitmap");
02430     }
02431 
02432     // Get the rendered OILBitmap
02433     OILBitmap* pFullBitmap = BitmapRR.ExtractBitmap();
02434     String_256 BmpName(m_pFilter->GetNewBitmapName());
02435     pFullBitmap->SetName(BmpName);
02436 
02437     if (bBackground && bAlpha)
02438     {
02439         // Merge in the mask info to knock out the surrounding areas
02440         OILBitmap* pMaskBitmap = MaskBitmap.ExtractBitmap();
02441         pFullBitmap->CopyFullyTransparentFrom(pMaskBitmap);
02442 
02443         // We can't delete an OILBitmap directly so we create a 
02444         // KernelBitmap and then delete that
02445         KernelBitmap* pTempBmp = KernelBitmap::MakeKernelBitmap(pMaskBitmap);
02446         delete pTempBmp;
02447     }
02448     
02449     KernelBitmap* pRealBmp = KernelBitmap::MakeKernelBitmap(pFullBitmap);
02450 
02451     // If we are converting a single NodeBitmap then maintain the lossy flag
02452     if (pSingleBitmap && pSingleBitmap->GetBitmap())
02453     {
02454         pRealBmp->SetAsLossy(pSingleBitmap->GetBitmap()->IsLossy());
02455     }
02456 
02457     // Attach the bitmap to this document or a copy will be created when 
02458     // it is used in the NodeBitmap
02459     BitmapList* pBmpList = NULL;
02460     Document* pCurDoc = Document::GetCurrent();
02461     if (pCurDoc)
02462         pBmpList = pCurDoc->GetBitmapList();
02463 
02464     // and then attach the bitmap (doesn't matter if BmpList is NULL)
02465     pRealBmp->Attach(pBmpList);
02466 
02467     // Create a NodeBitmap not in the tree
02468     NodeBitmap* pNodeBmp = new NodeBitmap();
02469     ERROR2IF(!pNodeBmp, NULL, "Failed to create NodeBitmap");
02470 
02471     pNodeBmp->SetUpPath();
02472     pNodeBmp->CreateShape(SpanBounds);
02473     pNodeBmp->BitmapRef.Attach(pRealBmp);       // Attach the correct bitmap
02474     pNodeBmp->ApplyDefaultBitmapAttrs(NULL);    // Apply the correct attrs
02475 
02476     // If we should be applying a non-mix transparency then do so
02477     if (TransToApply != TT_NoTranspType && TransToApply != TT_Mix)
02478     {
02479         AttrFlatTranspFill* pTrans = new AttrFlatTranspFill(pNodeBmp, FIRSTCHILD);
02480         if (pTrans)
02481         {
02482             pTrans->SetTranspType(TransToApply);
02483             UINT32 TransVal = 0;
02484             pTrans->SetStartTransp(&TransVal);
02485         }
02486     }
02487 
02488     if (pSingleSpread)
02489     {
02490         // Copy the spread and create a default layer
02491         Spread* pNewSpread = (Spread*)(pSingleSpread->PublicCopy());
02492         ERROR2IF(!pNewSpread, NULL, "Failed to create Spread");
02493 
02494         Layer* pNewLayer = new Layer(pNewSpread, FIRSTCHILD, String_256("Layer 1"));
02495         ERROR2IF(!pNewLayer, NULL, "Failed to create Layer");
02496 
02497         // Attach the NodeBitmap as the first child of the new layer
02498         pNodeBmp->AttachNode(pNewLayer, FIRSTCHILD);
02499 
02500         // Return the new spread node
02501         return(pNewSpread);
02502     }
02503 
02504     if (pSingleLayer)
02505     {
02506         // Create a shallow copy of the layer
02507         Layer* pNewLayer = (Layer*)(pSingleLayer->PublicCopy());
02508         ERROR2IF(!pNewLayer, NULL, "Failed to create Layer");
02509 
02510         // Attach the NodeBitmap as the first child of the new layer
02511         pNodeBmp->AttachNode(pNewLayer, FIRSTCHILD);
02512 
02513         // Return the new layer node
02514         return(pNewLayer);
02515     }
02516 
02517     // Just return the NodeBitmap
02518     return(pNodeBmp);
02519 }
02520 
02521 
02522 
02523 /****************************************************************************
02524 
02525 >   KernelBitmap* XPFRenderCallback::RenderFillToBitmap(Node* pNode, DocRect& BoundsRect)
02526 
02527     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
02528     Created:    31/10/2005
02529 
02530     Inputs:     pNode       - pointer to a Node
02531                 BoundsRect  - 
02532     Returns:    NULL in times of grief
02533     Purpose:    Renders the fill applied to the object into a KernelBitmap 
02534                 so that the fill can be replaced with a simple bitmap fill
02535 
02536 ****************************************************************************/
02537 
02538 KernelBitmap* XPFRenderCallback::RenderFillToBitmap(Node* pNode, DocRect& BoundsRect)
02539 {
02540     View* pView = View::GetCurrent();
02541     Spread* pSpread = pNode->FindParentSpread();
02542 
02543     Matrix ViewTrans;
02544     FIXED16 TempScale(1.0);
02545     double Dpi = m_pCapTree->GetRasteriseDPI();
02546 
02547     // Make sure that BoundsRect wont end up as a zero-sized rectangle
02548     double MPPerPix = 72000.0 / Dpi;
02549     if (BoundsRect.Width() < MPPerPix)
02550         BoundsRect.hi.x = BoundsRect.lo.x + (INT32)(MPPerPix + 0.5);
02551     if (BoundsRect.Height() < MPPerPix)
02552         BoundsRect.hi.y = BoundsRect.lo.y + (INT32)(MPPerPix + 0.5);
02553 
02554     GRenderBitmap BitmapRR(BoundsRect, ViewTrans, TempScale, 32, Dpi);
02555     BitmapRR.m_DoCompression = TRUE;
02556     BitmapRR.AttachDevice(pView, NULL, pSpread);
02557 
02558     TRACEUSER( "Gerry", _T("Rendering fill as bitmap (%d, %d)\n"), (INT32)((double)BoundsRect.Width() / MPPerPix), (INT32)((double)BoundsRect.Height() / MPPerPix));
02559 
02560     // Start rendering into the bitmap
02561     if (!BitmapRR.StartRender())
02562     {
02563         ERROR2(NULL, "StartRender failed in RenderFillToBitmap");
02564     }
02565 
02566     BitmapRR.SaveContext();
02567 
02568     // Best quality please
02569     QualityAttribute *pQualAttr = new QualityAttribute();
02570     pQualAttr->QualityValue.SetQuality(QUALITY_MAX);
02571     BitmapRR.SetQuality(pQualAttr, TRUE);
02572 
02573     NodeAttribute* pAttr;
02574     pAttr = FindChildAttr(pNode, CC_RUNTIME_CLASS(AttrFillGeometry));
02575     if (pAttr)
02576         pAttr->Render(&BitmapRR);
02577     pAttr = FindChildAttr(pNode, CC_RUNTIME_CLASS(AttrFillMapping));
02578     if (pAttr)
02579         pAttr->Render(&BitmapRR);
02580     pAttr = FindChildAttr(pNode, CC_RUNTIME_CLASS(AttrFillEffect));
02581     if (pAttr)
02582         pAttr->Render(&BitmapRR);
02583 
02584     BitmapRR.SetLineColour(COLOUR_NONE);
02585 
02586     Path RectPath;
02587     if (RectPath.Initialise())
02588     {
02589         // Start at bottom left corner
02590         RectPath.InsertMoveTo(BoundsRect.lo);
02591         RectPath.InsertLineTo(DocCoord(BoundsRect.hi.x, BoundsRect.lo.y));
02592         RectPath.InsertLineTo(BoundsRect.hi);
02593         RectPath.InsertLineTo(DocCoord(BoundsRect.lo.x, BoundsRect.hi.y));
02594         RectPath.InsertLineTo(BoundsRect.lo);
02595 
02596         // Close the path properly
02597         RectPath.CloseSubPath();
02598         RectPath.IsFilled = TRUE;
02599         RectPath.IsStroked = FALSE;
02600         BitmapRR.DrawPath(&RectPath);
02601     }
02602     else
02603     {
02604         pNode->Render(&BitmapRR);
02605     }
02606 
02607     BitmapRR.RestoreContext();
02608 
02609     // Stop rendering
02610     BitmapRR.StopRender();
02611 
02612     OILBitmap* pFullBitmap = BitmapRR.ExtractBitmap();
02613     String_256 BmpName = m_pFilter->GetNewBitmapName();
02614     pFullBitmap->SetName(BmpName);
02615     KernelBitmap* pRealBmp = KernelBitmap::MakeKernelBitmap(pFullBitmap);
02616 
02617     // Attach the bitmap to this document or a copy will be created when 
02618     // it is used in the attribute
02619     BitmapList* pBmpList = NULL;
02620     Document* pCurDoc = Document::GetCurrent();
02621     if (pCurDoc)
02622         pBmpList = pCurDoc->GetBitmapList();
02623 
02624     // and then attach the bitmap (doesn't matter if BmpList is NULL)
02625     pRealBmp->Attach(pBmpList);
02626 
02627     return(pRealBmp);
02628 }
02629 
02630 
02631 
02632 /****************************************************************************
02633 
02634 >   KernelBitmap* XPFRenderCallback::RenderTransToBitmap(Node* pNode, DocRect& BoundsRect, UINT32* pTransType)
02635 
02636     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
02637     Created:    31/10/2005
02638 
02639     Inputs:     pNode       - pointer to a Node
02640                 BoundsRect  - 
02641                 pTransType  - pointer to a UINT32
02642     Returns:    NULL in times of grief
02643     Purpose:    Renders the transparency applied to the object as a greyscale 
02644                 bitmap so that the transparency can be replaced by a simple 
02645                 bitmap transparency
02646 
02647 ****************************************************************************/
02648 
02649 KernelBitmap* XPFRenderCallback::RenderTransToBitmap(Node* pNode, DocRect& BoundsRect, UINT32* pTransType)
02650 {
02651     View* pView = View::GetCurrent();
02652     Spread* pSpread = pNode->FindParentSpread();
02653 
02654     Matrix ViewTrans;
02655     FIXED16 TempScale(1.0);
02656     double Dpi = m_pCapTree->GetRasteriseDPI();
02657 
02658     // Make sure that BoundsRect wont end up as a zero-sized rectangle
02659     double MPPerPix = 72000.0 / Dpi;
02660     if (BoundsRect.Width() < MPPerPix)
02661         BoundsRect.hi.x = BoundsRect.lo.x + (INT32)(MPPerPix + 0.5);
02662     if (BoundsRect.Height() < MPPerPix)
02663         BoundsRect.hi.y = BoundsRect.lo.y + (INT32)(MPPerPix + 0.5);
02664 
02665     GRenderBitmap BitmapRR(BoundsRect, ViewTrans, TempScale, 32, Dpi);
02666     BitmapRR.AttachDevice(pView, NULL, pSpread);
02667 
02668     TRACEUSER( "Gerry", _T("Rendering trans as bitmap (%d, %d)\n"), (INT32)((double)BoundsRect.Width() / MPPerPix), (INT32)((double)BoundsRect.Height() / MPPerPix));
02669 
02670     // Start rendering into the bitmap
02671     if (!BitmapRR.StartRender())
02672     {
02673         ERROR2(NULL, "StartRender failed in RenderTransToBitmap");
02674     }
02675 
02676     // Should draw a big white rectangle here, into the bitmap render region or
02677     // transparent objects will not fade to white where you can see the paper under them
02678     DocRect DrawRect = BoundsRect;
02679     // Inflate the rect by 2 pixels
02680     DrawRect.Inflate( (INT32)(2*72000.0/Dpi + 0.5) );
02681 
02682     // Draw it into the real bitmap
02683     BitmapRR.SaveContext();
02684     BitmapRR.SetFillColour(COLOUR_WHITE);
02685     BitmapRR.DrawRect(&DrawRect);
02686 
02687     // Best quality please
02688     QualityAttribute *pQualAttr = new QualityAttribute();
02689     pQualAttr->QualityValue.SetQuality(QUALITY_MAX);
02690     BitmapRR.SetQuality(pQualAttr, TRUE);
02691 
02692     NodeAttribute* pAttr;
02693     pAttr = FindChildAttr(pNode, CC_RUNTIME_CLASS(AttrTranspFillGeometry));
02694     if (pAttr)
02695     {
02696         // It might be safer to create a copy of the attribute so that 
02697         // the transparency type can be changed without affecting the existing 
02698         // attribute but the attribute is going to get deleted anyway
02699         TranspFillAttribute* pVal = (TranspFillAttribute*)pAttr->GetAttributeValue();
02700         if (pTransType)
02701             *pTransType = pVal->GetTranspType();
02702         pVal->SetTranspType(TT_Mix);
02703         pAttr->Render(&BitmapRR);
02704     }
02705     pAttr = FindChildAttr(pNode, CC_RUNTIME_CLASS(AttrTranspFillMapping));
02706     if (pAttr)
02707         pAttr->Render(&BitmapRR);
02708 
02709     BitmapRR.SetFillColour(COLOUR_BLACK);
02710     BitmapRR.SetLineColour(COLOUR_NONE);
02711 
02712     Path RectPath;
02713     if (RectPath.Initialise())
02714     {
02715         // Start at bottom left corner
02716         RectPath.InsertMoveTo(BoundsRect.lo);
02717         RectPath.InsertLineTo(DocCoord(BoundsRect.hi.x, BoundsRect.lo.y));
02718         RectPath.InsertLineTo(BoundsRect.hi);
02719         RectPath.InsertLineTo(DocCoord(BoundsRect.lo.x, BoundsRect.hi.y));
02720         RectPath.InsertLineTo(BoundsRect.lo);
02721 
02722         // Close the path properly
02723         RectPath.CloseSubPath();
02724         RectPath.IsFilled = TRUE;
02725         RectPath.IsStroked = FALSE;
02726         BitmapRR.DrawPath(&RectPath);
02727     }
02728     else
02729     {
02730         pNode->Render(&BitmapRR);
02731     }
02732 
02733     BitmapRR.RestoreContext();
02734 
02735     // Stop rendering
02736     BitmapRR.StopRender();
02737 
02738     OILBitmap* pFullBitmap = BitmapRR.ExtractBitmap();
02739     String_256 BmpName = m_pFilter->GetNewBitmapName();
02740     pFullBitmap->SetName(BmpName);
02741     KernelBitmap* pRealBmp = KernelBitmap::MakeKernelBitmap(pFullBitmap);
02742 
02743     // Attach the bitmap to this document or a copy will be created when 
02744     // it is used in the attribute
02745     BitmapList* pBmpList = NULL;
02746     Document* pCurDoc = Document::GetCurrent();
02747     if (pCurDoc)
02748         pBmpList = pCurDoc->GetBitmapList();
02749 
02750     // and then attach the bitmap (doesn't matter if BmpList is NULL)
02751     pRealBmp->Attach(pBmpList);
02752 
02753     return(pRealBmp);
02754 }
02755 
02756 
02757 
02758 /****************************************************************************
02759 
02760 >   KernelBitmap* XPFRenderCallback::RenderFillAndTransToBitmap(Node* pNode, DocRect& BoundsRect)
02761 
02762     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
02763     Created:    31/10/2005
02764 
02765     Inputs:     pNode       - pointer to a Node
02766                 BoundsRect  - 
02767     Returns:    NULL in times of grief
02768     Purpose:    Renders the applied fill and transparency to a bitmap so 
02769                 both the fill and trans can be replaced by a simple bitmap 
02770                 fill.  If the transparency is non-alpha compatible then 
02771                 we also have to render all the previous objects into it
02772 
02773 ****************************************************************************/
02774 
02775 KernelBitmap* XPFRenderCallback::RenderFillAndTransToBitmap(Node* pNode, DocRect& BoundsRect)
02776 {
02777     BOOL bBackground = FALSE;
02778     NodeAttribute* pTransAttr = FindChildAttr(pNode, CC_RUNTIME_CLASS(AttrTranspFillGeometry));
02779     if (pTransAttr)
02780     {
02781         TranspFillAttribute* pTrans = (TranspFillAttribute*)(pTransAttr->GetAttributeValue());
02782         UINT32 Type = pTrans->GetTranspType();
02783         if (Type != TT_NoTranspType &&
02784             Type != TT_Mix &&
02785             Type != TT_DARKEN &&
02786             Type != TT_LIGHTEN &&
02787             Type != TT_BRIGHTNESS &&
02788             Type != TT_BEVEL)
02789         {
02790             bBackground = TRUE;
02791         }
02792     }
02793     
02794     if (!m_pCapTree->GetRasteriseAlpha())
02795         bBackground = TRUE;
02796 
02797     View* pView = View::GetCurrent();
02798     Spread* pSpread = pNode->FindParentSpread();
02799 
02800     Matrix ViewTrans;
02801     FIXED16 TempScale(1.0);
02802     double Dpi = m_pCapTree->GetRasteriseDPI();
02803 
02804     // Make sure that BoundsRect wont end up as a zero-sized rectangle
02805     double MPPerPix = 72000.0 / Dpi;
02806     if (BoundsRect.Width() < MPPerPix)
02807         BoundsRect.hi.x = BoundsRect.lo.x + (INT32)(MPPerPix + 0.5);
02808     if (BoundsRect.Height() < MPPerPix)
02809         BoundsRect.hi.y = BoundsRect.lo.y + (INT32)(MPPerPix + 0.5);
02810 
02811     GRenderBitmap BitmapRR(BoundsRect, ViewTrans, TempScale, 32, Dpi);
02812     if (!bBackground)
02813         BitmapRR.m_DoCompression = TRUE;
02814     BitmapRR.AttachDevice(pView, NULL, pSpread);
02815 
02816     TRACEUSER( "Gerry", _T("Rendering fill and trans as bitmap (%d, %d)\n"), (INT32)((double)BoundsRect.Width() / MPPerPix), (INT32)((double)BoundsRect.Height() / MPPerPix));
02817 
02818     // Start rendering into the bitmap
02819     if (!BitmapRR.StartRender())
02820     {
02821         ERROR2(NULL, "StartRender failed in RenderFillAndTransToBitmap");
02822     }
02823 
02824     if (bBackground)
02825     {
02826         // Should draw a big white rectangle here, into the bitmap render region or
02827         // transparent objects will not fade to white where you can see the paper under them
02828         DocRect DrawRect = BoundsRect;
02829         // Inflate the rect by 2 pixels
02830         DrawRect.Inflate( (INT32)(2*72000.0/Dpi + 0.5) );
02831 
02832         // Draw it into the real bitmap
02833         BitmapRR.SaveContext();
02834         BitmapRR.SetFillColour(COLOUR_WHITE);
02835         BitmapRR.DrawRect(&DrawRect);
02836         BitmapRR.RestoreContext();
02837     }
02838 
02839     BitmapRR.SaveContext();
02840     
02841     // Best quality please
02842     QualityAttribute *pQualAttr = new QualityAttribute();
02843     pQualAttr->QualityValue.SetQuality(QUALITY_MAX);
02844     BitmapRR.SetQuality(pQualAttr, TRUE);
02845 
02846     if (bBackground)
02847     {
02848         // We need to render the background objects first
02849         // Reuse existing code by finding the previous object and 
02850         // asking for it to be rendered with its background
02851         Node* pBackNode = pNode->FindPrevious();
02852         Node* pParent = pNode->FindParent();
02853         while (pBackNode == NULL)
02854         {
02855             if (pParent == NULL)
02856                 break;
02857             pBackNode = pParent->FindPrevious();
02858             pParent = pParent->FindParent();
02859         }           
02860         
02861         if (pBackNode)
02862         {
02863             XPFSpanRenderCallback SpanCallback(pBackNode, pBackNode, TRUE);
02864             BitmapRR.RenderTree(pSpread, FALSE, FALSE, &SpanCallback);
02865         }
02866     }
02867 
02868     NodeAttribute* pAttr;
02869     pAttr = FindChildAttr(pNode, CC_RUNTIME_CLASS(AttrFillGeometry));
02870     if (pAttr)
02871         pAttr->Render(&BitmapRR);
02872     pAttr = FindChildAttr(pNode, CC_RUNTIME_CLASS(AttrFillMapping));
02873     if (pAttr)
02874         pAttr->Render(&BitmapRR);
02875     pAttr = FindChildAttr(pNode, CC_RUNTIME_CLASS(AttrFillEffect));
02876     if (pAttr)
02877         pAttr->Render(&BitmapRR);
02878     pAttr = FindChildAttr(pNode, CC_RUNTIME_CLASS(AttrTranspFillGeometry));
02879     if (pAttr)
02880         pAttr->Render(&BitmapRR);
02881     pAttr = FindChildAttr(pNode, CC_RUNTIME_CLASS(AttrTranspFillMapping));
02882     if (pAttr)
02883         pAttr->Render(&BitmapRR);
02884 
02885     BitmapRR.SetLineColour(COLOUR_NONE);
02886 
02887     Path RectPath;
02888     if (RectPath.Initialise())
02889     {
02890         // Start at bottom left corner
02891         RectPath.InsertMoveTo(BoundsRect.lo);
02892         RectPath.InsertLineTo(DocCoord(BoundsRect.hi.x, BoundsRect.lo.y));
02893         RectPath.InsertLineTo(BoundsRect.hi);
02894         RectPath.InsertLineTo(DocCoord(BoundsRect.lo.x, BoundsRect.hi.y));
02895         RectPath.InsertLineTo(BoundsRect.lo);
02896 
02897         // Close the path properly
02898         RectPath.CloseSubPath();
02899         RectPath.IsFilled = TRUE;
02900         RectPath.IsStroked = FALSE;
02901         BitmapRR.DrawPath(&RectPath);
02902     }
02903     else
02904     {
02905         pNode->Render(&BitmapRR);
02906     }
02907 
02908     BitmapRR.RestoreContext();
02909 
02910     // Stop rendering
02911     BitmapRR.StopRender();
02912 
02913     OILBitmap* pFullBitmap = BitmapRR.ExtractBitmap();
02914     String_256 BmpName = m_pFilter->GetNewBitmapName();
02915     pFullBitmap->SetName(BmpName);
02916     KernelBitmap* pRealBmp = KernelBitmap::MakeKernelBitmap(pFullBitmap);
02917 
02918     // Attach the bitmap to this document or a copy will be created when 
02919     // it is used in the attribute
02920     BitmapList* pBmpList = NULL;
02921     Document* pCurDoc = Document::GetCurrent();
02922     if (pCurDoc)
02923         pBmpList = pCurDoc->GetBitmapList();
02924 
02925     // and then attach the bitmap (doesn't matter if BmpList is NULL)
02926     pRealBmp->Attach(pBmpList);
02927 
02928     return(pRealBmp);
02929 }
02930 
02931 
02932 /****************************************************************************
02933 
02934 >   BOOL XPFSpanRenderCallback::BeforeNode(RenderRegion* pRegion, Node* pNode)
02935 
02936     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
02937     Created:    19/06/2006
02938 
02939     Inputs:     pRegion     - pointer to a RenderRegion
02940                 pNode       - pointer to a Node
02941     Returns:    TRUE if ok, FALSE if bother
02942     Purpose:    
02943 
02944 ****************************************************************************/
02945 
02946 BOOL XPFSpanRenderCallback::BeforeNode(RenderRegion* pRegion, Node* pNode)
02947 {
02948 //  char* pStateStr = (m_RenderState == RS_INSPAN) ? "in" : (m_RenderState == RS_AFTERSPAN) ? "after" : "before";
02949 //  TRACE( _T("XPFSpanRC# BeforeNode    0x%08x - %s  %s\n"), pNode, pNode->GetRuntimeClass()->m_lpszClassName, pStateStr);
02950     
02951     BOOL bRender = FALSE;
02952     switch (m_RenderState)
02953     {
02954         case RS_BEFORESPAN:
02955             if (m_bBackground || pNode->IsAnAttribute() || pNode->IsANodeClipView())
02956             {
02957                 // Let it render normally
02958                 bRender = TRUE;
02959             }
02960             break;
02961 
02962         case RS_INSPAN:
02963             bRender = TRUE;
02964             break;
02965         
02966         case RS_AFTERSPAN:
02967             // Must skip everything until the end
02968             bRender = FALSE;
02969             break;
02970 
02971         default:
02972             TRACE( _T("XPFSpanRC# Bad RenderState in BeforeNode\n"));
02973             break;
02974     }           
02975 
02976 //  TRACE( _T("XPFSpanRC# BeforeNode    0x%08x - %s returning %s\n", pNode, pNode->GetRuntimeClass()->m_lpszClassName, bRender ? "true" : "false"));
02977     return(bRender);
02978 }
02979 
02980 
02981 /****************************************************************************
02982 
02983 >   BOOL XPFSpanRenderCallback::BeforeSubtree(RenderRegion* pRegion, Node* pNode, Node** ppNextNode, BOOL bClip, SubtreeRenderState* pState)
02984 
02985     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
02986     Created:    19/06/2006
02987 
02988     Inputs:     pRegion     - pointer to a RenderRegion
02989                 pNode       - pointer to a Node
02990                 ppNextNode  - pointer to a pointer to a Node
02991                 bClip       - 
02992                 pState      - pointer to a SubtreeRenderState
02993     Returns:    TRUE if ok, FALSE if bother
02994     Purpose:    
02995 
02996 ****************************************************************************/
02997 
02998 BOOL XPFSpanRenderCallback::BeforeSubtree(RenderRegion* pRegion, Node* pNode, Node** ppNextNode, BOOL bClip, SubtreeRenderState* pState)
02999 {
03000 //  char* pStateStr = (m_RenderState == RS_INSPAN) ? "in" : (m_RenderState == RS_AFTERSPAN) ? "after" : "before";
03001 //  TRACE( _T("XPFSpanRC# BeforeSubtree 0x%08x - %s  %s\n"), pNode, pNode->GetRuntimeClass()->m_lpszClassName, pStateStr);
03002 
03003     switch (m_RenderState)
03004     {
03005         case RS_BEFORESPAN:
03006             if (pNode == m_pFirstNode)
03007             {
03008 //              TRACE( _T("XPFSpanRC# Start of span\n"));
03009                 // Change state to be in the span
03010                 m_RenderState = RS_INSPAN;
03011             }
03012             else if (!pNode->IsAnAttribute() && !m_bBackground && !pNode->IsNodeInSubtree(m_pFirstNode))
03013             {
03014                 // The first node isn't in this subtree so don't bother rendering it
03015                 *pState = SUBTREE_NORENDER;
03016                 return(TRUE);
03017             }
03018             break;
03019 
03020         case RS_INSPAN:
03021             break;
03022 
03023         case RS_AFTERSPAN:
03024             // Don't render this subtree
03025             *pState = SUBTREE_NORENDER;
03026             return(TRUE);
03027             break;
03028 
03029         default:
03030             TRACE( _T("XPFSpanRC# Bad RenderState in BeforeSubtree\n"));
03031             break;
03032     }           
03033     
03034     return(FALSE);
03035 }
03036         
03037 
03038 /****************************************************************************
03039 
03040 >   BOOL XPFSpanRenderCallback::AfterSubtree(RenderRegion* pRegion, Node* pNode)
03041 
03042     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
03043     Created:    19/06/2006
03044 
03045     Inputs:     pRegion     - pointer to a RenderRegion
03046                 pNode       - pointer to a Node
03047     Returns:    TRUE if ok, FALSE if bother
03048     Purpose:    
03049 
03050 ****************************************************************************/
03051 
03052 BOOL XPFSpanRenderCallback::AfterSubtree(RenderRegion* pRegion, Node* pNode)
03053 {
03054 //  char* pStateStr = (m_RenderState == RS_INSPAN) ? "in" : (m_RenderState == RS_AFTERSPAN) ? "after" : "before";
03055 //  TRACE( _T("XPFSpanRC# AfterSubtree    0x%08x - %s  %s\n"), pNode, pNode->GetRuntimeClass()->m_lpszClassName, pStateStr);
03056 
03057     // By default we do want RenderAfterSubtree to be called
03058     BOOL bStopRender = FALSE;
03059     switch (m_RenderState)
03060     {
03061         case RS_BEFORESPAN:
03062             if (!m_bBackground && !pNode->IsNodeInSubtree(m_pFirstNode))
03063             {
03064                 // The first node isn't in this subtree so don't bother rendering it
03065                 bStopRender = TRUE;
03066             }
03067             break;
03068 
03069         case RS_INSPAN:
03070             if (pNode == m_pLastNode)
03071             {
03072 //              TRACE( _T("XPFSpanRC# End of span\n"));
03073                 // Change state to be after the span
03074                 m_RenderState = RS_AFTERSPAN;
03075             }
03076             break;
03077         
03078         case RS_AFTERSPAN:
03079             // Must skip everything until the end
03080             bStopRender = TRUE;
03081             break;
03082 
03083         default:
03084             TRACE( _T("XPFSpanRC# Bad RenderState in AfterSubtree\n"));
03085             break;
03086     }           
03087 //  TRACE( _T("XPFSpanRC# AfterSubtree  0x%08x - %s returning %s\n", pNode, pNode->GetRuntimeClass()->m_lpszClassName, bStopRender ? "true" : "false"));
03088     return(bStopRender);
03089 }
03090 
03091 
03092 
03093 CommonTransInfo::CommonTransInfo()
03094 {
03095     m_bCommonType = TRUE;
03096     m_CommonType = TT_NoTranspType;
03097 }
03098 
03099 void CommonTransInfo::UpdateCommonType(UINT32 Type)
03100 {
03101     if (m_bCommonType)
03102     {
03103         if (Type == TT_NoTranspType ||
03104             Type == TT_DARKEN ||
03105             Type == TT_LIGHTEN ||
03106             Type == TT_BRIGHTNESS ||
03107             Type == TT_BEVEL)
03108         {
03109             Type = TT_Mix;      // These are all mix
03110         }
03111 
03112         if (m_CommonType == TT_NoTranspType)
03113             m_CommonType = Type;
03114         else if (m_CommonType != Type)
03115             m_bCommonType = FALSE;
03116     }
03117 }
03118 
03119 UINT32 CommonTransInfo::GetCommonType()
03120 {
03121     return(m_bCommonType ? m_CommonType : TT_NoTranspType);
03122 }
03123 
03124 
03125 
03126 /****************************************************************************
03127 
03128 >   XPFView::~XPFView()
03129 
03130     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
03131     Created:    31/10/2005
03132     Purpose:    Destroys a XPFView, deallocating it's associated ViewState.
03133 
03134 ****************************************************************************/
03135 
03136 XPFView::~XPFView()
03137 {
03138     delete pVState;
03139     pVState = 0;
03140 }
03141 
03142 
03143 
03144 /********************************************************************************************
03145 
03146 >   BOOL XPFView::Init(double DPI)
03147 
03148     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (copying Tim code)
03149     Created:    022/4/95
03150 
03151     Returns:    TRUE if initialised ok;
03152                 FALSE if not
03153 
03154     Purpose:    Initialise the XPFView for rendering.
03155 
03156 ********************************************************************************************/
03157 
03158 BOOL XPFView::Init(double DPI)
03159 {
03160     // Store the DPI away
03161     m_DPI = DPI;
03162     
03163     // Set up our pixel size
03164     PixelWidth = FIXED16(72000.0 / DPI);
03165     PixelHeight = FIXED16(72000.0 / DPI);
03166     ScaledPixelWidth = PixelWidth;
03167     ScaledPixelHeight = PixelHeight;
03168 
03169     // Get ourselves a ViewState object
03170     pVState = new ViewState;
03171     if (pVState == NULL) 
03172         return FALSE;
03173 
03174     // Connect this view state to this view
03175     pVState->pView = this;
03176 
03177     // All ok
03178     return TRUE;
03179 }
03180 
03181 
03182 
03183 /********************************************************************************************
03184 
03185 >   BOOL XPFView::ViewStateChanged()
03186 
03187     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (copying Tim code)
03188     Created:    22/4/95
03189     Returns:    TRUE (always).
03190     Purpose:    
03191 
03192 ********************************************************************************************/
03193 
03194 BOOL XPFView::ViewStateChanged()
03195 {
03196     // Local variables...
03197     DocCoord    ExtentLo;                       // coord of bottom-left of logical extent
03198     DocCoord    ExtentHi;                       // coord of top-right of logical extent
03199     
03200     // Read DocCoords extent of document & set extent in platform-indy ViewState struct.
03201     pDoc->GetExtents(&ExtentLo, &ExtentHi, &PhysExtent, this);
03202     SetExtent(ExtentLo, ExtentHi);              
03203 
03204     return TRUE;
03205 }
03206 
03207 
03208 
03209 /********************************************************************************************
03210 
03211 >   void XPFView::SetViewPixelSize()
03212 
03213     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (copying Tim code)
03214     Created:    22/4/95
03215     Purpose:    Sets up the pixel size for this view object.
03216     SeeAlso:    XPFView
03217 
03218 ********************************************************************************************/
03219 
03220 void XPFView::SetViewPixelSize()
03221 {
03222     // Set the scaled pixel size
03223     ScaledPixelWidth = PixelWidth / Scale;
03224     ScaledPixelHeight = PixelHeight / Scale;
03225 }
03226 
03227 
03228 
03229 /********************************************************************************************
03230 
03231 >   void XPFView::ContinueRenderView(RenderRegion*, Spread*, BOOL = TRUE, BOOL = TRUE,
03232                                      BOOL bForceImmediate = FALSE)
03233 
03234     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (copying Tim code)
03235     Created:    22/4/95
03236     Inputs:     N/A
03237     Purpose:    None - XPFView is a skeleton class that is only used to access screen
03238                 characteristics.
03239     Errors:     Always => ERROR3
03240 
03241 ********************************************************************************************/
03242 
03243 void XPFView::ContinueRenderView(RenderRegion*, Spread*, BOOL, BOOL,
03244                                      BOOL bForceImmediate)
03245 {
03246     ERROR3("XPFView::ContinueRenderView() should not be called!");
03247 }
03248 
03249 
03250 
03251 /********************************************************************************************
03252 
03253 >   CDC *XPFView::GetRenderDC()
03254 
03255     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (copying Tim code)
03256     Created:    22/4/95
03257     Returns:    NULL (always)
03258     Purpose:    None - XPFView is a skeleton class that is only used to access screen
03259                 characteristics.
03260 
03261 ********************************************************************************************/
03262 
03263 CNativeDC *XPFView::GetRenderDC()
03264 {
03265     return NULL;
03266 }
03267 
03268 
03269 
03270 /********************************************************************************************
03271 
03272 >   BOOL XPFView::GetForeBackMode()
03273 
03274     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (copying Tim code)
03275     Created:    22/4/95
03276     Returns:    FALSE - dialogs don't do background rendering.
03277     Purpose:    None - XPFView is a skeleton class that is only used to access screen
03278                 characteristics.
03279 
03280 ********************************************************************************************/
03281 
03282 BOOL XPFView::GetForeBackMode()
03283 {
03284     // XPFViews don't background render.
03285     return FALSE;
03286 }
03287 
03288 
03289 
03290 /********************************************************************************************
03291 
03292 >   void XPFView::SetForeBackMode(BOOL)
03293 
03294     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (copying Tim code)
03295     Created:    22/4/95
03296     Inputs:     N/A
03297     Purpose:    None - XPFView is a skeleton class that is only used to access screen
03298                 characteristics.
03299     Errors:     ERROR3 always - dialogs cannot background render!
03300     SeeAlso:    XPFView
03301 
03302 ********************************************************************************************/
03303 
03304 void XPFView::SetForeBackMode(BOOL)
03305 {
03306     ERROR3("XPFView::SetForeBackMode() should not be called!");
03307 }
03308 
03309 
03310 
03311 /********************************************************************************************
03312 
03313 >   DocRect XPFView::GetDocViewRect(Spread*)
03314 
03315     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (copying Tim code)
03316     Created:    22/4/95
03317     Inputs:     N/A
03318     Returns:    The bounds of the objects in the InternalClipboard
03319     Purpose:    To determine the docrect area that this view is viewing
03320 
03321 ********************************************************************************************/
03322 
03323 DocRect XPFView::GetDocViewRect(Spread* pSpread)
03324 {
03325     return(pSpread->GetBoundingRect());
03326 }
03327 
03328 
03329 
03330 /********************************************************************************************
03331 
03332 >   void XPFView::SetExtent(DocCoord, DocCoord)
03333 
03334     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (copying Tim code)
03335     Created:    22/4/95
03336     Inputs:     Two DocCoords describing the low and high corners of a rectangle in logical
03337                 space describing the full extent of the document. I.E. the bottom-left corner
03338                 of the last chapter and the top-right corner of the first.
03339     Purpose:    Informs the DocView that the extent of the document has changed in some way and 
03340                 that the view must be altered to take this into account (namely the 
03341                 scrollbars).
03342     SeeAlso:    XPFView
03343 
03344 ********************************************************************************************/
03345 
03346 void XPFView::SetExtent(DocCoord lolog, DocCoord hilog)
03347 {
03348     // Convert the extent given in DocCoord to WorkCoords...
03349     pVState->WorkAreaExtent.lo = lolog.ToWork(pDoc, this);
03350     pVState->WorkAreaExtent.hi = hilog.ToWork(pDoc, this);
03351 }
03352 
03353 
03354 
03355 /********************************************************************************************
03356 
03357 >   WorkRect XPFView::GetViewRect()
03358 
03359     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (copying Tim code)
03360     Created:    22/4/95
03361     Returns:    An empty rectangle (always).
03362     Purpose:    None - XPFView is a skeleton class that is only used to access screen
03363                 characteristics.
03364 
03365 ********************************************************************************************/
03366 
03367 WorkRect XPFView::GetViewRect()
03368 {
03369     WorkRect Empty;
03370     return Empty;
03371 }
03372 
03373 
03374 
03375 /****************************************************************************
03376 
03377 >   double XPFView::GetConvertToEditableShapesDPI()
03378 
03379     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
03380     Created:    18/08/2005
03381 
03382     Returns:    The resolution to use for convert to editable shapes 
03383                 operations while this view is current
03384     Purpose:    Allows derived view classes to override the reolution
03385 
03386 ****************************************************************************/
03387 
03388 double XPFView::GetConvertToEditableShapesDPI()
03389 {
03390     return(m_DPI);
03391 }

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