#include <opcntr.h>
Inheritance diagram for ConvertPathToShapesBecomeA:
Public Member Functions | |
ConvertPathToShapesBecomeA (BecomeAReason Reason, CCRuntimeClass *pClass, UndoableOperation *pOp, BOOL Sel) | |
Constructor (initialises the path). | |
virtual BOOL | PassBack (NodeRenderableInk *pNewNode, NodeRenderableInk *pCreatedByNode, CCAttrMap *pAttrMap=NULL) |
void | GetSummedPath (Path *pPath) |
NodeRenderableInk * | GetContextNode () |
Having potentially converted brushes or strokes to shapes we need to retrieve them. This can take a couple of forms, depending on what was converted: 1 brush will return one group containing nodepaths of the brush objects >1 brush will return a group, with group children containing the brushes 1 or more brushes + 1 or more strokes will return a group Strokes ONLY - will return a nodepath, which will contain any other strokes as its siblings. | |
Private Attributes | |
Path | m_SummedPath |
NodeGroup * | m_pContextNode |
Definition at line 833 of file opcntr.h.
|
Constructor (initialises the path).
Definition at line 4644 of file opcntr.cpp. 04647 : BecomeA(Reason, pClass, pOp, Sel) 04648 { 04649 m_SummedPath.Initialise(); 04650 m_pContextNode = NULL; 04651 04652 }
|
|
Having potentially converted brushes or strokes to shapes we need to retrieve them. This can take a couple of forms, depending on what was converted: 1 brush will return one group containing nodepaths of the brush objects >1 brush will return a group, with group children containing the brushes 1 or more brushes + 1 or more strokes will return a group Strokes ONLY - will return a nodepath, which will contain any other strokes as its siblings.
Definition at line 4903 of file opcntr.cpp. 04904 { 04905 if (m_pContextNode == NULL) 04906 return NULL; 04907 04908 NodeRenderableInk* pRetNode = m_pContextNode; 04909 04910 // if the context node has no children then we have no brushes, only strokes, so return the first sibling 04911 if (pRetNode->FindFirstChild() == NULL) 04912 { 04913 // we will have inserted any strokes as siblings to the context node 04914 pRetNode = static_cast<NodeRenderableInk*>(pRetNode->FindNext()); 04915 if (pRetNode == NULL) 04916 { 04917 ERROR3("Urk, we don't seem to have anything to return in ConvertPathToShapesBecomeA::GetContextNode"); 04918 } 04919 // unhook the context node and delete it 04920 m_pContextNode->CascadeDelete(); 04921 delete m_pContextNode; 04922 } 04923 m_pContextNode = NULL; 04924 return pRetNode; 04925 }
|
|
Definition at line 843 of file opcntr.h. 00843 { pPath->CloneFrom(m_SummedPath); }
|
|
DY 28/11/2000 This has been changed to deal with what gets passed back by brush and stroke attributes. So basically there are three cases: 1) No brush or stroke attributes applied: Easy, we just add the paths to the summed path that we are storing. 2) Stroke attribute applied: We ask the stroke for its stroked path and store it as a sibling to our context node. 3) Brush applied: Somewhat more complex - the BrushBecomeAGroup does pretty much what its name suggests, and we store the returned group under the context node. Recall that if both a brush and a stroke are applied then the stroke acts as a pressure provider to the brush. Reimplemented from BecomeA. Definition at line 4679 of file opcntr.cpp. 04682 { 04683 // continuity checks 04684 if (!pNewNode || !pCreatedByNode) 04685 { 04686 ERROR3("The new node or the created by node is NULL"); 04687 return FALSE; 04688 } 04689 04690 if (!pNewNode->IsNodePath()) 04691 { 04692 ERROR3("New node isn't a node path"); 04693 return FALSE; 04694 } 04695 04696 // if (!GetUndoOp()) 04697 // { 04698 // ERROR3("No operation defined"); 04699 // return FALSE; 04700 // } 04701 04702 // first, if we've not been given an attribute map, then create one 04703 if (!pAttrMap) 04704 { 04705 CCAttrMap * pXMap = CCAttrMap::MakeAppliedAttrMap(pCreatedByNode); 04706 04707 pAttrMap = pXMap->Copy(); 04708 04709 delete pXMap; 04710 04711 // exit if we don't have an attribute map 04712 if (!pAttrMap) 04713 { 04714 pNewNode->DeleteChildren(pNewNode->FindFirstChild()); 04715 delete pNewNode; 04716 ERROR3("Couldn't create attribute map"); 04717 return FALSE; 04718 } 04719 } 04720 NodePath * pPathNode = NULL; 04721 // Pre release bodge - DY 15/11 Brush attributes should really be catered for in MakeNodePathFromAttributes 04722 // but that has too many potential knock-on effects for me to test now 04723 AttrBrushType* pAttrBrush = NULL; 04724 pAttrMap->Lookup(CC_RUNTIME_CLASS(AttrBrushType), (void*&)pAttrBrush); 04725 if (pAttrBrush && pAttrBrush->GetBrushHandle() != BrushHandle_NoBrush) 04726 { 04727 //Turn the brush into a group with lots of nodepaths 04728 BrushBecomeAGroup BecomeA(BECOMEA_PASSBACK, CC_RUNTIME_CLASS(NodePath), GetUndoOp()); 04729 pAttrBrush->DoBecomeA(&BecomeA, pCreatedByNode); 04730 04731 // the brush will create a group out of itself and we want to retrieve that 04732 NodeGroup* pBrushGroup = BecomeA.GetNodeGroup(); 04733 if (pBrushGroup != NULL) 04734 { 04735 if (m_pContextNode == NULL) 04736 { 04737 m_pContextNode = pBrushGroup; 04738 } 04739 else 04740 { 04741 // insert as the last sibling 04742 Node* pNode = m_pContextNode; 04743 Node* pNext = NULL; 04744 while (pNode) 04745 { 04746 pNext = pNode->FindNext(); 04747 if (pNext == NULL) 04748 pBrushGroup->AttachNode(pNode, NEXT); 04749 pNode = pNext; 04750 } 04751 } 04752 } 04753 else 04754 ERROR3("Failed to create node group!"); 04755 04756 pAttrMap->DeleteAttributes(); 04757 delete pAttrMap; 04758 delete pNewNode; 04759 return TRUE; 04760 } 04761 04762 // likewise if we have an active stroke attribute 04763 AttrStrokeType* pStroke = NULL; 04764 pAttrMap->Lookup(CC_RUNTIME_CLASS(AttrStrokeType), (void*&)pStroke); 04765 AttrVariableWidth* pVarWidth = NULL; 04766 pAttrMap->Lookup(CC_RUNTIME_CLASS(AttrVariableWidth), (void*&)pVarWidth); 04767 04768 if (pStroke && pStroke->HasPathProcessor() && pVarWidth && pVarWidth->HasActiveValueFunction()) 04769 { 04770 PathProcessorStroke* pPPS = pStroke->GetPathProcessor(); 04771 Path* pPath = &((NodePath*)pNewNode)->InkPath; 04772 NodePath* pStrokedPath = pPPS->GetSmoothProcessedPath(pPath, pCreatedByNode); 04773 04774 if (pStrokedPath) 04775 { 04776 // if we don't have a context node then make one 04777 if (m_pContextNode == NULL) 04778 { 04779 ALLOC_WITH_FAIL(m_pContextNode, new NodeGroup, GetUndoOp()); 04780 if (m_pContextNode == NULL) 04781 { 04782 delete pStrokedPath; 04783 return FALSE; 04784 } 04785 } 04786 04787 // Karim 05/12/2000 04788 // process the returned stroke, to change its working 04789 // winding rule from non-zero to even-odd. 04790 Path* pInkStrokePath = &(pStrokedPath->InkPath); 04791 double Flatness = pInkStrokePath->CalculateFlatnessValueFromPath(750.0, 2.0, 375.0); 04792 pInkStrokePath->ClipPathToPath(*pInkStrokePath, pInkStrokePath, 3 | 0x10, 20, Flatness, Flatness); 04793 04794 // bit of a hack here, but it avoids some code duplication. Basically OpConvertPathToShapes 04795 // has a really handy function doing all the things you need to do when converting a stroked shape 04796 // to a path, so we're going to assume that our undo op is definitely an OpConvertPathToShapes. 04797 UndoableOperation* pOp = GetUndoOp(); 04798 if (pOp == NULL || pOp->IsKindOf(CC_RUNTIME_CLASS(OpConvertPathToShapes))) 04799 { 04800 OpConvertPathToShapes* pConvert = (OpConvertPathToShapes*)pOp; 04801 04802 OpConvertPathToShapes::AdjustStrokeAndFillAttrs(pConvert, pStrokedPath, NULL, pAttrMap); 04803 } 04804 // insert as the last sibling 04805 Node* pNode = m_pContextNode; 04806 Node* pNext = NULL; 04807 while (pNode) 04808 { 04809 pNext = pNode->FindNext(); 04810 if (pNext == NULL) 04811 pStrokedPath->AttachNode(pNode, NEXT); 04812 pNode = pNext; 04813 } 04814 pAttrMap->DeleteAttributes(); 04815 delete pAttrMap; 04816 delete pNewNode; 04817 return TRUE; 04818 } 04819 } 04820 04821 04822 04823 // This deals with the case if we have neither a brush or stroke attribute, 04824 // simply sum the paths. 04825 04826 double Flatness = ((NodePath *)pNewNode)->InkPath.CalculateFlatnessValueFromPath(750.0, 1.0, 375.0); 04827 pPathNode = ((NodePath *)pNewNode)->MakeNodePathFromAttributes(Flatness, pAttrMap, TRUE); 04828 04829 // ensure that the path is correct by clipping it 04830 Path BlankPath; 04831 BlankPath.Initialise(); 04832 04833 Path ClipPath; 04834 ClipPath.Initialise(); 04835 04836 // delete the new node 04837 pNewNode->DeleteChildren(pNewNode->FindFirstChild()); 04838 delete pNewNode; 04839 04840 pAttrMap->DeleteAttributes(); 04841 delete pAttrMap; 04842 04843 if (!pPathNode) 04844 { 04845 return FALSE; 04846 } 04847 /* 04848 // smooth the new node's path 04849 double Error = SMOOTH_MIN + (SMOOTH_MAX - SMOOTH_MIN)*pow((35/100), 3.0); 04850 04851 FitCurveNoChangeGeometry::SmoothPath(&(pPathNode->InkPath), Error); 04852 */ 04853 DocRect dr1(0,0,0,0); 04854 DocRect dr2(0,0,0,0); 04855 04856 m_SummedPath.GetTrueBoundingRect(&dr1); 04857 pPathNode->InkPath.GetTrueBoundingRect(&dr2); 04858 04859 // now, let's add this node to the become A path 04860 // if (m_SummedPath.GetBoundingRect().IsIntersectedWith(pPathNode->InkPath.GetBoundingRect())) MRH 19/5/00 04861 if (dr1.IsIntersectedWith(dr2)) 04862 { 04863 Path OrigPath; 04864 OrigPath.Initialise(); 04865 OrigPath.CloneFrom(m_SummedPath); 04866 04867 m_SummedPath.ClearPath(); 04868 04869 OrigPath.ClipPathToPath(pPathNode->InkPath, &m_SummedPath, 7 | CLIPPING_CLIP_WINDING, 04870 50, 50, 50); 04871 } 04872 else 04873 { 04874 m_SummedPath.MergeTwoPaths(pPathNode->InkPath); 04875 } 04876 04877 delete pPathNode; 04878 04879 return TRUE; 04880 }
|
|
|
|
|