XPFRenderCallback Class Reference

This is the custom render callback class for the capabilities conversion. More...

#include <xpfrgn.h>

Inheritance diagram for XPFRenderCallback:

RenderCallback CCObject SimpleCCObject List of all members.

Public Member Functions

 XPFRenderCallback (PluginNativeFilter *pFilter, XPFRenderRegion *pXPFRegion, CapabilityTree *pCapTree, INT32 ConvertPass)
 Constructs an XPFRenderCallback object to control the rendering loop for each phase of the conversion mechanism.
 ~XPFRenderCallback ()
 Destructor.
virtual BOOL BeforeNode (RenderRegion *pRegion, Node *pNode)
virtual BOOL BeforeSubtree (RenderRegion *pRegion, Node *pNode, Node **ppNextNode, BOOL bClip, SubtreeRenderState *pState)
SpreadGetNewSpread ()
void SetAttachContext (Node *pContext, AttachNodeDirection Direction)
BOOL ConvertNodes ()
 Performs the required conversion on the stored list of nodes.

Protected Member Functions

BOOL ConvertNodesForPass2 ()
 Performs the "stroked" conversion on the convert list.
BOOL ConvertNodesForPass3 ()
 Performs the bitmapfill, bitmaptrans and bitmapfilltrans conversions on the convert list.
BOOL ConvertNodesForPass4 ()
 Performs the bitmap conversion on the convert list.
BOOL ConvertNodesForPass5 ()
 Performs the bitmapspan conversion on the convert list.
void RemoveChildAttrs (Node *pNode, CCRuntimeClass *pClass)
 Removes all child attributes of a particular attribute type.
NodeAttributeFindChildAttr (Node *pNode, CCRuntimeClass *pClass)
 Finds the last child attr of the specified attribute type.
NodeRenderNodesToBitmap (Node *pFirstNode, Node *pLastNode, BOOL bNonAlphaTrans)
 Renders a range of nodes into a bitmap. If it uses non-alpha trans then a 24bpp bitmap is generated including all the objects before the span. If it doesn't use non-alpha trans then a 32bpp RGBA bitmap of just the node span is generated.
KernelBitmapRenderFillToBitmap (Node *pNode, DocRect &BoundsRect)
 Renders the fill applied to the object into a KernelBitmap so that the fill can be replaced with a simple bitmap fill.
KernelBitmapRenderTransToBitmap (Node *pNode, DocRect &BoundsRect, UINT32 *pTransType)
 Renders the transparency applied to the object as a greyscale bitmap so that the transparency can be replaced by a simple bitmap transparency.
KernelBitmapRenderFillAndTransToBitmap (Node *pNode, DocRect &BoundsRect)
 Renders the applied fill and transparency to a bitmap so both the fill and trans can be replaced by a simple bitmap fill. If the transparency is non-alpha compatible then we also have to render all the previous objects into it.
TextStoryReformatTextStory (TextStory *pStory)
 Creates a copy of a TextStory where the copy is manually kerned and only uses left justification.
NodeReformatTextLine (TextLine *pLineNode, FormatRegion *pFormatRegion)
 Creates a left justified and manually kerned copy of a text line by inserting manual kern codes where necessary.
BOOL CopyAttributesFromNode (Node *pDestNode, Node *pSrcNode)
 Copies all attributes except justification and tracking from one node to another.
BOOL DoesNodeUseNonAlphaTrans (Node *pRootNode)
 Determines if a node has any attributes that use non-alpha transparency.
BOOL FindCommonTransTypeToApply (Node *pFirstNode, Node *pLastNode, UINT32 *pCommonType)

Private Attributes

INT32 m_ConvertPass
PluginNativeFilterm_pFilter
XPFRenderRegionm_pXPFRegion
CapabilityTreem_pCapTree
Spreadm_pNewSpread
Nodem_pContextNode
AttachNodeDirection m_Direction
Nodem_pSpanParent
List m_ConvertList
List m_ParentList

Detailed Description

This is the custom render callback class for the capabilities conversion.

Author:
Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
Date:
26/01/05

Definition at line 250 of file xpfrgn.h.


Constructor & Destructor Documentation

XPFRenderCallback::XPFRenderCallback PluginNativeFilter pFilter,
XPFRenderRegion pXPFRegion,
CapabilityTree pCapTree,
INT32  ConvertPass
 

Constructs an XPFRenderCallback object to control the rendering loop for each phase of the conversion mechanism.

Author:
Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/10/2005
Parameters:
pFilter - pointer to a PluginNativeFilter [INPUTS] pXPFRegion - pointer to a XPFRenderRegion pCapTree - pointer to a CapabilityTree ConvertPass - conversion pass

Definition at line 625 of file xpfrgn.cpp.

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 }

XPFRenderCallback::~XPFRenderCallback  ) 
 

Destructor.

Author:
Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/10/2005

Definition at line 650 of file xpfrgn.cpp.

00651 {
00652     m_ConvertList.DeleteAll();
00653     m_ParentList.DeleteAll();
00654 }


Member Function Documentation

BOOL XPFRenderCallback::BeforeNode RenderRegion pRegion,
Node pNode
[virtual]
 

Author:
Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/10/2005
Parameters:
pRegion - pointer to a RenderRegion [INPUTS] pNode - pointer to a Node
Returns:
TRUE if ok, FALSE if bother

Reimplemented from RenderCallback.

Definition at line 672 of file xpfrgn.cpp.

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 }

BOOL XPFRenderCallback::BeforeSubtree RenderRegion pRegion,
Node pNode,
Node **  ppNextNode,
BOOL  bClip,
SubtreeRenderState pState
[virtual]
 

Author:
Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/10/2005
Parameters:
pRegion - pointer to a RenderRegion [INPUTS] pNode - pointer to a Node ppNextNode - pointer to a pointer to a Node bClip - pState - pointer to a SubtreeRenderState
Returns:
TRUE if ok, FALSE if bother

Reimplemented from RenderCallback.

Definition at line 945 of file xpfrgn.cpp.

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 }

BOOL XPFRenderCallback::ConvertNodes  ) 
 

Performs the required conversion on the stored list of nodes.

Author:
Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/10/2005
Returns:
TRUE if ok, FALSE if bother

Definition at line 1623 of file xpfrgn.cpp.

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 }

BOOL XPFRenderCallback::ConvertNodesForPass2  )  [protected]
 

Performs the "stroked" conversion on the convert list.

Author:
Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/10/2005
Returns:
TRUE if ok, FALSE if bother

Definition at line 1668 of file xpfrgn.cpp.

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 }

BOOL XPFRenderCallback::ConvertNodesForPass3  )  [protected]
 

Performs the bitmapfill, bitmaptrans and bitmapfilltrans conversions on the convert list.

Author:
Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
Date:
31/10/2005
Returns:
TRUE if ok, FALSE if bother

Definition at line 1821 of file xpfrgn.cpp.

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);