00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 #include "camtypes.h"
00104 #include "nodepath.h"
00105
00106 #include <math.h>
00107
00108
00109
00110 #include "blobs.h"
00111 #include "contmenu.h"
00112 #include "lineattr.h"
00113 #include "ophist.h"
00114 #include "opbreak.h"
00115 #include "pathedit.h"
00116 #include "snap.h"
00117 #include "pathops.h"
00118 #include "nodetxts.h"
00119 #include "saveeps.h"
00120
00121
00122 #include "cxftags.h"
00123 #include "cxfile.h"
00124
00125 #include "rechpath.h"
00126
00127
00128
00129
00130
00131
00132 #include "gclips.h"
00133
00134
00135 #include "extender.h"
00136 #include "ngcore.h"
00137
00138 #include "gdraw.h"
00139
00140 #include "brshattr.h"
00141 #include "qualattr.h"
00142
00143
00144 #include "nodebldr.h"
00145
00146
00147 #include "gblend.h"
00148 #include "blndhelp.h"
00149 #include "opdrbrsh.h"
00150 #include "rsmooth.h"
00151 #include "strkattr.h"
00152 #include "ppstroke.h"
00153 #include "nodeclip.h"
00154 #include "attrmap.h"
00155
00156
00157 DECLARE_SOURCE( "$Revision: 1688 $" );
00158
00159 CC_IMPLEMENT_DYNCREATE( NodePath, NodeRenderableInk )
00160
00161 CC_IMPLEMENT_DYNAMIC(PathRecordHandler,CamelotRecordHandler)
00162 CC_IMPLEMENT_DYNAMIC(PathFlagsRecordHandler,CamelotRecordHandler)
00163
00164
00165 #define new CAM_DEBUG_NEW
00166 #define CONVERTSTROKES
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 NodePath::NodePath(Node* ContextNode,
00217 AttachNodeDirection Direction,
00218 BOOL Locked,
00219 BOOL Mangled,
00220 BOOL Marked,
00221 BOOL Selected
00222 ):NodeRenderableInk(ContextNode, Direction, Locked, Mangled, Marked, Selected )
00223 {
00224 CurrentRotation = 0.0;
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 NodePath::NodePath(): NodeRenderableInk()
00252 {
00253 CurrentRotation = 0.0;
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 BOOL NodePath::IsNodePath() const
00272 {
00273 return TRUE;
00274 }
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 BOOL NodePath::SetUpPath(INT32 RequiredSize, INT32 BlockSize)
00297 {
00298 CurrentRotation = 0.0;
00299 return (InkPath.Initialise(RequiredSize, BlockSize));
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 #ifdef _DEBUG
00314 void NodePath::ShowDebugTreeDetails() const
00315 {
00316 TRACE( _T("Path "));
00317
00318
00319 NodeRenderableInk::ShowDebugTreeDetails();
00320
00321
00322 }
00323 #endif
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 void NodePath::GetDebugDetails( StringBase* Str )
00337 {
00338 #ifdef _DEBUG
00339
00340 NodeRenderableInk::GetDebugDetails( Str );
00341
00342 InkPath.FindStartOfPath();
00343 String_256 TempStr;
00344
00345 (*Str) += TEXT( "\r\nPath Data Dump\r\n" );
00346 TempStr._MakeMsg( TEXT( "#1%ld bytes used\r\n"), InkPath.GetPathByteLength() );
00347 (*Str) += TempStr;
00348
00349 #if !defined(EXCLUDE_FROM_RALPH)
00350 DocRect BlobRect = GetBlobBoundingRect();
00351 TempStr._MakeMsg( TEXT("Blob Bounding Rect :-\r\n\t#1%ld,\t#2%ld\r\n\t#3%ld,\t#4%ld\r\n"),
00352 BlobRect.lo.x, BlobRect.lo.y, BlobRect.hi.x, BlobRect.hi.y );
00353 (*Str) += TempStr;
00354 #endif
00355
00356 TempStr._MakeMsg(TEXT("The Path is #1%sFilled and #2%sStroked\r\n"), InkPath.IsFilled ? "" : "not ", InkPath.IsStroked ? "" : "not ");
00357 (*Str) += TempStr;
00358
00359 (*Str) += TEXT( "\r\nNum\tType\tX Coord\tY Coord\r\n" );
00360 PathVerb* Verbs = InkPath.GetVerbArray();
00361 DocCoord* Coords = InkPath.GetCoordArray();
00362 PathFlags* Flags = InkPath.GetFlagArray();
00363 INT32 numcoords = InkPath.GetNumCoords();
00364 for (INT32 i=0; i<numcoords; i++)
00365 {
00366
00367 TempStr._MakeMsg( TEXT("#1%d.\t#2%d\t#3%ld,\t#4%ld\t"),
00368 i, Verbs[i], Coords[i].x, Coords[i].y );
00369
00370
00371 if (Flags[i].IsSmooth)
00372 TempStr += TEXT("S");
00373
00374 if (Flags[i].IsRotate)
00375 TempStr += TEXT("R");
00376
00377 if (Flags[i].IsEndPoint)
00378 TempStr += TEXT("E");
00379
00380 if (Flags[i].IsSelected)
00381 TempStr += TEXT("(sel)");
00382
00383 TempStr += TEXT("\r\n");
00384
00385 (*Str) += TempStr;
00386
00387 }
00388 #endif
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 UINT32 NodePath::GetNodeSize() const
00408 {
00409 return (sizeof(NodePath)+InkPath.GetPathByteLength());
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 Node* NodePath::SimpleCopy()
00426 {
00427
00428 NodePath* NodeCopy = new NodePath();
00429 if (NodeCopy)
00430 CopyNodeContents(NodeCopy);
00431
00432 return NodeCopy;
00433 }
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 void NodePath::CopyNodeContents( NodePath* NodeCopy)
00451 {
00452 NodeRenderableInk::CopyNodeContents( NodeCopy );
00453
00454
00455 if (NodeCopy->InkPath.Initialise(InkPath.GetNumCoords(),12))
00456 NodeCopy->InkPath.CopyPathDataFrom(&InkPath);
00457 }
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 void NodePath::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
00475 {
00476 ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node");
00477 ENSURE(IS_A(pNodeCopy, NodePath), "PolyCopyNodeContents given wrong dest node type");
00478
00479 if (IS_A(pNodeCopy, NodePath))
00480 CopyNodeContents((NodePath*)pNodeCopy);
00481 }
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496 void NodePath::Render(RenderRegion* pRender)
00497 {
00498
00499 TRACEUSER( "Diccon", _T("Rendering nodepath\n"));
00500 pRender->DrawPath(&InkPath);
00501 }
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 void NodePath::RenderEorDrag( RenderRegion* pRender )
00518 {
00519
00520
00521
00522
00523 pRender -> DrawPath( &InkPath );
00524 }
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539 void NodePath::RenderObjectBlobs(RenderRegion* pRender)
00540 {
00541
00542 Spread* pSpread = FindParentSpread();
00543 ENSURE(pSpread != NULL, "NodePath does not have a parent spread");
00544
00545
00546 if (pSpread!=NULL)
00547 InkPath.RenderPathBlobs(pRender);
00548
00549
00550
00551 NodeAttribute* pAttr = NULL;
00552 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBrushType), &pAttr);
00553 if (pAttr!= NULL)
00554 {
00555 if (((AttrBrushType*)pAttr)->GetBrushHandle() != BrushHandle_NoBrush)
00556 {
00557
00558
00559
00560
00561 {
00562 View* pRenderView = NULL;
00563 pRenderView = pRender->GetRenderView();
00564 if(pRenderView != NULL)
00565 {
00566 Quality viewQuality = pRenderView->RenderQuality;
00567 if (viewQuality.GetBlendQuality() == Quality::FullBlend)
00568 {
00569 pRender->SetLineColour(COLOUR_BEZIERLINE);
00570 pRender->SetFillColour(COLOUR_NONE);
00571 pRender->DrawPath(&InkPath);
00572 }
00573 }
00574 }
00575 }
00576 }
00577 }
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590 void NodePath::RenderPenBlobs(RenderRegion* pRender)
00591 {
00592
00593 Spread* pSpread = FindParentSpread();
00594 ENSURE(pSpread != NULL, "NodePath does not have a parent spread");
00595
00596
00597 if (pSpread!=NULL)
00598 InkPath.RenderPathPenBlobs(pSpread);
00599 }
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613 void NodePath::RenderTinyBlobs(RenderRegion* pRender)
00614 {
00615
00616 pRender->SetLineColour(COLOUR_NONE);
00617 pRender->SetFillColour(COLOUR_UNSELECTEDBLOB);
00618
00619
00620 DocCoord* Coords = InkPath.GetCoordArray();
00621 pRender->DrawBlob(Coords[0], BT_UNSELECTED);
00622 }
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640 ChangeCode NodePath::OnChildChange(ObjChangeParam* pParam)
00641 {
00642
00643 NodeAttribute* pAttr = NULL;
00644 AttrBrushType* pAttrBrush = NULL;
00645 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBrushType), &pAttr);
00646 if (pAttr!= NULL)
00647 {
00648 pAttrBrush = (AttrBrushType*)pAttr;
00649
00650
00651 UpdateBrushAction* pAction;
00652 UndoableOperation* pOp = pParam->GetOpPointer();
00653 if (pOp != NULL)
00654 UpdateBrushAction::Init(pOp, pOp->GetUndoActionList(), this, &pAction);
00655 }
00656 return CC_OK;
00657 }
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670 void NodePath::ClearSubSelection(Spread* pSpread)
00671 {
00672 #if !defined(EXCLUDE_FROM_RALPH)
00673 ENSURE( pSpread!=NULL, "Parent Spread was NULL in NodePath::ClearSubSelection" );
00674
00675 if ((pSpread!=NULL) && (InkPath.IsSubSelection()))
00676 {
00677 InkPath.RenderPathBlobs(pSpread);
00678 InkPath.ClearSubSelection();
00679 InkPath.RenderPathBlobs(pSpread);
00680 }
00681 #endif
00682 }
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 BOOL NodePath::OnClick( DocCoord PointerPos, ClickType Click,
00707 ClickModifiers ClickMods, Spread *pSpread )
00708 {
00709 #ifndef STANDALONE
00710
00711 DocRect BlobRect;
00712 DocCoord* Coords = InkPath.GetCoordArray();
00713 PathFlags* Flags = InkPath.GetFlagArray();
00714
00715
00716
00717 DocView *pDocView = DocView::GetSelected();
00718 ERROR3IF(pDocView == NULL, "NodePath::OnClick: Could not get selected DocView");
00719 if (pDocView == NULL)
00720 return FALSE;
00721
00722
00723 BlobManager* pBlobMgr = GetApplication()->GetBlobManager();
00724 if (pBlobMgr == NULL)
00725 return FALSE;
00726 if (!pBlobMgr->GetCurrentInterest().Object)
00727 return FALSE;
00728
00729 INT32 NumCoords = InkPath.GetNumCoords();
00730 INT32 i;
00731 if (InkPath.FindNearestPoint( PointerPos,
00732 POINTFLAG_ENDPOINTS |
00733 POINTFLAG_CONTROLPOINTS |
00734 POINTFLAG_ENDSFIRST,
00735 &i)
00736 )
00737 {
00738
00739 if ( Click == CLICKTYPE_SINGLE )
00740 {
00741
00742
00743 if (Flags[i].IsEndPoint)
00744 {
00745 if (ClickMods.Adjust && ClickMods.Constrain)
00746 {
00747 HandleBlobClick(Coords, Flags, i, NumCoords, TRUE, TRUE);
00748 }
00749 else
00750 {
00751 if ((!Flags[i].IsSelected) || ((Flags[i].IsSelected) && (ClickMods.Adjust)))
00752 {
00753 HandleBlobClick(Coords, Flags, i, NumCoords, ClickMods.Adjust, FALSE);
00754 }
00755 else
00756 {
00757
00758
00759
00760 if (Flags[i].IsSelected && !ClickMods.Menu)
00761 {
00762 OpNodePathEditBlob* pOpNodePath = new OpNodePathEditBlob;
00763 if (pOpNodePath == NULL)
00764 InformError();
00765 else
00766 pOpNodePath->DoStartDragEdit(this, Coords[i], pSpread);
00767 }
00768 }
00769 }
00770 }
00771 else
00772 {
00773
00774 }
00775 }
00776
00777 if ( Click == CLICKTYPE_DOUBLE)
00778 {
00779
00780
00781
00782 if (Flags[i].IsSelected && Flags[i].IsEndPoint)
00783 {
00784
00785 OpToggleSmooth* pOpToggle = new OpToggleSmooth;
00786 if (!pOpToggle)
00787 {
00788
00789 InformError();
00790 }
00791 else
00792 {
00793
00794 pOpToggle->DoTogglePoint(this, i, pSpread, FALSE, !ClickMods.Constrain);
00795 }
00796 }
00797 }
00798
00799
00800 if ( Click == CLICKTYPE_DRAG && !ClickMods.Menu )
00801 {
00802
00803
00804 {
00805 if (Flags[i].IsEndPoint)
00806 {
00807
00808
00809 OpNodePathEditBlob* pOpNodePath = new OpNodePathEditBlob;
00810 if (pOpNodePath == NULL)
00811 {
00812
00813 InformError();
00814 }
00815 else
00816 {
00817
00818
00819
00820
00821
00822 pOpNodePath->DoStartDragEdit(this, Coords[i], pSpread);
00823 }
00824 }
00825 else
00826 {
00827
00828
00829 OpNodePathEditControlBlob* pOpNodePath = new OpNodePathEditControlBlob;
00830 if (pOpNodePath==NULL)
00831 {
00832
00833 InformError();
00834 }
00835 else
00836 {
00837
00838
00839
00840
00841
00842 pOpNodePath->DoStartDragEdit(this, Coords[i], pSpread, i);
00843 }
00844 }
00845 }
00846 }
00847
00848 return TRUE;
00849 }
00850
00851 #endif
00852
00853 return FALSE;
00854 }
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873 BOOL NodePath::OnBlobPopUp(Spread* pSpread, DocCoord PointerPos, ContextMenu* pMenu)
00874 {
00875 #if !defined(EXCLUDE_FROM_RALPH)
00876 DocRect BlobRect;
00877
00878
00879
00880
00881
00882 DocView *pDocView = DocView::GetSelected();
00883 ERROR3IF(pDocView == NULL, "NodePath::OnClick: Could not get selected DocView");
00884 if (pDocView == NULL)
00885 return FALSE;
00886
00887
00888
00889 if (!InkPath.IsSubSelection())
00890 return FALSE;
00891
00892
00893 INT32 i;
00894 if (InkPath.FindNearestPoint( PointerPos,
00895 POINTFLAG_ENDPOINTS |
00896 POINTFLAG_CONTROLPOINTS |
00897 POINTFLAG_ENDSFIRST,
00898 &i)
00899 )
00900 {
00901 pMenu->BuildCommand(TOOL_OPTOKEN_BEZTOOL, TRUE);
00902
00903 pMenu->BuildCommand(OPTOKEN_MAKELINESOP);
00904 pMenu->BuildCommand(OPTOKEN_MAKECURVESOP, TRUE);
00905
00906 pMenu->BuildCommand(OPTOKEN_DELETEPOINTSOP);
00907 pMenu->BuildCommand(OPTOKEN_BREAKATPOINTS, TRUE);
00908
00909 pMenu->BuildCommand(OPTOKEN_SELECTALLPATHPOINTS);
00910 pMenu->BuildCommand(OPTOKEN_DESELECTALLPATHPOINTS, TRUE);
00911
00912 return TRUE;
00913 }
00914
00915 #endif
00916
00917 return FALSE;
00918 }
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936 BOOL NodePath::OnNodePopUp(Spread* pSpread, DocCoord PointerPos, ContextMenu* pMenu)
00937 {
00938 #if !defined(EXCLUDE_FROM_RALPH)
00939 BOOL ok = TRUE;
00940
00941 ok = ok && pMenu->BuildCommand(TOOL_OPTOKEN_BEZTOOL, TRUE);
00942
00943 return ok;
00944 #else
00945 return FALSE;
00946 #endif
00947 }
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971 void NodePath::HandleBlobClick(DocCoord* Coords, PathFlags* Flags, INT32 Pos, INT32 NumCoords,
00972 BOOL Adjust, BOOL Constrain)
00973 {
00974 #if !defined(EXCLUDE_FROM_RALPH)
00975 PathVerb* Verbs = InkPath.GetVerbArray();
00976
00977
00978 if (!Adjust && !Constrain)
00979 {
00980 SelRange* Selected = GetApplication()->FindSelection();
00981 Node* pNode = Selected->FindFirst();
00982 while (pNode!=NULL)
00983 {
00984 if ((pNode!=this) && (pNode->IsKindOf(CC_RUNTIME_CLASS(NodePath))))
00985 {
00986
00987 NodePath* pNodePath = (NodePath*) pNode;
00988 if (pNodePath->InkPath.IsSubSelection())
00989 {
00990 Spread* pSpread = pNodePath->FindParentSpread();
00991 ENSURE(pSpread!=NULL, "Node did not have a parent spread in NodePath::HandleBlobClick");
00992 if (pSpread!=NULL)
00993 {
00994 pNodePath->InkPath.RenderPathSelectedControlBlobs(pSpread);
00995 pNodePath->InkPath.ClearSubSelection();
00996 pNodePath->InkPath.RenderPathSelectedControlBlobs(pSpread);
00997 }
00998 }
00999 }
01000
01001
01002 pNode = Selected->FindNext(pNode);
01003 }
01004 }
01005
01006
01007
01008 BOOL NewSelState;
01009 BOOL OldSelState = Flags[Pos].IsSelected;
01010 if (OldSelState)
01011 NewSelState = FALSE;
01012 else
01013 NewSelState = TRUE;
01014
01015 Spread *pSpread = FindParentSpread();
01016 ENSURE(pSpread != NULL, "NodePath does not have a parent spread");
01017
01018
01019 InkPath.RenderPathSelectedControlBlobs(pSpread);
01020
01021
01022 if (!Adjust && !Constrain)
01023 InkPath.ClearSubSelection();
01024
01025
01026 if (Adjust && Constrain)
01027 {
01028 BOOL NewSelState = !Flags[Pos].IsSelected;
01029 for (INT32 loop = 0; loop < InkPath.GetNumCoords(); loop++)
01030 {
01031 Flags[loop].IsSelected = NewSelState;
01032 }
01033 }
01034 else
01035 {
01036
01037 Flags[Pos].IsSelected = NewSelState;
01038
01039 if ((Pos>0) && (!Flags[Pos-1].IsEndPoint))
01040 {
01041
01042 Flags[Pos-1].IsSelected = NewSelState;
01043 }
01044
01045
01046 if ((Pos+1<NumCoords) && (!Flags[Pos+1].IsEndPoint))
01047 {
01048
01049 Flags[Pos+1].IsSelected = NewSelState;
01050 }
01051
01052
01053
01054
01055 if (Verbs[Pos] == PT_MOVETO)
01056 {
01057 INT32 j;
01058
01059 for (j=Pos+1;j<NumCoords && Verbs[j] != PT_MOVETO;j++);
01060 j--;
01061 if (Verbs[j] & PT_CLOSEFIGURE)
01062 {
01063
01064 Flags[j].IsSelected = NewSelState;
01065
01066 if ((j>0) && (!Flags[j-1].IsEndPoint))
01067 {
01068
01069 Flags[j-1].IsSelected = NewSelState;
01070 }
01071 }
01072
01073 }
01074 }
01075
01076 InkPath.RenderPathSelectedControlBlobs(pSpread);
01077 #endif
01078 }
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097 void NodePath::Transform( TransformBase& Trans )
01098 {
01099
01100 Trans.Transform( (DocCoord*)InkPath.GetCoordArray(), InkPath.GetNumCoords() );
01101
01102
01103 InvalidateBoundingRect();
01104
01105
01106 TransformChildren(Trans);
01107
01108
01109
01110 }
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130 String NodePath::Describe(BOOL Plural, BOOL Verbose)
01131 {
01132
01133 if (InkPath.IsSubPathClosed(0))
01134 {
01135 if (Plural)
01136 return(String(_R(IDS_DESCRIBE_SHAPES)));
01137 else
01138 return(String(_R(IDS_DESCRIBE_SHAPE)));
01139 }
01140 else
01141 {
01142 if (Plural)
01143 return(String(_R(IDS_PATH_DESCRP)));
01144 else
01145 return(String(_R(IDS_PATH_DESCRS)));
01146 }
01147 };
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167 DocRect NodePath::GetBoundingRect(BOOL DontUseAttrs, BOOL HitTest)
01168 {
01169
01170 if (!IsBoundingRectValid || DontUseAttrs)
01171 {
01172
01173 DocRect NewBoundingRect;
01174
01175
01176 if (!CalculatePathBoundingRect(InkPath, DontUseAttrs, &NewBoundingRect))
01177 {
01178
01179
01180 NewBoundingRect = InkPath.GetBoundingRect();
01181 }
01182
01183
01184
01185 if (NewBoundingRect.Width() == 0)
01186 NewBoundingRect.hi.x++;
01187 if (NewBoundingRect.Height() == 0)
01188 NewBoundingRect.hi.y++;
01189
01190
01191 if (DontUseAttrs)
01192 {
01193
01194 return NewBoundingRect;
01195 }
01196 else
01197 {
01198
01199
01200
01201 CCAttrMap AttribMap(30);
01202 if (FindAppliedAttributes(&AttribMap))
01203 {
01204 void* pType;
01205 void* pVal;
01206
01207
01208 CCAttrMap::iterator end = AttribMap.GetEndPosition();
01209 for( CCAttrMap::iterator Pos = AttribMap.GetStartPosition(); Pos != end; ++Pos )
01210 {
01211
01212 pType = Pos->first;
01213 pVal = Pos->second;
01214
01215 if (pVal != NULL)
01216 {
01217 if ( ((NodeAttribute*)pVal)->EffectsParentBounds() )
01218 {
01219
01220
01221 DocRect AttrBounds =
01222 ((NodeAttribute*)pVal)->GetAttrBoundingRect(this, &AttribMap);
01223 NewBoundingRect = NewBoundingRect.Union(AttrBounds);
01224 }
01225 }
01226 }
01227 }
01228
01229
01230 BoundingRectangle = NewBoundingRect;
01231
01232
01233 IsBoundingRectValid = TRUE;
01234 }
01235 }
01236
01237
01238 return BoundingRectangle;
01239 }
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256 DocRect NodePath::GetBlobBoundingRect()
01257 {
01258
01259 PathVerb* Verbs = InkPath.GetVerbArray();
01260 PathFlags* Flags = InkPath.GetFlagArray();
01261 DocCoord* Coords = InkPath.GetCoordArray();
01262 INT32 NumCoords = InkPath.GetNumCoords();
01263
01264 DocRect BlobRect;
01265 DocRect Rect;
01266
01267
01268 BlobManager* BlobMgr = GetApplication()->GetBlobManager();
01269 if (BlobMgr==NULL)
01270 return GetBoundingRect();
01271
01272
01273 for (INT32 i=0; i<NumCoords; i++)
01274 {
01275 if (i==0)
01276 {
01277
01278 Rect = DocRect(Coords[0].x, Coords[0].y,
01279 Coords[0].x + 1L, Coords[0].y + 1L);
01280 }
01281 else
01282 {
01283
01284 Rect.IncludePoint(Coords[i]);
01285 }
01286 }
01287
01288
01289 BlobMgr->GetBlobRect(Rect.lo, &BlobRect);
01290 Rect = Rect.Union(BlobRect);
01291 BlobMgr->GetBlobRect(Rect.hi, &BlobRect);
01292 Rect = Rect.Union(BlobRect);
01293
01294
01295
01296
01297 BlobStyle Blobs = BlobMgr->GetCurrentInterest(TRUE);
01298 if (Blobs.Pen)
01299 {
01300
01301
01302
01303
01304 PathVerb LastVerb = Verbs[NumCoords-1];
01305 PathFlags LastFlag = Flags[NumCoords-1];
01306
01307 if ((LastVerb == PT_BEZIERTO) && (LastFlag.IsRotate))
01308 {
01309 DocCoord Pt0 = Coords[NumCoords-2];
01310 DocCoord Pt1 = Coords[NumCoords-1];
01311
01312 DocCoord GhostPt;
01313 GhostPt.x = Pt1.x - (Pt0.x - Pt1.x);
01314 GhostPt.y = Pt1.y - (Pt0.y - Pt1.y);
01315
01316 BlobMgr->GetBlobRect(GhostPt,&BlobRect);
01317 Rect = Rect.Union(BlobRect);
01318 }
01319 }
01320
01321
01322 IncludeChildrensBoundingRects(&Rect);
01323
01324
01325 return Rect;
01326 }
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358 BOOL NodePath::CanBecomeA(BecomeA* pBecomeA)
01359 {
01360 if (pBecomeA->BAPath())
01361 {
01362 pBecomeA->AddCount(1);
01363
01364 return TRUE;
01365 }
01366
01367 return FALSE;
01368 }
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388 BOOL NodePath::DoBecomeA(BecomeA* pBecomeA)
01389 {
01390
01391 ERROR2IF_PF(pBecomeA == NULL,FALSE,("pBecomeA is NULL"));
01392
01393
01394
01395 BOOL ValidReason = (pBecomeA->GetReason() == BECOMEA_REPLACE || pBecomeA->GetReason() == BECOMEA_PASSBACK);
01396 ERROR2IF_PF(!ValidReason,FALSE,("Unkown BecomeA reason %d",pBecomeA->GetReason()));
01397
01398 BOOL Success = TRUE;
01399 NodePath* pNewNodePath = NULL;
01400
01401 if (pBecomeA->BAPath())
01402 {
01403 switch (pBecomeA->GetReason())
01404 {
01405 case BECOMEA_REPLACE:
01406
01407
01408 pBecomeA->PassBack(this, this);
01409 break;
01410
01411 case BECOMEA_PASSBACK :
01412 {
01413
01414 CALL_WITH_FAIL(((pNewNodePath = (NodePath*)SimpleCopy()) != NULL), pBecomeA->GetUndoOp(), Success);
01415
01416
01417 if (Success) Success = pBecomeA->PassBack(pNewNodePath,this);
01418 }
01419 break;
01420 default: break;
01421 }
01422 }
01423
01424 if (!Success)
01425 {
01426 if (pNewNodePath != NULL)
01427 {
01428
01429
01430 pNewNodePath->CascadeDelete();
01431 delete pNewNodePath;
01432 pNewNodePath = NULL;
01433 }
01434 }
01435
01436 return Success;
01437 }
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460 NodePath* NodePath::GetVariableWidthStrokePath()
01461 {
01462
01463 AttrVariableWidth* pVarWidth = NULL;
01464 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrVariableWidth), (NodeAttribute**)&pVarWidth);
01465 if (pVarWidth && ((VariableWidthAttrValue*)pVarWidth->GetAttributeValue())->GetWidthFunction() == NULL)
01466 return NULL;
01467
01468
01469 AttrStrokeType* pStroke = NULL;
01470 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeType), (NodeAttribute**)&pStroke);
01471
01472 NodePath* pRetNode = NULL;
01473 if (pStroke && pStroke->HasPathProcessor())
01474 {
01475 PathProcessorStroke* pPPS = pStroke->GetPathProcessor();
01476
01477 pRetNode = pPPS->GetProcessedPath(&InkPath, this);
01478 }
01479
01480 return pRetNode;
01481 }
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504 NodePath* NodePath::GetSmoothVariableWidthStrokePath()
01505 {
01506
01507 AttrVariableWidth* pVarWidth = NULL;
01508 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrVariableWidth), (NodeAttribute**)&pVarWidth);
01509 if (pVarWidth && ((VariableWidthAttrValue*)pVarWidth->GetAttributeValue())->GetWidthFunction() == NULL)
01510 return NULL;
01511
01512
01513 AttrStrokeType* pStroke = NULL;
01514 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeType), (NodeAttribute**)&pStroke);
01515
01516 NodePath* pRetNode = NULL;
01517 if (pStroke && pStroke->HasPathProcessor())
01518 {
01519 PathProcessorStroke* pPPS = pStroke->GetPathProcessor();
01520
01521 pRetNode = pPPS->GetSmoothProcessedPath(&InkPath, this);
01522 }
01523
01524 return pRetNode;
01525 }
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547 NodePath * NodePath::MakeNodePathFromAttributes(double Flatness, CCAttrMap * pAttrMap,
01548 BOOL bIncludeClosedPaths, BOOL IncludeWidth)
01549 {
01550
01551 AttrLineWidth * pAttrLineWidth = NULL;
01552 AttrStartArrow * pAttrStartArrow = NULL;
01553 AttrEndArrow * pAttrEndArrow = NULL;
01554 AttrJoinType * pAttrJoinType = NULL;
01555 AttrStartCap * pAttrStartCap = NULL;
01556 AttrDashPattern * pAttrDashPattern = NULL;
01557 AttrStrokeColour* pAttrStrokeColour = NULL;
01558 AttrStrokeType* pAttrStrokeType = NULL;
01559 AttrVariableWidth* pAttrVariableWidth = NULL;
01560
01561 if (!pAttrMap)
01562 {
01563
01564 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrLineWidth),(NodeAttribute **)(&pAttrLineWidth));
01565 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStartArrow),(NodeAttribute **)(&pAttrStartArrow));
01566 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrEndArrow),(NodeAttribute **)(&pAttrEndArrow));
01567 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrJoinType),(NodeAttribute **)(&pAttrJoinType));
01568 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStartCap),(NodeAttribute **)(&pAttrStartCap));
01569 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrDashPattern),(NodeAttribute **)(&pAttrDashPattern));
01570 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeColour),(NodeAttribute **)(&pAttrStrokeColour));
01571 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeType), (NodeAttribute **)(&pAttrStrokeType));
01572 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrVariableWidth), (NodeAttribute **)(&pAttrVariableWidth));
01573 }
01574 else
01575 {
01576
01577 pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrLineWidth), (void *&)pAttrLineWidth );
01578 pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStartArrow), (void *&)pAttrStartArrow );
01579 pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrEndArrow), (void *&)pAttrEndArrow);
01580 pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrJoinType), (void *&)pAttrJoinType);
01581 pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStartCap), (void *&)pAttrStartCap);
01582 pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrDashPattern), (void *&)pAttrDashPattern);
01583 pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStrokeColour), (void *&)pAttrStrokeColour);
01584 pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStrokeType), (void *&)pAttrStrokeType);
01585 pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrVariableWidth), (void *&)pAttrVariableWidth);
01586
01587 if (!pAttrLineWidth)
01588 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrLineWidth),(NodeAttribute **)(&pAttrLineWidth));
01589
01590 if (!pAttrStartArrow)
01591 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStartArrow),(NodeAttribute **)(&pAttrStartArrow));
01592
01593 if (!pAttrEndArrow)
01594 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrEndArrow), (NodeAttribute **)(&pAttrEndArrow));
01595
01596 if (!pAttrJoinType)
01597 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrJoinType),(NodeAttribute **)(&pAttrJoinType));
01598
01599 if (!pAttrStartCap)
01600 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStartCap),(NodeAttribute **)(&pAttrStartCap));
01601
01602 if (!pAttrDashPattern)
01603 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrDashPattern),(NodeAttribute **)(&pAttrDashPattern));
01604
01605 if (!pAttrStrokeColour)
01606 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeColour),(NodeAttribute **)(&pAttrStrokeColour));
01607
01608 if (!pAttrStrokeType)
01609 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeType), (NodeAttribute **)(&pAttrStrokeType));
01610
01611 if(!pAttrVariableWidth)
01612 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrVariableWidth), (NodeAttribute **)(&pAttrVariableWidth));
01613 }
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625 BOOL IsTransparentStroke = FALSE;
01626
01627 if(pAttrStrokeColour)
01628 {
01629 DocColour* pCol = pAttrStrokeColour->Value.GetStartColour();
01630 IsTransparentStroke = pCol->IsTransparent();
01631 }
01632
01633
01634 if (pAttrStrokeType && !IsTransparentStroke)
01635 {
01636
01637
01638 if(pAttrVariableWidth && ((VariableWidthAttrValue*)pAttrVariableWidth->GetAttributeValue())->GetWidthFunction() != NULL)
01639 {
01640
01641
01642 #ifdef CONVERTSTROKES // vector stroking in here
01643
01644 PathProcessorStroke* pPPS = pAttrStrokeType->GetPathProcessor();
01645 if (pPPS)
01646 {
01647 BOOL OriginalIsClosed = InkPath.IsClosed();
01648
01649 Path UnStrokedPath;
01650 UnStrokedPath.Initialise();
01651
01652 if(OriginalIsClosed)
01653 UnStrokedPath.CloneFrom(InkPath);
01654
01655
01656 Path ClonePath;
01657 ClonePath.Initialise();
01658 ClonePath.CloneFrom(InkPath);
01659
01660 ClonePath.IsFilled = FALSE;
01661 ClonePath.IsStroked = TRUE;
01662
01663
01664 NodePath* pNewNodePath = pPPS->GetSmoothProcessedPath(&ClonePath, this);
01665
01666 if (pNewNodePath == NULL)
01667 {
01668 ERROR3("Urk - Cannae get yer stroak path lassie");
01669 }
01670 else
01671 {
01672 double SFlat = pNewNodePath->InkPath.CalculateFlatnessValueFromPath(500.0,2.0,375.0);
01673 double CFlat = UnStrokedPath.CalculateFlatnessValueFromPath(500.0,2.0,375.0);
01674 DWORD ClipRule = OriginalIsClosed ? 7 : 3;
01675 if(UnStrokedPath.ClipPathToPath(pNewNodePath->InkPath,&pNewNodePath->InkPath,ClipRule|CLIPPING_SOURCE_WINDING,20,SFlat,CFlat) < 0)
01676 {
01677 ERROR3("Urk - Cannae get yer stroak path lassie");
01678 }
01679 }
01680
01681 return pNewNodePath;
01682 }
01683 #else
01684 if (RetroSmoothMe(Smooth))
01685 {
01686
01687 NodePath * pRetnNode = new NodePath;
01688 ERROR2IF(!pRetnNode,NULL,"Failed to create a new Path Node!");
01689 pRetnNode->InkPath.Initialise();
01690 pRetnNode->InkPath.CloneFrom(InkPath);
01691 return pRetnNode;
01692 }
01693 #endif
01694 }
01695 }
01696
01697
01698
01699
01700
01701
01702 NodePath * pRetnNode = new NodePath;
01703 ERROR2IF(!pRetnNode,NULL,"Failed to create a new Path Node!");
01704 pRetnNode->InkPath.Initialise();
01705
01706 Path SrcPath;
01707 SrcPath.Initialise();
01708 SrcPath.CloneFrom(InkPath);
01709
01710 DashPatternAttribute* pDashPattern = NULL;
01711 StartArrowAttribute* pStartArrow = NULL;
01712 LineWidthAttribute* pLineWidth = NULL;
01713 EndArrowAttribute* pEndArrow = NULL;
01714 JoinTypeAttribute* pJoinType = NULL;
01715 StartCapAttribute* pStartCap = NULL;
01716
01717
01718 if (pAttrLineWidth)
01719 pLineWidth = &(pAttrLineWidth->Value);
01720
01721 if (pAttrStartArrow)
01722 pStartArrow = &(pAttrStartArrow->Value);
01723
01724 if (pAttrEndArrow)
01725 pEndArrow = &(pAttrEndArrow->Value);
01726
01727 if (pAttrJoinType)
01728 pJoinType = &(pAttrJoinType->Value);
01729
01730 if (pAttrStartCap)
01731 pStartCap = &(pAttrStartCap->Value);
01732
01733 if (pAttrDashPattern)
01734 pDashPattern = &(pAttrDashPattern->Value);
01735
01736
01737 INT32 StartIndex = 0;
01738 INT32 EndIndex = 0;
01739
01740 Path SubPath;
01741 SubPath.Initialise();
01742
01743 Path FlatPath;
01744 FlatPath.Initialise();
01745
01746 UINT32 SubPathNum = 0;
01747 MILLIPOINT Width = 750;
01748 MILLIPOINT EndsWidth = 750;
01749
01750 if(pLineWidth != NULL)
01751 Width = EndsWidth = pLineWidth->LineWidth;
01752
01753 if(pAttrStrokeColour && pAttrStrokeColour->GetStartColour()->IsTransparent())
01754 {
01755 Width = 0;
01756 pDashPattern = NULL;
01757 }
01758
01759 JoinStyles JoinS = JOIN_ROUND;
01760
01761 if(pJoinType != NULL)
01762 JoinS = (pJoinType->JoinType == MitreJoin) ? JOIN_MITER : (pJoinType->JoinType == RoundJoin) ? JOIN_ROUND : JOIN_BEVEL;
01763
01765
01766 DashType* pDashRec = NULL;
01767 DashType GavinDash;
01768 GavinDash.Length = 0;
01769 GavinDash.Offset = 0;
01770 GavinDash.Array[0] = 0;
01771
01772
01773 if (pDashPattern && pDashPattern->DashPattern.Elements > 0 && pDashPattern->DashPattern.LineWidth > 0)
01774 {
01775 INT32 Length = pDashPattern->DashPattern.Elements;
01776
01777 if (Length > 8) Length = 8;
01778
01779 BOOL DoScale = pDashPattern->DashPattern.ScaleWithLineWidth;
01780 FIXED16 Scale = DoScale ? (double(Width) / double(pDashPattern->DashPattern.LineWidth)) : 1;
01781
01782 GavinDash.Length = Length;
01783 GavinDash.Offset = LongMulFixed16(pDashPattern->DashPattern.DashStart, Scale);
01784
01785 for (INT32 el = 0; el < Length; el++)
01786 {
01787 GavinDash.Array[el] = LongMulFixed16(pDashPattern->DashPattern.ElementData[el], Scale);
01788 }
01789 }
01790
01791
01792 pDashRec = &GavinDash;
01793
01795
01796
01797
01798 if(!IncludeWidth && pAttrStrokeColour && !pAttrStrokeColour->GetStartColour()->IsTransparent())
01799 Width = 50;
01800
01801 Path BlankPath;
01802 BlankPath.Initialise();
01803
01804 Path StrokedPath;
01805 StrokedPath.Initialise();
01806
01807 while (StartIndex < InkPath.GetNumCoords())
01808 {
01809
01810 EndIndex = StartIndex;
01811 InkPath.FindEndElOfSubPath(&EndIndex);
01812
01813
01814
01815 if (!InkPath.IsClosed() || bIncludeClosedPaths)
01816 {
01817
01818
01819 SubPath.ClearPath();
01820 InkPath.MakePathFromSubPath(SubPathNum, &SubPath);
01821 FlatPath.ClearPath();
01822 FlatPath.CloneFrom(SubPath);
01823
01824
01825 SrcPath.IsFilled = FALSE;
01826 SrcPath.IsStroked = FALSE;
01827
01828 if (pStartCap && pJoinType)
01829 {
01830 SubPath.StrokePathToPath(Width,
01831 pStartCap->StartCap,
01832 pJoinType->JoinType,
01833 pDashRec,
01834 &StrokedPath,
01835 Flatness,
01836 FALSE);
01837 }
01838 else
01839 {
01840 SubPath.StrokePathToPath(Width,
01841 LineCapRound,
01842 RoundJoin,
01843 pDashRec,
01844 &StrokedPath,
01845 Flatness,
01846 FALSE);
01847 }
01848
01849
01850 Path ClipPath;
01851 ClipPath.Initialise();
01852 ClipPath.CloneFrom(StrokedPath);
01853 StrokedPath.ClearPath();
01854
01855 if(ClipPath.ClipPathToPath(BlankPath, &StrokedPath, 6 | CLIPPING_CLIP_WINDING,30, Flatness, Flatness) < 2)
01856 StrokedPath.CloneFrom(ClipPath);
01857
01858
01859 INT32 Index = 0;
01860 DocCoord Centre;
01861 DocCoord Direction;
01862 Trans2DMatrix ArrowMatrix;
01863
01864 Path ArrowPath;
01865 ArrowPath.Initialise();
01866
01867 Path DestPathStartArrow;
01868 DestPathStartArrow.Initialise();
01869
01870 Path DestPathEndArrow;
01871 DestPathEndArrow.Initialise();
01872
01873 ClipPath.ClearPath();
01874
01875
01876 if (pStartArrow)
01877 {
01878 if (pStartArrow->StartArrow.GetArrowPath())
01879 {
01880 Centre = FlatPath.GetCoordArray()[0];
01881 Direction = FlatPath.GetCoordArray()[1];
01882
01883 pStartArrow->StartArrow.GetArrowMatrix(Centre, Direction,
01884 EndsWidth, &ArrowMatrix);
01885
01886
01887 ArrowPath.ClearPath();
01888 ArrowPath.CloneFrom(*pStartArrow->StartArrow.GetArrowPath());
01889
01890 ArrowMatrix.Transform(ArrowPath.GetCoordArray(), ArrowPath.GetNumCoords());
01891
01892 DestPathStartArrow.ClearPath();
01893 ClipPath.CloneFrom(StrokedPath);
01894 if(ClipPath.ClipPathToPath(ArrowPath,&StrokedPath, 7 | CLIPPING_SOURCE_WINDING,30, Flatness, Flatness) < 2)
01895 {
01896 TRACEUSER( "MarkH", _T("ClipFailed so copying path! NODEPATH\n"));
01897 }
01898
01899 pRetnNode->InkPath.MergeTwoPaths(DestPathStartArrow);
01900 }
01901 }
01902
01903
01904 if (pEndArrow)
01905 {
01906 if (pEndArrow->EndArrow.GetArrowPath())
01907 {
01908 Index = 0;
01909
01910 Centre = FlatPath.GetCoordArray()[FlatPath.GetNumCoords() - 1];
01911 Direction.x = FlatPath.GetCoordArray()[FlatPath.GetNumCoords() - 1].x -
01912 FlatPath.GetCoordArray()[FlatPath.GetNumCoords() - 2].x;
01913
01914 Direction.y = FlatPath.GetCoordArray()[FlatPath.GetNumCoords() - 1].y -
01915 FlatPath.GetCoordArray()[FlatPath.GetNumCoords() - 2].y;
01916
01917 Direction.x = Centre.x - Direction.x;
01918 Direction.y = Centre.y - Direction.y;
01919
01920 pEndArrow->EndArrow.GetArrowMatrix(Centre, Direction,
01921 EndsWidth, &ArrowMatrix);
01922
01923
01924 ArrowPath.ClearPath();
01925 ArrowPath.CloneFrom(*pEndArrow->EndArrow.GetArrowPath());
01926
01927 ArrowMatrix.Transform(ArrowPath.GetCoordArray(), ArrowPath.GetNumCoords());
01928
01929 DestPathEndArrow.ClearPath();
01930 ClipPath.CloneFrom(StrokedPath);
01931 if(ClipPath.ClipPathToPath(ArrowPath,&StrokedPath, 7 | CLIPPING_SOURCE_WINDING,30, Flatness, Flatness) < 2)
01932 {
01933 ArrowPath.CloneFrom(ClipPath);
01934 TRACEUSER( "MarkH", _T("ClipFailed so copying path! NODEPATH\n"));
01935 }
01936
01937 pRetnNode->InkPath.MergeTwoPaths(DestPathEndArrow);
01938 }
01939 }
01940
01941 if (pRetnNode->InkPath.GetBoundingRect().Union(StrokedPath.GetBoundingRect()).IsEmpty())
01942 {
01943 pRetnNode->InkPath.MergeTwoPaths(StrokedPath);
01944 }
01945 else
01946 {
01947 ClipPath.CloneFrom(pRetnNode->InkPath);
01948 pRetnNode->InkPath.ClearPath();
01949 if(StrokedPath.ClipPathToPath(ClipPath, &(pRetnNode->InkPath), 7 | CLIPPING_SOURCE_WINDING,30, Flatness, Flatness) < 2)
01950 {
01951 pRetnNode->InkPath.CloneFrom(ClipPath);
01952 TRACEUSER( "MarkH", _T("ClipFailed so copying path! NODEPATH\n"));
01953 }
01954 }
01955 }
01956 else
01957 {
01958 SubPath.ClearPath();
01959
01960
01961 if(IncludeWidth)
01962 {
01963
01964 SubPath.CloneFrom(InkPath);
01965 if(BlankPath.ClipPathToPath(SubPath, &StrokedPath, 3, 10, Flatness, Flatness) < 2)
01966 {
01967 StrokedPath.CloneFrom(SubPath);
01968 TRACEUSER( "MarkH", _T("ClipFailed so copying path! NODEPATH\n"));
01969 }
01970
01971
01972 StrokedPath.InitializeContourValues(Width,JoinS,true,Flatness);
01973 if(StrokedPath.GetContourForStep(&pRetnNode->InkPath,1.0) < 2)
01974 {
01975 pRetnNode->InkPath.CloneFrom(StrokedPath);
01976 TRACEUSER( "MarkH", _T("ClipFailed so copying path! NODEPATH\n"));
01977 }
01978 }
01979 else
01980 {
01981
01982 InkPath.MakePathFromSubPath(SubPathNum, &SubPath);
01983 pRetnNode->InkPath.MergeTwoPaths(SubPath);
01984 }
01985 }
01986
01987 StartIndex = EndIndex+1;
01988 SubPathNum++;
01989 }
01990
01991 if (pRetnNode)
01992 {
01993 pRetnNode->InkPath.IsFilled = TRUE;
01994 pRetnNode->InkPath.IsStroked = FALSE;
01995 }
01996
01997 return pRetnNode;
01998 }
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019 BOOL NodePath::RetroSmoothMe(double Smoothness)
02020 {
02021 if (Smoothness <= 0)
02022 {
02023 ERROR3("Zero smoothing value in NodePath::RetroSmoothMe");
02024 return TRUE;
02025 }
02026
02027 Spread *pSpread = Document::GetSelectedSpread();
02028 ERROR2IF(pSpread == NULL, FALSE, "No spread in NodePath::RetroSmoothMe");
02029
02030
02031 RetroSmooth rSmoother;
02032 rSmoother.Initialise();
02033 rSmoother.SetRenderFlag(false);
02034
02035
02036 InkPath.SetAllSubSelection();
02037
02038
02039 rSmoother.Changing(this, pSpread, Smoothness);
02040 BOOL ok = rSmoother.FinishedNoUndo(this);
02041
02042 InkPath.ClearSubSelection();
02043
02044 return ok;
02045 }
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071 BOOL NodePath::Snap(DocCoord* pDocCoord)
02072 {
02073 #if !defined(EXCLUDE_FROM_RALPH)
02074 return CSnap::SnapCoordToPath(pDocCoord, &InkPath);
02075 #else
02076 return FALSE;
02077 #endif
02078 }
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107 BOOL NodePath::Snap(DocRect* pDocRect,const DocCoord& PrevCoord,const DocCoord& CurCoord)
02108 {
02109 #if !defined(EXCLUDE_FROM_RALPH)
02110 TRACEUSER( "MarkN", _T("NodePath::Snap(DocRect)\n") );
02111 #endif
02112 return FALSE;
02113 }
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138 BOOL NodePath::SnapToCoords(DocCoord* pDocCoord)
02139 {
02140 #if !defined(EXCLUDE_FROM_RALPH)
02141 DocCoord* Coords = InkPath.GetCoordArray();
02142 PathFlags* Flags = InkPath.GetFlagArray();
02143 INT32 NumCoords = InkPath.GetNumCoords();
02144
02145
02146 for (INT32 i=0; i<NumCoords; i++)
02147 {
02148
02149 if (Flags[i].IsEndPoint)
02150 {
02151
02152 if (IsMagneticallyClose(&Coords[i], pDocCoord))
02153 return TRUE;
02154 }
02155 }
02156 #endif
02157
02158 return FALSE;
02159 }
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178 double NodePath::GetRotationAngle()
02179 {
02180 return CurrentRotation;
02181 }
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199 void NodePath::DeSelect(BOOL ReDraw, BOOL bDeselectChildren)
02200 {
02201 if (ReDraw && GetApplication()->GetBlobManager()->GetCurrentInterest().Object)
02202 InkPath.RenderPathSelectedControlBlobs(FindParentSpread());
02203
02204 InkPath.ClearSubSelection();
02205
02206
02207 NodeRenderableInk::DeSelect(ReDraw, bDeselectChildren);
02208 }
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231 BOOL NodePath::IsPathAllowable()
02232 {
02233 INT32 NumCoords = InkPath.GetNumCoords();
02234 PathVerb* Verbs = NULL;
02235 PathFlags* Flags = NULL;
02236 DocCoord* Coords = NULL;
02237 InkPath.GetPathArrays(&Verbs, &Coords, &Flags);
02238
02239
02240 if ( (NumCoords == 2) && (Verbs[1] & PT_CLOSEFIGURE) && ((Verbs[1] & ~PT_CLOSEFIGURE) == PT_LINETO) )
02241 {
02242 ERROR3IF(Verbs[0] != PT_MOVETO,"Path didn't start with a moveto!");
02243 return FALSE;
02244 }
02245
02246
02247 if ( (NumCoords == 4) && (Verbs[3] & PT_CLOSEFIGURE) && ((Verbs[3] & ~PT_CLOSEFIGURE) == PT_BEZIERTO) )
02248 {
02249 ERROR3IF(Verbs[0] != PT_MOVETO,"Path didn't start with a moveto!");
02250 ERROR3IF(Verbs[1] != PT_BEZIERTO,"Path didn't continue with a Bezierto!");
02251 return FALSE;
02252 }
02253
02254 return TRUE;
02255 }
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275 BOOL NodePath::NeedsToExport(RenderRegion* pRender, BOOL VisibleLayersOnly, BOOL CheckSelected)
02276 {
02277 #ifdef DO_EXPORT
02278 if (pRender->IsKindOf(CC_RUNTIME_CLASS(EPSRenderRegion)))
02279 {
02280 Node* pParent=FindParent();
02281 if (pParent!=NULL && IS_A(pParent,TextStory))
02282 return FALSE;
02283 }
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293 if (CheckSelected)
02294 return (IsSelected() || IsChildOfSelected() || IsParentOfSelected());
02295 else
02296 return TRUE;
02297 #else
02298 return FALSE;
02299 #endif
02300 }
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322 BOOL NodePath::AllowOp(ObjChangeParam* pParam, BOOL SetOpPermissionState,
02323 BOOL DoPreTriggerEdit)
02324 {
02325
02326 BOOL allowed = NodeRenderableInk::AllowOp(pParam, SetOpPermissionState, FALSE);
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342 if (allowed && DoPreTriggerEdit)
02343 {
02344
02345 UndoableOperation* pChangeOp = pParam->GetOpPointer();
02346 if (pChangeOp != NULL && pChangeOp->MayChangeNodeBounds() && NameGallery::Instance())
02347 {
02348 allowed = NameGallery::Instance()->PreTriggerEdit(pChangeOp, pParam, this);
02349 }
02350 }
02351 if (SetOpPermissionState)
02352 SetOpPermission(PERMISSION_ALLOWED);
02353
02354 return allowed;
02355 }
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372 UINT32 NodePath::ChooseTagValue()
02373 {
02374 #ifdef DO_EXPORT
02375 UINT32 Tag = TAG_UNDEFINED;
02376
02377 if (BaseCamelotFilter::WritePathsInRelativeFormat())
02378 {
02379 Tag = TAG_PATH_RELATIVE;
02380 if (InkPath.IsFilled && !InkPath.IsStroked)
02381 Tag = TAG_PATH_RELATIVE_FILLED;
02382 else if (!InkPath.IsFilled && InkPath.IsStroked)
02383 Tag = TAG_PATH_RELATIVE_STROKED;
02384 else if (InkPath.IsFilled && InkPath.IsStroked)
02385 Tag = TAG_PATH_RELATIVE_FILLED_STROKED;
02386 }
02387 else
02388 {
02389 Tag = TAG_PATH;
02390 if (InkPath.IsFilled && !InkPath.IsStroked)
02391 Tag = TAG_PATH_FILLED;
02392 else if (!InkPath.IsFilled && InkPath.IsStroked)
02393 Tag = TAG_PATH_STROKED;
02394 else if (InkPath.IsFilled && InkPath.IsStroked)
02395 Tag = TAG_PATH_FILLED_STROKED;
02396 }
02397
02398 return Tag;
02399 #else
02400 return TAG_UNDEFINED;
02401 #endif
02402 }
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426 INT32 NodePath::EstimateNodeComplexity (OpParam* details)
02427 {
02428 return (InkPath.GetUsedSlots ());
02429 }
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445 INT32 NodePath::CalcPathRecordSize()
02446 {
02447 INT32 NumCoords = InkPath.GetNumCoords();
02448
02449 if (BaseCamelotFilter::WritePathsInRelativeFormat())
02450 return (sizeof(PathVerb)*NumCoords)+(sizeof(DocCoord)*NumCoords);
02451 else
02452 return sizeof(INT32)+(sizeof(PathVerb)*NumCoords)+(sizeof(DocCoord)*NumCoords);
02453 }
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468 BOOL NodePath::WritePathToRecord(CamelotFileRecord* pRecord)
02469 {
02470 ERROR2IF(pRecord == NULL,FALSE,"NULL record ptr");
02471
02472 if (BaseCamelotFilter::WritePathsInRelativeFormat())
02473 return pRecord->WritePathRelative(&InkPath);
02474 else
02475 return pRecord->WritePath(&InkPath);
02476 }
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491 BOOL NodePath::WritePathRecord(BaseCamelotFilter* pFilter)
02492 {
02493 #ifdef DO_EXPORT
02494 ERROR2IF(pFilter == NULL,FALSE,"NULL filter param");
02495
02496 INT32 RecordSize = CalcPathRecordSize();
02497
02498 BOOL ok = TRUE;
02499
02500
02501 UINT32 Tag = ChooseTagValue();
02502
02503 CamelotFileRecord Rec(pFilter,Tag,RecordSize);
02504
02505 ok = Rec.Init();
02506 if (ok) ok = WritePathToRecord(&Rec);
02507
02508 UINT32 RecordNumber;
02509 if (ok) RecordNumber = pFilter->WriteDefinitionRecord(&Rec);
02510 if (ok) ok = (RecordNumber != 0);
02511 if (ok) pFilter->AddPathRecordRefToList(this,RecordNumber);
02512
02513 if (!ok)
02514 pFilter->GotError(_R(IDE_FILE_WRITE_ERROR));
02515
02516 return ok;
02517 #else
02518 return FALSE;
02519 #endif
02520 }
02521
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533
02534
02535
02536
02537 BOOL NodePath::WritePathRefRecord(BaseCamelotFilter* pFilter,UINT32 SrcPathRecNum,Matrix* pTransform)
02538 {
02539 ERROR2IF(pTransform == NULL,FALSE,"NULL transform matrix ptr");
02540
02541 BOOL ok = TRUE;
02542
02543 UINT32 Tag = TAG_PATHREF_TRANSFORM;
02544 INT32 Size = TAG_PATHREF_TRANSFORM_SIZE;
02545
02546 CamelotFileRecord Rec(pFilter,Tag,Size);
02547 if (ok) ok = Rec.Init();
02548 if (ok) ok = Rec.WriteReference(SrcPathRecNum);
02549 if (ok) ok = Rec.WriteMatrixTrans(*pTransform,0,0);
02550 if (ok) ok = (pFilter->Write(&Rec) != 0);
02551
02552 return ok;
02553 }
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569 BOOL NodePath::WritePreChildrenWeb(BaseCamelotFilter* pFilter)
02570 {
02571 #ifdef DO_EXPORT
02572
02573 BOOL ok = TRUE;
02574 UINT32 SrcPathRecNum;
02575 Matrix Transform;
02576
02577 INT32 RecordSize = CalcPathRecordSize();
02578
02579
02580
02581
02582 if (RecordSize > TAG_PATHREF_TRANSFORM_SIZE && pFilter->FindSimilarPath(this,&SrcPathRecNum,&Transform))
02583 ok = WritePathRefRecord(pFilter,SrcPathRecNum,&Transform);
02584 else
02585 ok = WritePathRecord(pFilter);
02586
02587 return ok;
02588
02589 #else
02590 return FALSE;
02591 #endif
02592 }
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605
02606
02607 BOOL NodePath::WritePreChildrenNative(BaseCamelotFilter* pFilter)
02608 {
02609 #ifdef DO_EXPORT
02610
02611
02612
02613
02614 if (pFilter->IsCompactNativeFilter() || pFilter->GetNativeCheckSimilarPaths())
02615 return WritePreChildrenWeb(pFilter);
02616 else
02617 return WritePathRecord(pFilter);
02618 #else
02619 return FALSE;
02620 #endif
02621 }
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639 BOOL NodePath::WriteBeginChildRecordsNative(BaseCamelotFilter* pFilter)
02640 {
02641 #ifdef DO_EXPORT
02642 ERROR2IF(pFilter == NULL,FALSE,"NULL filter param");
02643
02644 BOOL ok = pFilter->WriteZeroSizedRecord(TAG_DOWN);
02645
02646 if (ok)
02647 {
02648 INT32 NumCoords = InkPath.GetNumCoords();
02649 INT32 RecordSize = sizeof(BYTE)*NumCoords;
02650
02651 CamelotFileRecord Rec(pFilter,TAG_PATH_FLAGS,RecordSize);
02652 ok = Rec.Init();
02653
02654 PathFlags* pFlags = InkPath.GetFlagArray();
02655
02656 if (ok && pFlags != NULL)
02657 {
02658 BYTE Flags;
02659 for (INT32 i=0; ok && i < NumCoords;i++)
02660 {
02661 Flags = 0;
02662
02663 if (pFlags[i].IsSmooth) Flags |= TAG_PATH_FLAGS_SMOOTH;
02664 if (pFlags[i].IsRotate) Flags |= TAG_PATH_FLAGS_ROTATE;
02665 if (pFlags[i].IsEndPoint) Flags |= TAG_PATH_FLAGS_ENDPOINT;
02666
02667 ok = Rec.WriteBYTE(Flags);
02668 }
02669
02670 ok = pFilter->Write(&Rec);
02671 }
02672
02673 if (ok)
02674 {
02675 if (pFilter->GetBoundsWriteLevel() >= BWL_ALL)
02676 ok = WriteBoundsRecord(pFilter);
02677 }
02678 }
02679
02680 return ok;
02681 #else
02682 return FALSE;
02683 #endif
02684 }
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701 BOOL NodePath::WriteEndChildRecordsNative(BaseCamelotFilter* pFilter)
02702 {
02703 #ifdef DO_EXPORT
02704 ERROR2IF(pFilter == NULL,FALSE,"NULL filter param");
02705
02706 return pFilter->WriteZeroSizedRecord(TAG_UP);
02707 #else
02708 return FALSE;
02709 #endif
02710 }
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745 BOOL NodePath::IsDifferent(Node *pOther)
02746 {
02747
02748 if (NodeRenderableInk::IsDifferent(pOther))
02749 return(TRUE);
02750
02751 ERROR3IF(GetRuntimeClass() != pOther->GetRuntimeClass(),
02752 "Node::IsDifferent base class method seems to have been broken");
02753
02754
02755 if (InkPath.GetNumCoords() != ((NodePath *)pOther)->InkPath.GetNumCoords())
02756 return(TRUE);
02757
02758
02759 DocCoord *pCoord1 = InkPath.GetCoordArray();
02760 DocCoord *pCoord2 = ((NodePath *)pOther)->InkPath.GetCoordArray();
02761
02762 PathVerb *pVerb1 = InkPath.GetVerbArray();
02763 PathVerb *pVerb2 = ((NodePath *)pOther)->InkPath.GetVerbArray();
02764
02765 for (INT32 i = 0; i < InkPath.GetNumCoords(); i++)
02766 {
02767 if (pVerb1[i] != pVerb2[i] || pCoord1[i] != pCoord2[i])
02768 return(TRUE);
02769 }
02770
02771 return(FALSE);
02772 }
02773
02774
02775
02776
02777
02778
02779
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790 BOOL NodePath::IsANodeBlendPath()
02791 {
02792 return FALSE;
02793 }
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813 DocRect NodePath::ValidateExtend(const ExtendParams& ExtParams)
02814 {
02815 INT32 numPoints = InkPath.GetNumCoords();
02816 DocCoord* doccArray = InkPath.GetCoordArray();
02817 DocRect drMinExtend = Extender::ValidateControlPoints(numPoints, doccArray, ExtParams);
02818
02819
02820
02821 if (drMinExtend.lo.x == INT32_MAX &&
02822 drMinExtend.lo.y == INT32_MAX &&
02823 drMinExtend.hi.x == INT32_MAX &&
02824 drMinExtend.hi.y == INT32_MAX)
02825 drMinExtend = Node::ValidateExtend(ExtParams);
02826
02827 return drMinExtend;
02828 }
02829
02830
02831
02832
02833
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850 void NodePath::Extend(const ExtendParams& ExtParams)
02851 {
02852 TransformTranslateObject(ExtParams);
02853 TransformStretchObject(ExtParams);
02854
02855
02856 Node::Extend(ExtParams);
02857 }
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874
02875 void NodePath::TransformTranslateObject(const ExtendParams& ExtParams)
02876 {
02877
02878 INT32 numPoints = InkPath.GetNumCoords();
02879 DocCoord* doccArray = InkPath.GetCoordArray();
02880
02881
02882 if (ExtParams.fExtendFlags & X_EXTEND)
02883 {
02884
02885 Trans2DMatrix baseXoffset(ExtParams.doccOffset.x, 0);
02886 Transform(baseXoffset);
02887
02888 for (INT32 i = 0; i < numPoints; i ++)
02889 {
02890 if (doccArray[i].x > (ExtParams.doccEndCentre.x + ExtParams.xincExtendBuffer))
02891 doccArray[i].x += ExtParams.xinc;
02892 else if (doccArray[i].x < (ExtParams.doccEndCentre.x - ExtParams.xdecExtendBuffer))
02893 doccArray[i].x -= ExtParams.xdec;
02894 }
02895 }
02896
02897
02898 if (ExtParams.fExtendFlags & Y_EXTEND)
02899 {
02900
02901 Trans2DMatrix baseYoffset(0, ExtParams.doccOffset.y);
02902 Transform(baseYoffset);
02903
02904 for (INT32 i = 0; i < numPoints; i ++)
02905 {
02906 if (doccArray[i].y > (ExtParams.doccEndCentre.y + ExtParams.yincExtendBuffer))
02907 doccArray[i].y += ExtParams.yinc;
02908 else if (doccArray[i].y < (ExtParams.doccEndCentre.y - ExtParams.ydecExtendBuffer))
02909 doccArray[i].y -= ExtParams.ydec;
02910 }
02911 }
02912 }
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936 DocRect NodePath::GetExtendTargetBounds(const ExtendParams& ExtParams)
02937 {
02938
02939
02940 DocRect drBounds = GetBoundingRect();
02941 DocRect drPointBounds = InkPath.GetBoundingRect();
02942 if (ExtParams.fExtendFlags & X_EXTEND)
02943 {
02944 drBounds.lo.x = drPointBounds.lo.x;
02945 drBounds.hi.x = drPointBounds.hi.x;
02946 }
02947 if (ExtParams.fExtendFlags & Y_EXTEND)
02948 {
02949 drBounds.lo.y = drPointBounds.lo.y;
02950 drBounds.hi.y = drPointBounds.hi.y;
02951 }
02952
02953 return drBounds;
02954 }
02955
02956
02957
02958
02959
02960
02961
02962
02963
02964
02965
02966
02967
02968
02969
02970
02971
02972
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982 BOOL NodePath::CreateFromPath(NodePath** ppNewPath, Path* pSrcPath, Operation* pOp)
02983 {
02984 ERROR2IF(ppNewPath == NULL, FALSE, "NodePath::CreateFromPath; called with NULL param!");
02985
02986 NodePath* pNewPath = NULL;
02987 ALLOC_WITH_FAIL(pNewPath, new NodePath, pOp);
02988 if (pNewPath != NULL)
02989 {
02990 if (pSrcPath != NULL)
02991 {
02992 BOOL ok = pNewPath->InkPath.Initialise(pSrcPath->GetNumCoords(), 1);
02993 if (ok)
02994 CALL_WITH_FAIL(pNewPath->InkPath.CopyPathDataFrom(pSrcPath), pOp, ok);
02995
02996 if (!ok)
02997 {
02998 delete pNewPath;
02999 pNewPath = NULL;
03000 }
03001 }
03002 else
03003 {
03004 pNewPath->SetUpPath();
03005 }
03006 }
03007
03008 *ppNewPath = pNewPath;
03009 return (pNewPath != NULL);
03010 }
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026
03027
03028
03029 Path* NodePath::GetPathCopy()
03030 {
03031 Path* pResult = new Path;
03032 if (pResult != NULL)
03033 {
03034 if (!pResult->Initialise(InkPath.GetNumCoords()) ||
03035 !pResult->CloneFrom(InkPath))
03036 {
03037 delete pResult;
03038 pResult = NULL;
03039 }
03040 }
03041
03042 return pResult;
03043 }
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053
03054
03055
03056
03057
03058
03059
03060 BOOL NodePath::GetAreaDetails(XLONG* pxlArea, XLONG* pxlPerimeter)
03061 {
03062 BOOL bOK = TRUE;
03063
03064 *pxlArea = InkPath.CalcArea();
03065 double dDistance = 0;
03066 bOK = InkPath.DistanceTo(InkPath.GetNumCoords()-1, 1, &dDistance);
03067 *pxlPerimeter = (INT32)dDistance;
03068
03069 return TRUE;
03070 }
03071
03072
03073
03074
03075
03076
03077
03078
03079
03080
03081
03082
03083
03084
03085
03086
03087
03088
03089
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130
03131 UINT32* PathRecordHandler::GetTagList()
03132 {
03133 static UINT32 TagList[] = { TAG_PATH,
03134 TAG_PATH_FILLED,
03135 TAG_PATH_STROKED,
03136 TAG_PATH_FILLED_STROKED,
03137 TAG_PATH_RELATIVE,
03138 TAG_PATH_RELATIVE_FILLED,
03139 TAG_PATH_RELATIVE_STROKED,
03140 TAG_PATH_RELATIVE_FILLED_STROKED,
03141
03142 TAG_PATHREF_IDENTICAL,
03143 TAG_PATHREF_TRANSFORM,
03144 CXFRH_TAG_LIST_END};
03145
03146 return (UINT32*)&TagList;
03147 }
03148
03149
03150
03151
03152
03153
03154
03155
03156
03157
03158
03159
03160
03161
03162
03163 BOOL PathRecordHandler::HandleRecord(CXaraFileRecord* pCXaraFileRecord)
03164 {
03165 ERROR2IF(pCXaraFileRecord == NULL,FALSE,"pCXaraFileRecord is NULL");
03166
03167 BOOL ok = TRUE;
03168
03169 switch (pCXaraFileRecord->GetTag())
03170 {
03171 case TAG_PATH: ok = HandlePathRecord(pCXaraFileRecord,FALSE,FALSE);break;
03172 case TAG_PATH_FILLED: ok = HandlePathRecord(pCXaraFileRecord,TRUE,FALSE); break;
03173 case TAG_PATH_STROKED: ok = HandlePathRecord(pCXaraFileRecord,FALSE,TRUE); break;
03174 case TAG_PATH_FILLED_STROKED: ok = HandlePathRecord(pCXaraFileRecord,TRUE,TRUE); break;
03175
03176 case TAG_PATH_RELATIVE: ok = HandlePathRelativeRecord(pCXaraFileRecord,FALSE,FALSE);break;
03177 case TAG_PATH_RELATIVE_FILLED: ok = HandlePathRelativeRecord(pCXaraFileRecord,TRUE,FALSE); break;
03178 case TAG_PATH_RELATIVE_STROKED: ok = HandlePathRelativeRecord(pCXaraFileRecord,FALSE,TRUE); break;
03179 case TAG_PATH_RELATIVE_FILLED_STROKED: ok = HandlePathRelativeRecord(pCXaraFileRecord,TRUE,TRUE); break;
03180
03181
03182
03183 case TAG_PATHREF_IDENTICAL:
03184 case TAG_PATHREF_TRANSFORM: ok = HandlePathRefRecord(pCXaraFileRecord); break;
03185
03186 default:
03187 ok = FALSE;
03188 ERROR3_PF(("I don't handle records with the tag (%d)\n",pCXaraFileRecord->GetTag()));
03189 break;
03190 }
03191
03192 return ok;
03193 }
03194
03195
03196
03197
03198
03199
03200
03201
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213 BOOL PathRecordHandler::HandlePathRecord(CXaraFileRecord* pCXaraFileRecord,BOOL Filled,BOOL Stroked)
03214 {
03215 ERROR2IF(pCXaraFileRecord == NULL,FALSE,"pCXaraFileRecord is NULL");
03216 ERROR3IF(!IsTagInList(pCXaraFileRecord->GetTag()),"I don't handle this tag type");
03217
03218 BOOL ok = FALSE;
03219
03220 NodePath* pNodePath = new NodePath;
03221
03222 if (pNodePath != NULL && pNodePath->SetUpPath())
03223 {
03224 ok = pCXaraFileRecord->ReadPath(&pNodePath->InkPath);
03225
03226 if (ok)
03227 {
03228 pNodePath->InkPath.IsFilled = Filled;
03229 pNodePath->InkPath.IsStroked= Stroked;
03230 pNodePath->InkPath.InitialiseFlags();
03231 }
03232 }
03233
03234 if (ok) ok = InsertNode(pNodePath);
03235 if (ok) SetLastNodePathInserted(pNodePath);
03236
03237 if (ok) AddPathRecordRefToList(pNodePath,pCXaraFileRecord->GetRecordNumber());
03238
03239 return ok;
03240 }
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253
03254
03255
03256
03257
03258
03259 BOOL PathRecordHandler::HandlePathRelativeRecord(CXaraFileRecord* pCXaraFileRecord,BOOL Filled,BOOL Stroked)
03260 {
03261 ERROR2IF(pCXaraFileRecord == NULL,FALSE,"pCXaraFileRecord is NULL");
03262 ERROR3IF(!IsTagInList(pCXaraFileRecord->GetTag()),"I don't handle this tag type");
03263
03264 BOOL ok = FALSE;
03265
03266 NodePath* pNodePath = new NodePath;
03267
03268 if (pNodePath != NULL && pNodePath->SetUpPath())
03269 {
03270 ok = pCXaraFileRecord->ReadPathRelative(&pNodePath->InkPath);
03271
03272 if (ok)
03273 {
03274 pNodePath->InkPath.IsFilled = Filled;
03275 pNodePath->InkPath.IsStroked= Stroked;
03276 pNodePath->InkPath.InitialiseFlags();
03277 }
03278 }
03279
03280 if (ok) ok = InsertNode(pNodePath);
03281 if (ok) SetLastNodePathInserted(pNodePath);
03282
03283 if (ok) AddPathRecordRefToList(pNodePath,pCXaraFileRecord->GetRecordNumber());
03284
03285 return ok;
03286 }
03287
03288
03289
03290
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303 BOOL PathRecordHandler::HandlePathRefRecord(CXaraFileRecord* pCXaraFileRecord)
03304 {
03305 ERROR2IF(pCXaraFileRecord == NULL,FALSE,"pCXaraFileRecord is NULL");
03306
03307 ERROR3IF(pCXaraFileRecord->GetTag() != TAG_PATHREF_TRANSFORM,"I don't handle this tag type");
03308
03309 BOOL ok = TRUE;
03310
03311 UINT32 SrcRecNum;
03312 Matrix Transform;
03313
03314 if (ok) ok = pCXaraFileRecord->ReadUINT32(&SrcRecNum);
03315 if (ok) ok = pCXaraFileRecord->ReadMatrixTrans(&Transform,0,0);
03316
03317 if (ok)
03318 {
03319 ok = FALSE;
03320
03321 NodePath* pSrcPath = FindPathRecordRefPath(SrcRecNum);
03322 if (pSrcPath != NULL)
03323 {
03324 NodePath* pNodePath = new NodePath;
03325 if (pNodePath != NULL && pNodePath->SetUpPath())
03326 {
03327 if (pNodePath->InkPath.MergeTwoPaths(pSrcPath->InkPath))
03328 {
03329 pNodePath->InkPath.IsFilled = pSrcPath->InkPath.IsFilled;
03330 pNodePath->InkPath.IsStroked= pSrcPath->InkPath.IsStroked;
03331
03332
03333
03334
03335
03336 DocCoord Origin = GetCoordOrigin();
03337 {
03338 Matrix TranslateMat(-Origin.x,-Origin.y);
03339 Trans2DMatrix Translate(TranslateMat);
03340 pNodePath->Transform(Translate);
03341 }
03342
03343
03344 Trans2DMatrix Trans(Transform);
03345 pNodePath->Transform(Trans);
03346
03347
03348 {
03349 Matrix TranslateMat(Origin.x,Origin.y);
03350 Trans2DMatrix Translate(TranslateMat);
03351 pNodePath->Transform(Translate);
03352 }
03353
03354 ok = InsertNode(pNodePath);
03355 if (ok) SetLastNodePathInserted(pNodePath);
03356 }
03357 }
03358 }
03359 }
03360
03361 return ok;
03362 }
03363
03364
03365
03366
03367
03368
03369
03370
03371
03372
03373
03374
03375
03376
03377
03378
03379
03380 #ifdef XAR_TREE_DIALOG
03381 void PathRecordHandler::GetRecordDescriptionText(CXaraFileRecord* pRecord,StringBase* pStr)
03382 {
03383 if (pStr == NULL || pRecord == NULL)
03384 return;
03385
03386 TCHAR s[256];
03387
03388
03389 CamelotRecordHandler::GetRecordDescriptionText(pRecord,pStr);
03390
03391 switch (pRecord->GetTag())
03392 {
03393 case TAG_PATH:
03394 case TAG_PATH_FILLED:
03395 case TAG_PATH_STROKED:
03396 case TAG_PATH_FILLED_STROKED:
03397
03398 DescribePath(pRecord,pStr);
03399 break;
03400
03401 case TAG_PATH_RELATIVE:
03402 case TAG_PATH_RELATIVE_FILLED:
03403 case TAG_PATH_RELATIVE_STROKED:
03404 case TAG_PATH_RELATIVE_FILLED_STROKED:
03405
03406 DescribePathRelative(pRecord,pStr);
03407 break;
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428 case TAG_PATHREF_TRANSFORM:
03429 {
03430 UINT32 SrcRecNum;
03431 Matrix Transform;
03432
03433 pRecord->ReadUINT32(&SrcRecNum);
03434 pRecord->ReadMatrix(&Transform);
03435
03436 camSprintf(s,_T("Src path rec num:\t%d\r\n"),SrcRecNum); (*pStr) += s;
03437
03438 FIXED16 abcd[4];
03439 INT32 ef[2];
03440 double d;
03441 Transform.GetComponents(abcd,ef);
03442
03443 d = abcd[0].MakeDouble(); camSprintf(s,_T("a = %g\r\n"),d); (*pStr) += s;
03444 d = abcd[1].MakeDouble(); camSprintf(s,_T("b = %g\r\n"),d); (*pStr) += s;
03445 d = abcd[2].MakeDouble(); camSprintf(s,_T("c = %g\r\n"),d); (*pStr) += s;
03446 d = abcd[3].MakeDouble(); camSprintf(s,_T("d = %g\r\n"),d); (*pStr) += s;
03447
03448 camSprintf(s,_T("e = %d\r\n"),ef[0]); (*pStr) += s;
03449 camSprintf(s,_T("f = %d\r\n"),ef[1]); (*pStr) += s;
03450 }
03451 break;
03452 }
03453 }
03454 #endif
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468
03469
03470
03471
03472
03473
03474
03475 UINT32* PathFlagsRecordHandler::GetTagList()
03476 {
03477 static UINT32 TagList[] = { TAG_PATH_FLAGS,
03478 CXFRH_TAG_LIST_END};
03479
03480 return (UINT32*)&TagList;
03481 }
03482
03483
03484
03485
03486
03487
03488
03489
03490
03491
03492
03493
03494
03495
03496
03497
03498
03499
03500 BOOL PathFlagsRecordHandler::HandleRecord(CXaraFileRecord* pCXaraFileRecord)
03501 {
03502 ERROR2IF(pCXaraFileRecord == NULL,FALSE,"pCXaraFileRecord is NULL");
03503 ERROR3IF(pCXaraFileRecord->GetTag() != TAG_PATH_FLAGS,"I don't handle this tag type");
03504
03505 BOOL ok = TRUE;
03506
03507 NodePath* pNodePath = GetLastNodePathInserted();
03508
03509 if (pNodePath != NULL)
03510 {
03511 UINT32 NumFlags = pCXaraFileRecord->GetSize()*sizeof(BYTE);
03512 UINT32 NumCoords = pNodePath->InkPath.GetNumCoords();
03513
03514 if (NumCoords == NumFlags)
03515 {
03516 PathFlags* pFlags = pNodePath->InkPath.GetFlagArray();
03517
03518 BYTE Flags;
03519 for (UINT32 i=0; ok && i < NumFlags;i++)
03520 {
03521 ok = pCXaraFileRecord->ReadBYTE(&Flags);
03522
03523 if (ok)
03524 {
03525 pFlags[i].IsSmooth = (Flags & TAG_PATH_FLAGS_SMOOTH) != 0;
03526 pFlags[i].IsRotate = (Flags & TAG_PATH_FLAGS_ROTATE) != 0;
03527 pFlags[i].IsEndPoint= (Flags & TAG_PATH_FLAGS_ENDPOINT) != 0;
03528 }
03529 }
03530 }
03531 }
03532 else
03533 {
03534 ERROR3("NULL node path ptr");
03535 }
03536
03537 return ok;
03538 }
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552
03553
03554
03555
03556 #ifdef XAR_TREE_DIALOG
03557 void PathFlagsRecordHandler::GetRecordDescriptionText(CXaraFileRecord* pRecord,StringBase* pStr)
03558 {
03559 if (pStr == NULL || pRecord == NULL)
03560 return;
03561
03562 TCHAR s[256];
03563
03564
03565 CamelotRecordHandler::GetRecordDescriptionText(pRecord,pStr);
03566
03567 switch (pRecord->GetTag())
03568 {
03569 case TAG_PATH_FLAGS:
03570 {
03571 UINT32 NumFlags = pRecord->GetSize()*sizeof(BYTE);
03572
03573 BYTE Flags;
03574 for (UINT32 i=0;i < NumFlags;i++)
03575 {
03576 pRecord->ReadBYTE(&Flags);
03577
03578 camSprintf(s,_T("Flags\r\n")); (*pStr) += s;
03579 camSprintf(s,_T("Smooth:\t%d\r\n"), (Flags & TAG_PATH_FLAGS_SMOOTH) != 0); (*pStr) += s;
03580 camSprintf(s,_T("Rotate:\t%d\r\n"), (Flags & TAG_PATH_FLAGS_ROTATE) != 0); (*pStr) += s;
03581 camSprintf(s,_T("EndPoint:\t%d\r\n"), (Flags & TAG_PATH_FLAGS_ENDPOINT) != 0); (*pStr) += s;
03582 camSprintf(s,_T("\r\n")); (*pStr) += s;
03583
03584 }
03585 }
03586 break;
03587 }
03588 }
03589 #endif