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 #include "camtypes.h"
00103 #include "nodershp.h"
00104
00105
00106
00107
00108 #include "blobs.h"
00109 #include "cameleps.h"
00110 #include "nativeps.h"
00111 #include "swfrndr.h"
00112 #include "contmenu.h"
00113
00114
00115 #include "nodepath.h"
00116
00117 #include "ophist.h"
00118
00119
00120 #include "shapeops.h"
00121 #include "snap.h"
00122
00123
00124
00125
00126
00127
00128 #include "cxfrgshp.h"
00129
00130
00131
00132
00133
00134
00135
00136
00137 #include "filtirr.h"
00138
00139 #include "extender.h"
00140
00141
00142 #include "attrmap.h"
00143
00144
00145 #include "strkattr.h"
00146 #include "ppstroke.h"
00147 #include "gclip.h"
00148 #include "gclips.h"
00149 #include "rsmooth.h"
00150 #include "brshattr.h"
00151
00152
00153 DECLARE_SOURCE( "$Revision: 1776 $" );
00154
00155
00156 CC_IMPLEMENT_DYNCREATE(NodeRegularShape, NodeRenderableInk)
00157
00158
00159 #define new CAM_DEBUG_NEW
00160
00161 static const double CurveFactor = 0.552;
00162
00163
00164
00165
00166
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 NodeRegularShape::NodeRegularShape(Node* ContextNode,
00205 AttachNodeDirection Direction,
00206 BOOL Locked,
00207 BOOL Mangled,
00208 BOOL Marked,
00209 BOOL Selected
00210 ) : NodeRenderableInk(ContextNode, Direction, Locked, Mangled, Marked, Selected )
00211 {
00212 InitialiseMemberVars();
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 NodeRegularShape::NodeRegularShape() : NodeRenderableInk()
00229 {
00230 InitialiseMemberVars();
00231 }
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 void NodeRegularShape::InitialiseMemberVars()
00248 {
00249 Circular = FALSE;
00250 Stellated = FALSE;
00251 PrimaryCurvature = FALSE;
00252 StellationCurvature = FALSE;
00253 NumSides = 6;
00254 StellRadiusToPrimary = 0.5;
00255 PrimaryCurveToPrimary = 0.2;
00256 StellCurveToStell = 0.2;
00257 StellOffsetRatio = 0.0;
00258 CachedRenderPath = NULL;
00259 PathCacheInvalid = TRUE;
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 NodeRegularShape::~NodeRegularShape()
00275 {
00276 DeleteCachedPath();
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 Node* NodeRegularShape::SimpleCopy()
00293 {
00294
00295 NodeRegularShape* NodeCopy = new NodeRegularShape();
00296 if (NodeCopy != NULL)
00297 CopyNodeContents(NodeCopy);
00298
00299 return NodeCopy;
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 void NodeRegularShape::CopyNodeContents(NodeRegularShape* NodeCopy)
00320 {
00321 ERROR3IF(NodeCopy == NULL,"NodeRegularShape::CopyNodeContents was asked to copy into a NULL pointer");
00322
00323
00324 delete NodeCopy->CachedRenderPath;
00325
00326
00327 NodeRenderableInk::CopyNodeContents(NodeCopy);
00328
00329
00330 NodeCopy->NumSides = NumSides;
00331 NodeCopy->Circular = Circular;
00332 NodeCopy->Stellated = Stellated;
00333 NodeCopy->PrimaryCurvature = PrimaryCurvature;
00334 NodeCopy->StellationCurvature = StellationCurvature;
00335 NodeCopy->StellRadiusToPrimary = StellRadiusToPrimary;
00336 NodeCopy->PrimaryCurveToPrimary = PrimaryCurveToPrimary;
00337 NodeCopy->StellCurveToStell = StellCurveToStell;
00338 NodeCopy->StellOffsetRatio = StellOffsetRatio;
00339 NodeCopy->UTCentrePoint = UTCentrePoint;
00340 NodeCopy->UTMajorAxes = UTMajorAxes;
00341 NodeCopy->UTMinorAxes = UTMinorAxes;
00342 NodeCopy->CachedRenderPath = NULL;
00343 NodeCopy->PathCacheInvalid = TRUE;
00344 NodeCopy->TransformMatrix = TransformMatrix;
00345
00346
00347 if (NodeCopy->EdgePath1.Initialise(EdgePath1.GetNumCoords(),1)
00348 && NodeCopy->EdgePath2.Initialise(EdgePath2.GetNumCoords(),1) )
00349 {
00350 NodeCopy->EdgePath1.CopyPathDataFrom(&EdgePath1);
00351 NodeCopy->EdgePath2.CopyPathDataFrom(&EdgePath2);
00352 }
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 void NodeRegularShape::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
00370 {
00371 ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node");
00372 ENSURE(IS_A(pNodeCopy, NodeRegularShape), "PolyCopyNodeContents given wrong dest node type");
00373
00374 if (IS_A(pNodeCopy, NodeRegularShape))
00375 CopyNodeContents((NodeRegularShape*)pNodeCopy);
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 #ifdef _DEBUG
00391 void NodeRegularShape::ShowDebugTreeDetails() const
00392 {
00393
00394
00395 TRACEALL( _T("NodeRegularShape ") );
00396 NodeRenderableInk::ShowDebugTreeDetails();
00397 }
00398 #endif
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 void NodeRegularShape::GetDebugDetails( StringBase* Str )
00414 {
00415 #if DEBUG_TREE
00416
00417 NodeRenderableInk::GetDebugDetails( Str );
00418
00419 String_256 TempStr;
00420 String_256 TempStr2;
00421
00422 (*Str) += TEXT( "\r\nRegular Path Data Dump\r\n" );
00423
00424 DocRect BlobRect = GetBlobBoundingRect();
00425 TempStr._MakeMsg( TEXT("Blob Bounding Rect :\r\n\t#1%ld,\t#2%ld\r\n\t#3%ld,\t#4%ld\r\n"),
00426 BlobRect.lo.x, BlobRect.lo.y, BlobRect.hi.x, BlobRect.hi.y );
00427 (*Str) += TempStr;
00428
00429 TempStr._MakeMsg( TEXT("#1%d sides\r\n"),NumSides);
00430 (*Str) += TempStr;
00431
00432 TempStr._MakeMsg( TEXT("Set Flags:"));
00433 if (Circular)
00434 {
00435 TempStr2._MakeMsg( TEXT(" Circular"));
00436 TempStr += TempStr2;
00437 }
00438 if (Stellated)
00439 {
00440 TempStr2._MakeMsg( TEXT(" Stellated"));
00441 TempStr += TempStr2;
00442 }
00443 if (PrimaryCurvature)
00444 {
00445 TempStr2._MakeMsg( TEXT(" PrimaryCurvature"));
00446 TempStr += TempStr2;
00447 }
00448 if (StellationCurvature)
00449 {
00450 TempStr2._MakeMsg( TEXT(" StellationCurvature"));
00451 TempStr += TempStr2;
00452 }
00453 if (!(Circular || Stellated || PrimaryCurvature || StellationCurvature))
00454 {
00455 TempStr2._MakeMsg( TEXT(" None! "));
00456 TempStr += TempStr2;
00457 }
00458 TempStr2._MakeMsg( TEXT("\r\n\r\n"));
00459 TempStr += TempStr2;
00460 (*Str) += TempStr;
00461
00462 TCHAR floatStr[20];
00463 camSnprintf( floatStr, 20, _T("%f"), StellRadiusToPrimary );
00464 TempStr._MakeMsg( TEXT("Stellation Radius :\t#1%s\r\n"), floatStr);
00465 (*Str) += TempStr;
00466 camSnprintf( floatStr, 20, _T("%f"), StellOffsetRatio );
00467 TempStr._MakeMsg( TEXT("Stellation Offset :\t#1%s\r\n\r\n"), floatStr);
00468 (*Str) += TempStr;
00469 camSnprintf( floatStr, 20, _T("%f"), PrimaryCurveToPrimary);
00470 TempStr._MakeMsg( TEXT("Primary Curvature :\t#1%s\r\n"), floatStr);
00471 (*Str) += TempStr;
00472 camSnprintf( floatStr, 20, _T("%f"), StellCurveToStell);
00473 TempStr._MakeMsg( TEXT("Stellation Curvature :\t#1%s\r\n"), floatStr);
00474 (*Str) += TempStr;
00475
00476 TempStr._MakeMsg( TEXT("\r\nUntransformed"));
00477 (*Str) += TempStr;
00478 TempStr._MakeMsg( TEXT("Centre Point :\t#1%ld,\t#2%ld\r\n"), UTCentrePoint.x, UTCentrePoint.y);
00479 (*Str) += TempStr;
00480 TempStr._MakeMsg( TEXT("Major axes :\t#1%ld,\t#2%ld\r\n"), UTMajorAxes.x, UTMajorAxes.y);
00481 (*Str) += TempStr;
00482 TempStr._MakeMsg( TEXT("Minor axes :\t#1%ld,\t#2%ld\r\n"), UTMinorAxes.x, UTMinorAxes.y);
00483 (*Str) += TempStr;
00484
00485 TempStr._MakeMsg( TEXT("\r\nTransformed"));
00486 (*Str) += TempStr;
00487 TempStr._MakeMsg( TEXT("Centre Point :\t#1%ld,\t#2%ld\r\n"), GetCentrePoint().x, GetCentrePoint().y);
00488 (*Str) += TempStr;
00489 TempStr._MakeMsg( TEXT("Major axes :\t#1%ld,\t#2%ld\r\n"), GetMajorAxes().x, GetMajorAxes().y);
00490 (*Str) += TempStr;
00491 TempStr._MakeMsg( TEXT("Minor axes :\t#1%ld,\t#2%ld\r\n"), GetMinorAxes().x, GetMinorAxes().y);
00492 (*Str) += TempStr;
00493
00494 fixed16 billy[4];
00495 INT32 bobby[2];
00496 TransformMatrix.GetComponents(billy, bobby);
00497
00498 TempStr._MakeMsg( TEXT("\r\nMatrix\r\n"));
00499 (*Str) += TempStr;
00500 camSnprintf( floatStr, 20, _T("%f,%f"), billy[0].MakeDouble(), billy[1].MakeDouble());
00501 TempStr._MakeMsg( TEXT("a, b :\t#1%s\r\n"), floatStr);
00502 (*Str) += TempStr;
00503 camSnprintf( floatStr, 20, _T("%f,%f"), billy[2].MakeDouble(), billy[3].MakeDouble());
00504 TempStr._MakeMsg( TEXT("c, d :\t#1%s\r\n"), floatStr);
00505 (*Str) += TempStr;
00506 TempStr._MakeMsg( TEXT("e, f :\t#1%ld,\t#2%ld\r\n"), bobby[0], bobby[1]);
00507 (*Str) += TempStr;
00508
00509 (*Str) += TEXT( "\r\nPath 1\r\nNum\tType\tX Coord\tY Coord\r\n" );
00510 PathVerb* Verbs = EdgePath1.GetVerbArray();
00511 DocCoord* Coords = EdgePath1.GetCoordArray();
00512 PathFlags* Flags = EdgePath1.GetFlagArray();
00513 INT32 i;
00514 for( i = 0; i<EdgePath1.GetNumCoords(); i++)
00515 {
00516
00517 TempStr._MakeMsg( TEXT("#1%d.\t#2%d\t#3%ld,\t#4%ld\r\n"),
00518 i, Verbs[i], Coords[i].x, Coords[i].y );
00519 (*Str) += TempStr;
00520 }
00521
00522 (*Str) += TEXT( "\r\nPath 2\r\nNum\tType\tX Coord\tY Coord\r\n" );
00523 Verbs = EdgePath2.GetVerbArray();
00524 Coords = EdgePath2.GetCoordArray();
00525 Flags = EdgePath2.GetFlagArray();
00526 for (i=0; i<EdgePath2.GetNumCoords(); i++)
00527 {
00528
00529 TempStr._MakeMsg( TEXT("#1%d.\t#2%d\t#3%ld,\t#4%ld\r\n"),
00530 i, Verbs[i], Coords[i].x, Coords[i].y );
00531 (*Str) += TempStr;
00532 }
00533
00534 Path* RenderPath = NULL;
00535 if (BuildShapePath(&RenderPath))
00536 {
00537
00538 (*Str) += TEXT( "\r\nRender path\r\nNum\tType\tX Coord\tY Coord\r\n" );
00539 Verbs = RenderPath->GetVerbArray();
00540 Coords = RenderPath->GetCoordArray();
00541 Flags = RenderPath->GetFlagArray();
00542 for (i=0; i<RenderPath->GetNumCoords(); i++)
00543 {
00544
00545 TempStr._MakeMsg( TEXT("#1%d.\t#2%d\t#3%ld,\t#4%ld\r\n"),
00546 i, Verbs[i], Coords[i].x, Coords[i].y );
00547 (*Str) += TempStr;
00548 }
00549 }
00550 else
00551 {
00552 TempStr._MakeMsg( TEXT("Failed to build render path") );
00553 (*Str) += TempStr;
00554 }
00555 #endif
00556 }
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573 BOOL NodeRegularShape::SetUpShape()
00574 {
00575 if (EdgePath1.Initialise(4, 1) && EdgePath2.Initialise(4, 1))
00576 {
00577 DocCoord Fred1(0,0);
00578 DocCoord Fred2(72000,0);
00579 EdgePath1.SetPathPosition(0);
00580 EdgePath1.InsertMoveTo(Fred1);
00581 EdgePath1.InsertLineTo(Fred2);
00582 EdgePath2.SetPathPosition(0);
00583 EdgePath2.InsertMoveTo(Fred1);
00584 EdgePath2.InsertLineTo(Fred2);
00585 return TRUE;
00586 }
00587 else
00588 return FALSE;
00589 }
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 void NodeRegularShape::Transform( TransformBase& Trans )
00605 {
00606 if (IS_A(&Trans, Trans2DMatrix))
00607 {
00608 TransformMatrix *= ((Trans2DMatrix&)Trans).GetMatrix();
00609 }
00610 else
00611 {
00612
00613 Trans.Transform(&UTCentrePoint, 1);
00614 Trans.Transform(&UTMajorAxes, 1);
00615 Trans.Transform(&UTMinorAxes, 1);
00616 }
00617
00618 EmergencyFixShape();
00619
00620
00621 InvalidateBoundingRect();
00622 InvalidateCache();
00623
00624 DocRect dr = GetBoundingRect();
00625
00626
00627 TransformChildren(Trans);
00628
00629 InvalidateBoundingRect();
00630 InvalidateCache();
00631 dr = GetBoundingRect();
00632 }
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647 void NodeRegularShape::TransformCentreAndAxes( TransformBase& Trans )
00648 {
00649
00650 TransformMatrix.transform(&UTCentrePoint);
00651 Trans.Transform(&UTCentrePoint, 1);
00652 TransformMatrix.Inverse().transform(&UTCentrePoint);
00653
00654 TransformMatrix.transform(&UTMajorAxes);
00655 Trans.Transform(&UTMajorAxes, 1);
00656 TransformMatrix.Inverse().transform(&UTMajorAxes);
00657
00658 TransformMatrix.transform(&UTMinorAxes);
00659 Trans.Transform(&UTMinorAxes, 1);
00660 TransformMatrix.Inverse().transform(&UTMinorAxes);
00661
00662 EmergencyFixShape();
00663
00664
00665 InvalidateBoundingRect();
00666 InvalidateCache();
00667 }
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692 BOOL NodeRegularShape::BuildShapePath(Path** RenderPath)
00693 {
00694 if ((CachedRenderPath == NULL) || PathCacheInvalid)
00695 {
00696 DeleteCachedPath();
00697
00698 CachedRenderPath = new (Path);
00699 if (CachedRenderPath == NULL)
00700 return FALSE;
00701
00702 BOOL Success = TRUE;
00703
00704 if (IsCircular())
00705 {
00706 Success = BuildEllipsePath(CachedRenderPath);
00707 }
00708 else
00709 {
00710 DocCoord* pArray;
00711 Success = BuildPolygonPoints(&pArray);
00712 if (Success)
00713 Success = BuildPolygonPath(CachedRenderPath, pArray);
00714 if (pArray != NULL)
00715 delete [] pArray;
00716 }
00717
00718 if (Success)
00719 {
00720 DocCoord* Coords = CachedRenderPath->GetCoordArray();
00721 TransformMatrix.transform((Coord*)Coords, CachedRenderPath->GetNumCoords());
00722
00723 *RenderPath = CachedRenderPath;
00724 PathCacheInvalid = FALSE;
00725 return TRUE;
00726 }
00727 else
00728 {
00729 DeleteCachedPath();
00730 return FALSE;
00731 }
00732 }
00733 else
00734 {
00735 *RenderPath = CachedRenderPath;
00736 return TRUE;
00737 }
00738 }
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753 void NodeRegularShape::Render ( RenderRegion* pRender )
00754 {
00755 Path* pRenderPath = NULL;
00756
00757
00758 if ( BuildShapePath ( &pRenderPath ) )
00759 {
00760
00761 pRender->DrawPath ( pRenderPath, NULL, GetPathShape () );
00762 }
00763 }
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778 void NodeRegularShape::RenderEorDrag( RenderRegion* pRender )
00779 {
00780 Path* RenderPath = NULL;
00781
00782 if (BuildShapePath(&RenderPath))
00783 pRender->DrawPath(RenderPath);
00784 }
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 void NodeRegularShape::RenderObjectBlobs(RenderRegion* pRender)
00800 {
00801 pRender->SetLineColour(COLOUR_UNSELECTEDBLOB);
00802 pRender->SetFillColour(COLOUR_UNSELECTEDBLOB);
00803
00804
00805 DocRect BlobSize;
00806 BlobManager* pBlobMgr = GetApplication()->GetBlobManager();
00807 if (pBlobMgr != NULL)
00808 {
00809 DocCoord Point = GetCentrePoint();
00810 pBlobMgr->GetBlobRect(Point, &BlobSize);
00811
00812 pRender->DrawLine(DocCoord(BlobSize.hi.x, BlobSize.hi.y), DocCoord(BlobSize.lo.x, BlobSize.lo.y));
00813 pRender->DrawLine(DocCoord(BlobSize.lo.x, BlobSize.hi.y), DocCoord(BlobSize.hi.x, BlobSize.lo.y));
00814 pRender->DrawPixel(DocCoord(BlobSize.hi.x, BlobSize.lo.y));
00815 pRender->DrawPixel(DocCoord(BlobSize.lo.x, BlobSize.lo.y));
00816 }
00817
00818 pRender->SetLineColour(COLOUR_NONE);
00819
00820 if (!IsCircular())
00821 {
00822 DocCoord* Array;
00823 INT32 Points = 0;
00824 BOOL Success = BuildPolygonPoints(&Array, &Points);
00825 UINT32 Counter = 0;
00826 if (Success)
00827 {
00828 TransformMatrix.transform((Coord*)Array, Points);
00829 for (UINT32 loop = 0; loop < NumSides; loop++)
00830 {
00831
00832 Counter ++;
00833 if (IsPrimaryCurvature())
00834 Counter ++;
00835
00836 if (IsStellated())
00837 {
00838 if (IsStellationCurvature())
00839 {
00840 pRender->DrawBlob(Array[Counter], BT_UNSELECTED);
00841 pRender->DrawBlob(Array[Counter+1], BT_UNSELECTED);
00842 pRender->DrawBlob(Array[Counter+2], BT_UNSELECTED);
00843 pRender->SetLineColour(COLOUR_BEZIERLINE);
00844 pRender->DrawLine(Array[Counter], Array[Counter+1]);
00845 pRender->DrawLine(Array[Counter+1], Array[Counter+2]);
00846 pRender->SetLineColour(COLOUR_NONE);
00847 Counter += 3;
00848 }
00849 else
00850 pRender->DrawBlob(Array[Counter++], BT_UNSELECTED);
00851 }
00852
00853 if (IsPrimaryCurvature())
00854 {
00855 pRender->DrawBlob(Array[Counter], BT_UNSELECTED);
00856 pRender->DrawBlob(Array[Counter+1], BT_UNSELECTED);
00857 pRender->DrawBlob(Array[Counter+2], BT_UNSELECTED);
00858 pRender->SetLineColour(COLOUR_BEZIERLINE);
00859 pRender->DrawLine(Array[Counter], Array[Counter+1]);
00860 pRender->DrawLine(Array[Counter+1], Array[Counter+2]);
00861 pRender->SetLineColour(COLOUR_NONE);
00862 Counter ++;
00863 }
00864 else
00865 pRender->DrawBlob(Array[Counter], BT_UNSELECTED);
00866 }
00867 }
00868 if (Array != NULL)
00869 delete [] Array;
00870 }
00871 else
00872 {
00873 pRender->DrawBlob(GetMinorAxes(), BT_UNSELECTED);
00874 pRender->DrawBlob(GetMajorAxes(), BT_UNSELECTED);
00875 pRender->DrawBlob(GetCentrePoint() - (GetMajorAxes() - GetCentrePoint()), BT_UNSELECTED);
00876 pRender->DrawBlob(GetCentrePoint() - (GetMinorAxes() - GetCentrePoint()), BT_UNSELECTED);
00877 }
00878 }
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894 void NodeRegularShape::RenderTinyBlobs(RenderRegion* pRender)
00895 {
00896
00897 pRender->SetLineColour(COLOUR_NONE);
00898 pRender->SetFillColour(COLOUR_UNSELECTEDBLOB);
00899
00900 Path* RenderPath = NULL;
00901 if (BuildShapePath(&RenderPath))
00902 {
00903
00904 DocCoord* Coords = RenderPath->GetCoordArray();
00905
00906
00907 pRender->DrawBlob(Coords[0], BT_UNSELECTED);
00908 }
00909 }
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927 DocRect NodeRegularShape::GetBoundingRect(BOOL DontUseAttrs, BOOL HitTest)
00928 {
00929
00930 DocRect NewBoundingRect(GetCentrePoint(),GetCentrePoint());
00931
00932 if (!IsBoundingRectValid || DontUseAttrs)
00933 {
00934 Path* RenderPath = NULL;
00935 BuildShapePath(&RenderPath);
00936
00937
00938 if (!CalculatePathBoundingRect(*RenderPath, DontUseAttrs, &NewBoundingRect))
00939 {
00940
00941
00942 NewBoundingRect = RenderPath->GetBoundingRect();
00943 }
00944
00945
00946 if (DontUseAttrs)
00947 {
00948
00949 return NewBoundingRect;
00950 }
00951 else
00952 {
00953
00954
00955
00956 CCAttrMap AttribMap(30);
00957 if (FindAppliedAttributes(&AttribMap))
00958 {
00959 CCRuntimeClass *pType;
00960 void *pVal;
00961
00962
00963 for( CCAttrMap::iterator Pos = AttribMap.GetStartPosition(); Pos != AttribMap.GetEndPosition(); )
00964 {
00965
00966 AttribMap.GetNextAssoc(Pos,pType,pVal);
00967
00968 if (pVal != NULL)
00969 {
00970 if ( ((NodeAttribute*)pVal)->EffectsParentBounds() )
00971 {
00972
00973
00974 DocRect AttrBounds =
00975 ((NodeAttribute*)pVal)->GetAttrBoundingRect(this, &AttribMap);
00976 NewBoundingRect = NewBoundingRect.Union(AttrBounds);
00977 }
00978 }
00979 }
00980 }
00981 }
00982
00983
00984 BoundingRectangle = NewBoundingRect;
00985
00986
00987 IsBoundingRectValid = TRUE;
00988 }
00989
00990 return BoundingRectangle;
00991 }
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008 DocRect NodeRegularShape::GetBlobBoundingRect()
01009 {
01010
01011 DocRect Rect = GetBoundingRect();
01012
01013 Path* RenderPath = NULL;
01014 BuildShapePath(&RenderPath);
01015
01016
01017 BlobManager* pBlobMgr = GetApplication()->GetBlobManager();
01018 if (pBlobMgr!= NULL)
01019 {
01020 DocRect BlobSize;
01021
01022 DocCoord* Coords = RenderPath->GetCoordArray();
01023 pBlobMgr->GetBlobRect(Coords[0], &BlobSize);
01024 Rect = Rect.Union(BlobSize);
01025
01026
01027 DocCoord Point = GetCentrePoint();
01028 pBlobMgr->GetBlobRect(Point, &BlobSize);
01029 Rect = Rect.Union(BlobSize);
01030 }
01031
01032
01033 if (!IsCircular())
01034 {
01035 DocCoord* Array;
01036 INT32 Points = 0;
01037 BOOL Success = BuildPolygonPoints(&Array, &Points);
01038 UINT32 Counter = 0;
01039 if (Success)
01040 {
01041 TransformMatrix.transform((Coord*)Array, Points);
01042 DocRect BlobSize;
01043 for (UINT32 loop = 0; loop < NumSides; loop++)
01044 {
01045 if (IsStellated())
01046 {
01047 if (IsStellationCurvature())
01048 {
01049 pBlobMgr->GetBlobRect(Array[Counter], &BlobSize);
01050 Rect = Rect.Union(BlobSize);
01051 pBlobMgr->GetBlobRect(Array[Counter+1], &BlobSize);
01052 Rect = Rect.Union(BlobSize);
01053 pBlobMgr->GetBlobRect(Array[Counter+2], &BlobSize);
01054 Rect = Rect.Union(BlobSize);
01055 Counter += 3;
01056 }
01057 else
01058 {
01059 pBlobMgr->GetBlobRect(Array[Counter++], &BlobSize);
01060 Rect = Rect.Union(BlobSize);
01061 }
01062 }
01063
01064 if (IsPrimaryCurvature())
01065 {
01066 pBlobMgr->GetBlobRect(Array[Counter], &BlobSize);
01067 Rect = Rect.Union(BlobSize);
01068 pBlobMgr->GetBlobRect(Array[Counter+1], &BlobSize);
01069 Rect = Rect.Union(BlobSize);
01070 pBlobMgr->GetBlobRect(Array[Counter+2], &BlobSize);
01071 Rect = Rect.Union(BlobSize);
01072 Counter += 3;
01073 }
01074 else
01075 {
01076 pBlobMgr->GetBlobRect(Array[Counter++], &BlobSize);
01077 Rect = Rect.Union(BlobSize);
01078 }
01079 }
01080 }
01081 if (Array != NULL)
01082 delete [] Array;
01083 }
01084 else
01085 {
01086 DocRect BlobSize;
01087 DocCoord Point = GetMajorAxes();
01088 pBlobMgr->GetBlobRect(Point, &BlobSize);
01089 Rect = Rect.Union(BlobSize);
01090 DocCoord Opposite = GetCentrePoint() - (GetMajorAxes() - GetCentrePoint());
01091 pBlobMgr->GetBlobRect(Opposite, &BlobSize);
01092 Rect = Rect.Union(BlobSize);
01093 Point = GetMinorAxes();
01094 pBlobMgr->GetBlobRect(Point, &BlobSize);
01095 Rect = Rect.Union(BlobSize);
01096 Opposite = GetCentrePoint() - (GetMinorAxes() - GetCentrePoint());
01097 pBlobMgr->GetBlobRect(Opposite, &BlobSize);
01098 Rect = Rect.Union(BlobSize);
01099 }
01100
01101
01102 IncludeChildrensBoundingRects(&Rect);
01103
01104
01105 return Rect;
01106 }
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121 UINT32 NodeRegularShape::GetNodeSize() const
01122 {
01123 return (sizeof(NodeRegularShape));
01124 }
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145 BOOL NodeRegularShape::OnClick( DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods,
01146 Spread* pSpread)
01147 {
01148 #ifndef STANDALONE
01149
01150
01151 BlobManager* pBlobMgr = GetApplication()->GetBlobManager();
01152 if (pBlobMgr == NULL)
01153 return FALSE;
01154 if (!pBlobMgr->GetCurrentInterest().Object)
01155 return FALSE;
01156
01157 DocCoord Start;
01158 DocCoord End;
01159 INT32 DragPointNumber;
01160 ShapeClickEffect HitTest = DetermineClickEffect(&PointerPos, pSpread, &DragPointNumber, &Start, &End);
01161 switch (HitTest)
01162 {
01163 case SHAPECLICK_CENTRE:
01164 {
01165 return ClickCentre(PointerPos, Click, ClickMods, pSpread);
01166 break;
01167 }
01168 case SHAPECLICK_ELLIPSE:
01169 {
01170 return ClickEllipse(PointerPos, Click, ClickMods, pSpread, FALSE);
01171 break;
01172 }
01173 case SHAPECLICK_PRIMARY:
01174 {
01175 return ClickPrimary(PointerPos, Click, ClickMods, pSpread, TRUE);
01176 break;
01177 }
01178 case SHAPECLICK_RECTANGLE:
01179 {
01180 return ClickPrimary(PointerPos, Click, ClickMods, pSpread, FALSE);
01181 break;
01182 }
01183 case SHAPECLICK_STELLATION:
01184 {
01185 return ClickStellation(PointerPos, Click, ClickMods, pSpread);
01186 break;
01187 }
01188 case SHAPECLICK_PRIMARYCURVE:
01189 {
01190 return ClickPCurve(PointerPos, Click, ClickMods, pSpread, Start, End);
01191 break;
01192 }
01193 case SHAPECLICK_STELLATIONCURVE:
01194 {
01195 return ClickSCurve(PointerPos, Click, ClickMods, pSpread, Start, End);
01196 break;
01197 }
01198 default: break;
01199 }
01200
01201 #endif
01202
01203
01204 return FALSE;
01205 }
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228 BOOL NodeRegularShape::OnToolClick( DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods,
01229 Spread* pSpread)
01230 {
01231 #ifndef STANDALONE
01232
01233
01234 BOOL ClickUsed = OnClick(PointerPos, Click, ClickMods, pSpread);
01235
01236
01237 if (!ClickUsed)
01238 {
01239 DocCoord Start;
01240 DocCoord End;
01241 INT32 DragPointNumber;
01242 ShapeClickEffect HitTest = DetermineClickEffect(&PointerPos, pSpread, &DragPointNumber, &Start, &End);
01243
01244 if (HitTest==SHAPECLICK_EDGE1 || HitTest==SHAPECLICK_EDGE2)
01245 return ClickEdge(PointerPos, Click, ClickMods, pSpread, (HitTest==SHAPECLICK_EDGE1) );
01246 }
01247
01248 #endif
01249
01250
01251 return FALSE;
01252 }
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278 BOOL NodeRegularShape::CanBecomeA(BecomeA* pBecomeA)
01279 {
01280
01281 if (pBecomeA->BAPath())
01282 {
01283 pBecomeA->AddCount(1);
01284
01285 return TRUE;
01286 }
01287
01288 return FALSE;
01289 }
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308 BOOL NodeRegularShape::DoBecomeA(BecomeA* pBecomeA)
01309 {
01310
01311 ERROR2IF_PF(pBecomeA == NULL,FALSE,("pBecomeA is NULL"));
01312
01313
01314
01315 BOOL ValidReason = (pBecomeA->GetReason() == BECOMEA_REPLACE || pBecomeA->GetReason() == BECOMEA_PASSBACK);
01316 ERROR2IF_PF(!ValidReason,FALSE,("Unkown BecomeA reason %d",pBecomeA->GetReason()));
01317
01318
01319 BOOL Success = TRUE;
01320 NodePath* pNewNodePath = NULL;
01321
01322 if (pBecomeA->BAPath())
01323 {
01324
01325
01326
01327 ALLOC_WITH_FAIL(pNewNodePath, (new NodePath), pBecomeA->GetUndoOp());
01328 Success = (pNewNodePath != NULL);
01329
01330
01331 Path* ShapePath = NULL;
01332 if (Success)
01333 Success = BuildShapePath(&ShapePath);
01334 pNewNodePath->InkPath.Initialise(ShapePath->GetNumCoords(),1);
01335
01336 if (Success) CALL_WITH_FAIL(pNewNodePath->InkPath.CopyPathDataFrom(ShapePath), pBecomeA->GetUndoOp(), Success);
01337
01338
01339
01340 if (Success)
01341 {
01342 switch (pBecomeA->GetReason())
01343 {
01344 case BECOMEA_REPLACE :
01345 {
01346
01347 UndoableOperation* pOp = pBecomeA->GetUndoOp();
01348
01349
01350 NodeHidden* pNodeHidden = NULL;
01351 if (pOp != NULL)
01352 Success = pBecomeA->GetUndoOp()->DoHideNode(this, TRUE, &pNodeHidden);
01353
01354 if (Success)
01355 {
01356
01357 if (pOp != NULL)
01358 pNewNodePath->AttachNode(pNodeHidden,NEXT);
01359 else
01360 pNewNodePath->AttachNode(this,NEXT);
01361
01362
01363 CALL_WITH_FAIL(CopyChildrenTo(pNewNodePath), pBecomeA->GetUndoOp(), Success);
01364
01365 if (Success)
01366 {
01367
01368 pNewNodePath->InvalidateBoundingRect();
01369 pNewNodePath->SetSelected(IsSelected());
01370
01371
01372 if (pOp != NULL)
01373 {
01374 HideNodeAction* UndoHideNodeAction;
01375 Success = (HideNodeAction::Init(pBecomeA->GetUndoOp(),
01376 pBecomeA->GetUndoOp()->GetUndoActionList(),
01377 pNewNodePath,
01378 TRUE,
01379 ( Action**)(&UndoHideNodeAction))
01380 != AC_FAIL);
01381 }
01382 else
01383 {
01384 UnlinkNodeFromTree();
01385 CascadeDelete();
01386 delete this;
01387 return TRUE;
01388 }
01389 }
01390 }
01391
01392 if (Success)
01393 pBecomeA->PassBack(pNewNodePath,this);
01394 }
01395 break;
01396
01397 case BECOMEA_PASSBACK :
01398 Success = pBecomeA->PassBack(pNewNodePath,this);
01399 break;
01400
01401 default: break;
01402 }
01403 }
01404 }
01405
01406 if (!Success)
01407 {
01408 if (pNewNodePath != NULL)
01409 {
01410
01411
01412 pNewNodePath->CascadeDelete();
01413 delete pNewNodePath;
01414 pNewNodePath = NULL;
01415 }
01416 }
01417
01418 return Success;
01419 }
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442 NodePath* NodeRegularShape::GetVariableWidthStrokePath()
01443 {
01444
01445 AttrVariableWidth* pVarWidth = NULL;
01446 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrVariableWidth), (NodeAttribute**)&pVarWidth);
01447 if (pVarWidth == NULL || ((VariableWidthAttrValue*)pVarWidth->GetAttributeValue())->GetWidthFunction() == NULL)
01448 return NULL;
01449
01450
01451 AttrStrokeType* pStroke = NULL;
01452 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeType), (NodeAttribute**)&pStroke);
01453
01454 NodePath* pRetNode = NULL;
01455 if (pStroke && pStroke->HasPathProcessor())
01456 {
01457 PathProcessorStroke* pPPS = pStroke->GetPathProcessor();
01458
01459
01460 Path* pShapePath = NULL;
01461 if (BuildShapePath(&pShapePath))
01462 pRetNode = pPPS->GetProcessedPath(pShapePath, this);
01463
01464 ERROR2IF(!pRetNode, NULL, "Failed to get a Processed Path");
01465
01466
01467 Path CopyPath;
01468 CopyPath.Initialise();
01469 CopyPath.CloneFrom(pRetNode->InkPath);
01470
01471
01472
01473
01474 double ClippingFlatness = CopyPath.CalculateFlatnessValueFromPath(2.0, 375.0, 500.0);
01475 double SourceFlatness = pShapePath->CalculateFlatnessValueFromPath(2.0, 375.0, 500.0);
01476
01477 CopyPath.ClipPathToPath(*pShapePath, &(pRetNode->InkPath), 7, 1, ClippingFlatness, SourceFlatness);
01478
01479 pRetNode->InkPath.InitialiseFlags();
01480
01481 Spread *pSpread = Document::GetSelectedSpread();
01482
01483
01484
01485 double smoothness = 15.0;
01486
01487
01488 RetroSmooth rSmoother;
01489 rSmoother.Initialise();
01490 rSmoother.SetRenderFlag(false);
01491
01492
01493 pRetNode->InkPath.SetAllSubSelection();
01494 rSmoother.Changing(pRetNode, pSpread, smoothness);
01495 rSmoother.FinishedNoUndo(pRetNode);
01496 pRetNode->InkPath.ClearSubSelection();
01497
01498 }
01499
01500 return pRetNode;
01501 }
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525 NodePath* NodeRegularShape::GetSmoothVariableWidthStrokePath()
01526 {
01527
01528 AttrVariableWidth* pVarWidth = NULL;
01529 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrVariableWidth), (NodeAttribute**)&pVarWidth);
01530 if (pVarWidth == NULL || ((VariableWidthAttrValue*)pVarWidth->GetAttributeValue())->GetWidthFunction() == NULL)
01531 return NULL;
01532
01533
01534 AttrStrokeType* pStroke = NULL;
01535 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeType), (NodeAttribute**)&pStroke);
01536
01537 NodePath* pRetNode = NULL;
01538 if (pStroke && pStroke->HasPathProcessor())
01539 {
01540 PathProcessorStroke* pPPS = pStroke->GetPathProcessor();
01541
01542
01543 Path* pShapePath = NULL;
01544 if (BuildShapePath(&pShapePath))
01545 pRetNode = pPPS->GetSmoothProcessedPath(pShapePath, this);
01546
01547
01548 Path CopyPath;
01549 CopyPath.Initialise();
01550 CopyPath.CloneFrom(pRetNode->InkPath);
01551
01552
01553
01554
01555 double ClippingFlatness = CopyPath.CalculateFlatnessValueFromPath(2.0, 375.0, 500.0);
01556 double SourceFlatness = pShapePath->CalculateFlatnessValueFromPath(2.0, 375.0, 500.0);
01557
01558 CopyPath.ClipPathToPath(*pShapePath, &(pRetNode->InkPath), 7, 1, ClippingFlatness, SourceFlatness);
01559
01560 pRetNode->InkPath.InitialiseFlags();
01561 }
01562
01563 return pRetNode;
01564 }
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589 BOOL NodeRegularShape::Snap(DocCoord* pDocCoord)
01590 {
01591 #if !defined(EXCLUDE_FROM_RALPH)
01592 Path* RenderPath = NULL;
01593 BOOL Snapped = FALSE;
01594 if (BuildShapePath(&RenderPath))
01595 Snapped = CSnap::SnapCoordToPath(pDocCoord, RenderPath);
01596
01597 return Snapped;
01598 #else
01599 return FALSE;
01600 #endif
01601 }
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629 BOOL NodeRegularShape::Snap(DocRect* pDocRect,const DocCoord& PrevCoord,const DocCoord& CurCoord)
01630 {
01631 return FALSE;
01632 }
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650 BOOL NodeRegularShape::SnapToCoords(DocCoord* pDocCoord)
01651 {
01652 #if !defined(EXCLUDE_FROM_RALPH)
01653 BOOL IsSnapped = FALSE;
01654
01655
01656 DocCoord Centre=GetCentrePoint();
01657 if (IsMagneticallyClose(&Centre, pDocCoord))
01658 IsSnapped = TRUE;
01659
01660
01661 if (!IsSnapped)
01662 {
01663 if (IsCircular())
01664 {
01665 DocCoord Points[4];
01666 Points[0]=GetMinorAxes();
01667 Points[1]=GetMajorAxes();
01668 Points[2]=GetCentrePoint() - (GetMajorAxes() - GetCentrePoint());
01669 Points[3]=GetCentrePoint() - (GetMinorAxes() - GetCentrePoint());
01670
01671 for (INT32 loop = 0; (!IsSnapped && (loop<4)); loop++)
01672 IsSnapped = IsMagneticallyClose(&(Points[loop]), pDocCoord);
01673 }
01674 else
01675 {
01676 DocCoord* Array = NULL;
01677 INT32 Points = 0;
01678 if (BuildPolygonPoints(&Array, &Points))
01679 {
01680 TransformMatrix.transform((Coord*)Array, Points);
01681 for (INT32 loop = 0; ((loop < Points) && !IsSnapped); loop++)
01682 {
01683 if (IsMagneticallyClose(&(Array[loop]), pDocCoord))
01684 IsSnapped = TRUE;
01685 }
01686
01687
01688 if (IsARectangle() && !IsReformed())
01689 {
01690 for (INT32 loop = 1; ((loop < Points) && !IsSnapped); loop++)
01691 {
01692 DocCoord MidPoint( (Array[loop-1].x+Array[loop].x)/2, (Array[loop-1].y+Array[loop].y)/2 );
01693 if (IsMagneticallyClose(&MidPoint, pDocCoord))
01694 IsSnapped = TRUE;
01695 }
01696 }
01697 }
01698 if (Array != NULL)
01699 delete [] Array;
01700 }
01701 }
01702 else
01703 {
01704 }
01705
01706 return IsSnapped;
01707 #else
01708 return FALSE;
01709 #endif
01710 }
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731 String NodeRegularShape::Describe(BOOL Plural, BOOL Verbose)
01732 {
01733
01734 if (IsCircular())
01735 {
01736 if (Plural)
01737 return(String(_R(IDS_ELLIPSE_DESCRP)));
01738 else
01739 return(String(_R(IDS_ELLIPSE_DESCRS)));
01740 }
01741
01742
01743 if (IsARectangle())
01744 {
01745 if (Plural)
01746 return(String(_R(IDS_RECTANGLE_DESCRP)));
01747 else
01748 return(String(_R(IDS_RECTANGLE_DESCRS)));
01749 }
01750
01751
01752 if (Plural)
01753 return(String(_R(IDS_REGSHAPE_PLURAL)));
01754 else
01755 return(String(_R(IDS_REGSHAPE_SINGULAR)));
01756 };
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777 void NodeRegularShape::PositionPointFromRatio(DocCoord* PosPoint, const DocCoord* EndPoint, const double Ratio)
01778 {
01779 PosPoint->x = UTCentrePoint.x + (INT32)((EndPoint->x - UTCentrePoint.x)*Ratio) ;
01780 PosPoint->y = UTCentrePoint.y + (INT32)((EndPoint->y - UTCentrePoint.y)*Ratio) ;
01781 }
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798 BOOL NodeRegularShape::MakeRegular(DocCoord RegularPoint)
01799 {
01800 #ifndef STANDALONE
01801
01802 ERROR3IF(NumSides < REGULARSHAPE_MINSIDES, "Shape not inited!");
01803
01804 OpShapeMakeRegular* Apple = new OpShapeMakeRegular;
01805 if (Apple != NULL)
01806 {
01807 Apple->DoMakeRegular(this, RegularPoint);
01808 return TRUE;
01809 }
01810 else
01811 return FALSE;
01812 #else
01813 return FALSE;
01814 #endif
01815 }
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833 BOOL NodeRegularShape::MakeStraight(BOOL StraightenOne)
01834 {
01835 #ifndef STANDALONE
01836
01837 ERROR3IF(NumSides < REGULARSHAPE_MINSIDES, "Shape not inited!");
01838
01839 EditRegularShapeParam ChangeData(this);
01840 Path NewEdge;
01841
01842
01843 if (NewEdge.Initialise(4, 1))
01844 {
01845 DocCoord Fred1(0,0);
01846 DocCoord Fred2(72000,0);
01847 NewEdge.SetPathPosition(0);
01848 NewEdge.AddMoveTo(Fred1);
01849 NewEdge.AddCurveTo(Fred2);
01850 }
01851 else
01852 {
01853 Error::SetError(_R(IDS_OUT_OF_MEMORY));
01854 return FALSE;
01855 }
01856
01857 if (StraightenOne)
01858 ChangeData.NewEdgePath1 = &NewEdge;
01859 else
01860 ChangeData.NewEdgePath2 = &NewEdge;
01861
01862
01863 OpDescriptor* Apple = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpEditRegularShape));
01864 if (Apple != NULL)
01865 {
01866 Apple->Invoke(&ChangeData);
01867 return TRUE;
01868 }
01869 else
01870 {
01871 Error::SetError(_R(IDS_OUT_OF_MEMORY));
01872 return FALSE;
01873 }
01874 #else
01875 return TRUE;
01876 #endif
01877 }
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907 ShapeClickEffect NodeRegularShape::DetermineClickEffect(DocCoord* pPos, Spread* pSpread,
01908 INT32* pPointNum, DocCoord* pStart, DocCoord* pEnd)
01909 {
01910 #ifndef STANDALONE
01911
01912
01913 if (FindParentSpread() != pSpread)
01914 return SHAPECLICK_NONE;
01915
01916 DocRect BlobBounds;
01917 DocCoord Interest;
01918 *pPointNum = -1;
01919
01920
01921
01922 if (!IsCircular())
01923 {
01924 DocCoord* Array;
01925 INT32 Points = 0;
01926 BOOL Success = BuildPolygonPoints(&Array, &Points);
01927 UINT32 Counter = 0;
01928 ShapeClickEffect TempEffect = SHAPECLICK_NONE;
01929 if (Success)
01930 {
01931 TransformMatrix.transform((Coord*)Array,Points);
01932 for (UINT32 loop = 0; loop < NumSides; loop++)
01933 {
01934 UINT32 EndOffset = 1;
01935 DocCoord Start = Array[Counter];
01936 DocCoord StellEnd(0,0);
01937 DocCoord PrimeEnd;
01938 if (IsPrimaryCurvature())
01939 EndOffset++ ;
01940 if (IsStellated())
01941 {
01942 if (IsStellationCurvature())
01943 EndOffset++;
01944 StellEnd = Array[Counter + EndOffset];
01945 EndOffset++;
01946 if (IsStellationCurvature())
01947 EndOffset++;
01948 }
01949 if (IsPrimaryCurvature())
01950 EndOffset++ ;
01951 PrimeEnd = Array[Counter + EndOffset];
01952
01953 GetApplication()->GetBlobManager()->GetBlobRect(Array[Counter++],&BlobBounds);
01954 if (BlobBounds.ContainsCoord(*pPos))
01955 {
01956 TempEffect = SHAPECLICK_PRIMARY;
01957 *pPos = Array[Counter-1];
01958 *pPointNum = Counter-1;
01959 goto FoundBlob;
01960 }
01961
01962 if (IsPrimaryCurvature())
01963 {
01964 GetApplication()->GetBlobManager()->GetBlobRect(Array[Counter++],&BlobBounds);
01965 if (BlobBounds.ContainsCoord(*pPos))
01966 {
01967 *pPos = Array[Counter-1];
01968 *pPointNum = Counter-1;
01969 if (pStart != NULL)
01970 *pStart = Start;
01971 if (pEnd != NULL)
01972 {
01973 if (IsStellated())
01974 *pEnd = StellEnd;
01975 else
01976 *pEnd = PrimeEnd;
01977 }
01978 TempEffect = SHAPECLICK_PRIMARYCURVE;
01979 goto FoundBlob;
01980 }
01981 }
01982
01983 if (IsStellated())
01984 {
01985
01986 if (IsStellationCurvature())
01987 {
01988 GetApplication()->GetBlobManager()->GetBlobRect(Array[Counter++],&BlobBounds);
01989 if (BlobBounds.ContainsCoord(*pPos))
01990 {
01991 *pPos = Array[Counter-1];
01992 *pPointNum = Counter-1;
01993 if (pStart != NULL)
01994 *pStart = StellEnd;
01995 if (pEnd != NULL)
01996 *pEnd = Start;
01997 TempEffect = SHAPECLICK_STELLATIONCURVE;
01998 goto FoundBlob;
01999 }
02000 }
02001
02002
02003 GetApplication()->GetBlobManager()->GetBlobRect(Array[Counter++],&BlobBounds);
02004 if (BlobBounds.ContainsCoord(*pPos))
02005 {
02006 *pPos = Array[Counter-1];
02007 *pPointNum = Counter-1;
02008 TempEffect = SHAPECLICK_STELLATION;
02009 goto FoundBlob;
02010 }
02011
02012
02013 if (IsStellationCurvature())
02014 {
02015 GetApplication()->GetBlobManager()->GetBlobRect(Array[Counter++],&BlobBounds);
02016 if (BlobBounds.ContainsCoord(*pPos))
02017 {
02018 *pPos = Array[Counter-1];
02019 *pPointNum = Counter-1;
02020 if (pStart != NULL)
02021 *pStart = StellEnd;
02022 if (pEnd != NULL)
02023 *pEnd = PrimeEnd;
02024 TempEffect = SHAPECLICK_STELLATIONCURVE;
02025 goto FoundBlob;
02026 }
02027 }
02028 }
02029
02030 if (IsPrimaryCurvature())
02031 {
02032 GetApplication()->GetBlobManager()->GetBlobRect(Array[Counter++],&BlobBounds);
02033 if (BlobBounds.ContainsCoord(*pPos))
02034 {
02035 *pPos = Array[Counter-1];
02036 *pPointNum = Counter-1;
02037 if (pEnd != NULL)
02038 {
02039 if (IsStellated())
02040 *pEnd = StellEnd;
02041 else
02042 *pEnd = Start;
02043 }
02044 if (pStart != NULL)
02045 *pStart = PrimeEnd;
02046 TempEffect = SHAPECLICK_PRIMARYCURVE;
02047 goto FoundBlob;
02048 }
02049 }
02050 }
02051 }
02052 FoundBlob:
02053 if (Array != NULL)
02054 delete [] Array;
02055 if ((TempEffect == SHAPECLICK_PRIMARY) && IsARectangle())
02056 TempEffect = SHAPECLICK_RECTANGLE;
02057 if (TempEffect != SHAPECLICK_NONE)
02058 return TempEffect;
02059 }
02060 else
02061 {
02062
02063
02064 DocCoord Opposite = GetCentrePoint() - (GetMajorAxes() - GetCentrePoint());
02065 DocRect OppBounds;
02066 GetApplication()->GetBlobManager()->GetBlobRect(Opposite,&OppBounds);
02067 DocCoord Point = GetMajorAxes();
02068 GetApplication()->GetBlobManager()->GetBlobRect(Point,&BlobBounds);
02069 if (BlobBounds.ContainsCoord(*pPos))
02070 {
02071 *pPos = Point;
02072 return SHAPECLICK_ELLIPSE;
02073 }
02074 if (OppBounds.ContainsCoord(*pPos))
02075 {
02076 *pPos = Opposite;
02077 return SHAPECLICK_ELLIPSE;
02078 }
02079
02080
02081 Opposite = GetCentrePoint() - (GetMinorAxes() - GetCentrePoint());
02082 GetApplication()->GetBlobManager()->GetBlobRect(Opposite,&OppBounds);
02083 Point = GetMinorAxes();
02084 GetApplication()->GetBlobManager()->GetBlobRect(Point,&BlobBounds);
02085 if (BlobBounds.ContainsCoord(*pPos))
02086 {
02087 *pPos = Point;
02088 return SHAPECLICK_ELLIPSE;
02089 }
02090 if (OppBounds.ContainsCoord(*pPos))
02091 {
02092 *pPos = Opposite;
02093 return SHAPECLICK_ELLIPSE;
02094 }
02095 }
02096
02097
02098 Interest = GetCentrePoint();
02099 GetApplication()->GetBlobManager()->GetBlobRect(Interest,&BlobBounds);
02100 if (BlobBounds.ContainsCoord(*pPos))
02101 {
02102 *pPos = Interest;
02103 return SHAPECLICK_CENTRE;
02104 }
02105
02106
02107
02108 if (!IsCircular())
02109 {
02110 Path* RenderPath = NULL;
02111 INT32 tempPos;
02112 BuildShapePath(&RenderPath);
02113 if (RenderPath->PointCloseToLine(*pPos, &tempPos))
02114 {
02115
02116 const UINT32 EdgePath1Count = EdgePath1.GetNumCoords()-1;
02117 const UINT32 EdgePath2Count = EdgePath2.GetNumCoords()-1;
02118 INT32 Current = EdgePath1Count;
02119 if (Current >= tempPos)
02120 return SHAPECLICK_EDGE1;
02121 while (Current <= RenderPath->GetNumCoords()-1)
02122 {
02123 if (Current >= tempPos)
02124 return SHAPECLICK_EDGE1;
02125
02126
02127 if (IsStellated() && IsStellationCurvature())
02128 {
02129 Current += 3;
02130 if (Current >= tempPos)
02131 return SHAPECLICK_NONE;
02132 }
02133
02134
02135 if (IsStellated())
02136 {
02137 Current += EdgePath2Count;
02138 if (Current >= tempPos)
02139 return SHAPECLICK_EDGE2;
02140 }
02141
02142
02143 if (IsPrimaryCurvature())
02144 {
02145 Current += 3;
02146 if (Current >= tempPos)
02147 return SHAPECLICK_NONE;
02148 }
02149
02150
02151 Current += EdgePath1Count;
02152 }
02153 ERROR3("Didn't find Current in RenderPath!");
02154 return SHAPECLICK_NONE;
02155 }
02156 }
02157
02158 #endif
02159
02160
02161 return SHAPECLICK_NONE;
02162 }
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186 BOOL NodeRegularShape::InsertShapeEdge(Path* RenderPath, Path* Edge, DocCoord NewEnd)
02187 {
02188
02189 if (Edge->GetNumCoords() == 2)
02190 {
02191 return RenderPath->AddLineTo(NewEnd);
02192 }
02193 else
02194 {
02195 ERROR3IF(Edge->GetNumCoords() != 4,"The edge path did not consist of a single Bezier curve");
02196
02197 DocCoord* EdgeCoords = Edge->GetCoordArray();
02198 DocCoord* RenderCoords = RenderPath->GetCoordArray();
02199
02200
02201 DocCoord InsertStart = RenderCoords[RenderPath->GetNumCoords()-1];
02202 DocCoord EdgeStart = EdgeCoords[0];
02203 DocCoord EdgeEnd = EdgeCoords[3];
02204
02205
02206 if (InsertStart == NewEnd)
02207 {
02208 return RenderPath->AddCurveTo(InsertStart, NewEnd, NewEnd);
02209 }
02210
02211
02212 DocCoord ControlPoints[2];
02213 ControlPoints[0] = EdgeCoords[1] - EdgeCoords[0];
02214 ControlPoints[1] = EdgeCoords[2] - EdgeCoords[0];
02215 double ScaleFactor = InsertStart.Distance(NewEnd)/EdgeStart.Distance(EdgeEnd);
02216
02217 double EdgeRotation = atan2( (double)(EdgeEnd.y-EdgeStart.y) , (double)(EdgeEnd.x-EdgeStart.x) );
02218 double InsertRotation = atan2( (double)(NewEnd.y-InsertStart.y) , (double)(NewEnd.x-InsertStart.x) );
02219 double theta = InsertRotation - EdgeRotation;
02220
02221 double a = ScaleFactor * cos(theta);
02222 double b = ScaleFactor * sin(theta);
02223 double c = -ScaleFactor * sin(theta);
02224 double d = ScaleFactor * cos(theta);
02225 INT32 e = InsertStart.x;
02226 INT32 f = InsertStart.y;
02227
02228 Trans2DMatrix Trans(Matrix(a,b,c,d,e,f));
02229 Trans.Transform( ControlPoints, 2);
02230
02231 return RenderPath->AddCurveTo(ControlPoints[0], ControlPoints[1], NewEnd);
02232 }
02233 }
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252 BOOL NodeRegularShape::BuildEllipsePath(Path* RenderPath)
02253 {
02254 ERROR3IF(!IsCircular(),"BuildEllipsePath called for a non-elliptical shape");
02255
02256
02257 if (!RenderPath->Initialise(12,4) )
02258 {
02259 return FALSE;
02260 }
02261
02262 RenderPath->SetPathPosition(0);
02263
02264
02265 const DocCoord w( UTMinorAxes);
02266 const DocCoord x( UTCentrePoint + (UTCentrePoint - UTMajorAxes) );
02267 const DocCoord y( UTCentrePoint + (UTCentrePoint - UTMinorAxes) );
02268 const DocCoord z( UTMajorAxes );
02269
02270
02271 const DocCoord a( UTMinorAxes + (UTMajorAxes - UTCentrePoint) );
02272 const DocCoord b( UTMinorAxes - (UTMajorAxes - UTCentrePoint) );
02273 const DocCoord c( y - (UTMajorAxes - UTCentrePoint) );
02274 const DocCoord d( y + (UTMajorAxes - UTCentrePoint) );
02275
02276
02277 BOOL Success = TRUE;
02278
02279
02280 DocCoord CP1;
02281 DocCoord CP2;
02282
02283
02284 Success = RenderPath->AddMoveTo(z);
02285
02286
02287 if (Success)
02288 {
02289 CP1 = DocCoord::PositionPointFromRatio(z, a, CurveFactor);
02290 CP2 = DocCoord::PositionPointFromRatio(w, a, CurveFactor);
02291 Success = RenderPath->AddCurveTo(CP1, CP2, w);
02292 }
02293
02294
02295 if (Success)
02296 {
02297 CP1 = DocCoord::PositionPointFromRatio(w, b, CurveFactor);
02298 CP2 = DocCoord::PositionPointFromRatio(x, b, CurveFactor);
02299 Success = RenderPath->AddCurveTo(CP1, CP2, x);
02300 }
02301
02302
02303 if (Success)
02304 {
02305 CP1 = DocCoord::PositionPointFromRatio(x, c, CurveFactor);
02306 CP2 = DocCoord::PositionPointFromRatio(y, c, CurveFactor);
02307 Success = RenderPath->AddCurveTo(CP1, CP2, y);
02308 }
02309
02310
02311 if (Success)
02312 {
02313 CP1 = DocCoord::PositionPointFromRatio(y, d, CurveFactor);
02314 CP2 = DocCoord::PositionPointFromRatio(z, d, CurveFactor);
02315 Success = RenderPath->AddCurveTo(CP1, CP2, z);
02316 }
02317
02318
02319 if (Success)
02320 {
02321 RenderPath->CloseSubPath();
02322 RenderPath->IsFilled = TRUE;
02323 }
02324
02325 return Success;
02326 }
02327
02328
02329
02330 class FloatCoord
02331 {
02332 public:
02333 FloatCoord() {};
02334 FloatCoord(double initX, double initY) {X = initX; Y = initY;};
02335 double X;
02336 double Y;
02337 };
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363 BOOL NodeRegularShape::BuildPolygonPoints(DocCoord** pArray, INT32* NumPoints)
02364 {
02365 ERROR3IF(IsCircular(),"Can't build a points array for a circular shape!");
02366 ERROR2IF(NumSides == 0, FALSE, "Zero number of sides!");
02367 ERROR3IF(IsPrimaryCurvature() && !IsStellationCurvature(), "Shape has primary curvature but not stellation curvature");
02368 ERROR3IF(!IsPrimaryCurvature() && IsStellationCurvature(), "Shape has stellation curvature but not primary curvature");
02369
02370 FloatCoord* pFloatArray = NULL;
02371 DocCoord* pDocArray = *pArray;
02372
02373
02374 UINT32 FloatElements = NumSides;
02375 UINT32 DocElements = NumSides;
02376 if (IsStellated())
02377 {
02378 FloatElements += NumSides;
02379 DocElements += NumSides;
02380 }
02381 if (IsPrimaryCurvature())
02382 DocElements += NumSides*2;
02383 if (IsStellated() && IsStellationCurvature())
02384 DocElements += NumSides*2;
02385 DocElements += 3;
02386 FloatElements += 2;
02387
02388 pFloatArray = new FloatCoord[FloatElements];
02389 pDocArray = new DocCoord[DocElements];
02390 *pArray = pDocArray;
02391
02392
02393 if ( (pDocArray == NULL) || (pFloatArray == NULL) )
02394 {
02395 if (pDocArray != NULL)
02396 delete [] pDocArray;
02397 if (pFloatArray != NULL)
02398 delete [] pFloatArray;
02399 return FALSE;
02400 }
02401
02402
02403 double CurrentAngle = (float)(PI/NumSides);
02404 const double AngleInc = (float)((2*PI)/NumSides);
02405 const double StellationInc = (float)((AngleInc/2) + (StellOffsetRatio*AngleInc));
02406 const double MaxRadius = 0.5;
02407 double Radius = MaxRadius;
02408 double StellationRadius = Stellated ? (Radius * StellRadiusToPrimary) : Radius;
02409 if (StellationRadius > MaxRadius)
02410 {
02411 const double ratio = StellationRadius/Radius;
02412 Radius = Radius / ratio;
02413 StellationRadius = StellationRadius / ratio;
02414 }
02415 const FloatCoord InitialPrimaryPoint(0.0, Radius);
02416 const FloatCoord InitialStellationPoint(0.0, StellationRadius);
02417 UINT32 FloatCounter = 0;
02418 FloatCoord TempCoord;
02419
02420 UINT32 CurrentSide;
02421 for( CurrentSide = 0; CurrentSide < NumSides; CurrentSide++)
02422 {
02423
02424 TempCoord.X = (float)(InitialPrimaryPoint.X*cos(CurrentAngle)
02425 - InitialPrimaryPoint.Y*sin(CurrentAngle) + MaxRadius);
02426 TempCoord.Y = (float)(InitialPrimaryPoint.X*sin(CurrentAngle)
02427 + InitialPrimaryPoint.Y*cos(CurrentAngle) + MaxRadius);
02428 pFloatArray[FloatCounter++] = TempCoord;
02429
02430
02431 if (Stellated)
02432 {
02433 TempCoord.X = (float)(InitialStellationPoint.X*cos(CurrentAngle+StellationInc)
02434 - InitialStellationPoint.Y*sin(CurrentAngle+StellationInc) + MaxRadius);
02435 TempCoord.Y = (float)(InitialStellationPoint.X*sin(CurrentAngle+StellationInc)
02436 + InitialStellationPoint.Y*cos(CurrentAngle+StellationInc) + MaxRadius);
02437 pFloatArray[FloatCounter++] = TempCoord;
02438 }
02439
02440 CurrentAngle += AngleInc;
02441 }
02442
02443 pFloatArray[FloatCounter] = pFloatArray[0];
02444 ERROR3IF(FloatCounter >= FloatElements, "Ran over end of FloatCoord array");
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457 DocCoord OuterMajor = UTMajorAxes;
02458 DocCoord OuterMinor = UTMinorAxes;
02459
02460
02461
02462 if (IsStellated() && (GetStellRadiusToPrimary() > 1.0))
02463 {
02464 PositionPointFromRatio(&OuterMajor, &UTMajorAxes, GetStellRadiusToPrimary());
02465 PositionPointFromRatio(&OuterMinor, &UTMinorAxes, GetStellRadiusToPrimary());
02466 }
02467
02468
02469
02470 const DocCoord ParallelOrigin(UTCentrePoint.x*3 - (OuterMajor.x + OuterMinor.x),
02471 UTCentrePoint.y*3 - (OuterMajor.y + OuterMinor.y));
02472 const DocCoord ParallelA((OuterMajor.x - (OuterMinor.x-UTCentrePoint.x)) - ParallelOrigin.x,
02473 (OuterMajor.y - (OuterMinor.y-UTCentrePoint.y)) - ParallelOrigin.y);
02474 const DocCoord ParallelB((OuterMinor.x - (OuterMajor.x-UTCentrePoint.x)) - ParallelOrigin.x,
02475 (OuterMinor.y - (OuterMajor.y-UTCentrePoint.y)) - ParallelOrigin.y);
02476
02477 UINT32 DocCounter = 0;
02478 FloatCounter = 0;
02479 DocCoord PrimaryPoint;
02480 DocCoord StellationPoint(0,0);
02481 DocCoord NextPrimary;
02482
02483
02484 FloatCoord InitPrimeFloat = pFloatArray[FloatCounter++];
02485 NextPrimary.x = (INT32)(InitPrimeFloat.X*ParallelB.x + InitPrimeFloat.Y*ParallelA.x) + ParallelOrigin.x;
02486 NextPrimary.y = (INT32)(InitPrimeFloat.X*ParallelB.y + InitPrimeFloat.Y*ParallelA.y) + ParallelOrigin.y;
02487
02488
02489
02490
02491
02492 for (CurrentSide = 0; CurrentSide < NumSides; CurrentSide++)
02493 {
02494
02495 PrimaryPoint = NextPrimary;
02496 pDocArray[DocCounter++] = PrimaryPoint;
02497
02498
02499 if (IsStellated())
02500 {
02501 const FloatCoord StellFloat = pFloatArray[FloatCounter++];
02502 StellationPoint.x = (INT32)(StellFloat.X*ParallelB.x + StellFloat.Y*ParallelA.x) + ParallelOrigin.x;
02503 StellationPoint.y = (INT32)(StellFloat.X*ParallelB.y + StellFloat.Y*ParallelA.y) + ParallelOrigin.y;
02504
02505 }
02506
02507
02508 const FloatCoord PrimeFloat = pFloatArray[FloatCounter++];
02509 NextPrimary.x = (INT32)(PrimeFloat.X*ParallelB.x + PrimeFloat.Y*ParallelA.x) + ParallelOrigin.x;
02510 NextPrimary.y = (INT32)(PrimeFloat.X*ParallelB.y + PrimeFloat.Y*ParallelA.y) + ParallelOrigin.y;
02511
02512
02513 if (IsPrimaryCurvature())
02514 DocCounter++;
02515
02516 if (IsStellated())
02517 {
02518 if (IsStellationCurvature())
02519 DocCounter ++;
02520
02521 pDocArray[DocCounter++] = StellationPoint;
02522
02523 if (IsStellationCurvature())
02524 DocCounter ++;
02525 }
02526
02527 if (IsPrimaryCurvature())
02528 DocCounter++;
02529 }
02530 pDocArray[DocCounter] = pDocArray[0];
02531
02532
02533 if (IsPrimaryCurvature())
02534 {
02535
02536 double temp = UTCentrePoint.Distance(OuterMajor) ;
02537 const double OuterMajorLength = (temp > 1.0) ? (temp) : (1.0);
02538 const double PrimaryCurvatureLength = OuterMajorLength * GetPrimaryCurveToPrimary();
02539 const double StellationCurvatureLength = OuterMajorLength * GetStellCurveToStell();
02540
02541 DocCounter = 0;
02542 DocCoord TempCoord;
02543
02544 for (CurrentSide = 0; CurrentSide < NumSides; CurrentSide++)
02545 {
02546 DocCoord PrimaryPoint = pDocArray[DocCounter];
02547 DocCoord StellationPoint = pDocArray[DocCounter+3];
02548 DocCoord NextPrimary = IsStellated() ? pDocArray[DocCounter+6] : pDocArray[DocCounter+3];
02549
02550
02551
02552 if (IsStellated())
02553 {
02554
02555 double DistanceToNext = PrimaryPoint.Distance(StellationPoint);
02556 double FitRatio;
02557 if ((DistanceToNext < 1.0) || ((PrimaryCurvatureLength + StellationCurvatureLength) < 1.0))
02558 TempCoord = PrimaryPoint;
02559 else
02560 {
02561 FitRatio = PrimaryCurvatureLength / DistanceToNext;
02562 if ((PrimaryCurvatureLength + StellationCurvatureLength) > DistanceToNext)
02563 {
02564 double Scaler = DistanceToNext / (PrimaryCurvatureLength + StellationCurvatureLength);
02565 FitRatio = (PrimaryCurvatureLength * Scaler) / DistanceToNext;
02566 }
02567 TempCoord = DocCoord::PositionPointFromRatio(PrimaryPoint, StellationPoint, FitRatio);
02568 }
02569 }
02570 else
02571 {
02572
02573 double DistanceToNext = PrimaryPoint.Distance(NextPrimary);
02574 double FitRatio = 0.5;
02575 if (DistanceToNext < 1.0)
02576 TempCoord = PrimaryPoint;
02577 else
02578 {
02579 if ((PrimaryCurvatureLength + PrimaryCurvatureLength) < DistanceToNext)
02580 FitRatio = PrimaryCurvatureLength / DistanceToNext;
02581
02582 TempCoord = DocCoord::PositionPointFromRatio(PrimaryPoint, NextPrimary, FitRatio);
02583 }
02584 }
02585 pDocArray[DocCounter+1] = TempCoord;
02586
02587 if (IsStellated())
02588 {
02589
02590 double DistanceToNext = PrimaryPoint.Distance(StellationPoint);
02591 if ((DistanceToNext < 1.0) || ((PrimaryCurvatureLength + StellationCurvatureLength) < 1.0))
02592 TempCoord = StellationPoint;
02593 else
02594 {
02595 double FitRatio = StellationCurvatureLength / DistanceToNext;
02596 if ((PrimaryCurvatureLength + StellationCurvatureLength) > DistanceToNext)
02597 {
02598 double Scaler = DistanceToNext / (PrimaryCurvatureLength + StellationCurvatureLength);
02599 FitRatio = (StellationCurvatureLength * Scaler) / DistanceToNext;
02600 }
02601 TempCoord = DocCoord::PositionPointFromRatio(StellationPoint, PrimaryPoint, FitRatio);
02602 }
02603 pDocArray[DocCounter+2] = TempCoord;
02604
02605
02606 DistanceToNext = StellationPoint.Distance(NextPrimary);
02607 if ((DistanceToNext < 1.0) || ((PrimaryCurvatureLength + StellationCurvatureLength) < 1.0))
02608 TempCoord = StellationPoint;
02609 else
02610 {
02611 double FitRatio = StellationCurvatureLength / DistanceToNext;
02612 if ((PrimaryCurvatureLength + StellationCurvatureLength) > DistanceToNext)
02613 {
02614 double Scaler = DistanceToNext / (PrimaryCurvatureLength + StellationCurvatureLength);
02615 FitRatio = (StellationCurvatureLength * Scaler) / DistanceToNext;
02616 }
02617 TempCoord = DocCoord::PositionPointFromRatio(StellationPoint, NextPrimary, FitRatio);
02618 }
02619 pDocArray[DocCounter+4] = TempCoord;
02620 }
02621
02622
02623
02624 if (IsStellated())
02625 {
02626
02627 double DistanceToNext = StellationPoint.Distance(NextPrimary);
02628 if ((DistanceToNext < 1.0) || ((PrimaryCurvatureLength + StellationCurvatureLength) < 1.0))
02629 TempCoord = StellationPoint;
02630 else
02631 {
02632 double FitRatio = PrimaryCurvatureLength / DistanceToNext;
02633 if ((PrimaryCurvatureLength + StellationCurvatureLength) > DistanceToNext)
02634 {
02635 double Scaler = DistanceToNext / (PrimaryCurvatureLength + StellationCurvatureLength);
02636 FitRatio = (PrimaryCurvatureLength * Scaler) / DistanceToNext;
02637 }
02638 TempCoord = DocCoord::PositionPointFromRatio(NextPrimary, StellationPoint, FitRatio);
02639 }
02640
02641 pDocArray[DocCounter+5] = TempCoord;
02642 }
02643 else
02644 {
02645
02646 double DistanceToNext = PrimaryPoint.Distance(NextPrimary);
02647 if (DistanceToNext < 1.0)
02648 TempCoord = PrimaryPoint;
02649 else
02650 {
02651 double FitRatio = 0.5;
02652 if ((PrimaryCurvatureLength + PrimaryCurvatureLength) < DistanceToNext)
02653 FitRatio = PrimaryCurvatureLength / DistanceToNext;
02654
02655 TempCoord = DocCoord::PositionPointFromRatio(NextPrimary, PrimaryPoint, FitRatio);
02656 }
02657 pDocArray[DocCounter+2] = TempCoord;
02658 }
02659
02660
02661 DocCounter+=3;
02662 if (IsStellated())
02663 DocCounter+=3;
02664 }
02665 }
02666
02667 pDocArray[DocCounter++] = pDocArray[0];
02668 pDocArray[DocCounter] = pDocArray[1];
02669
02670
02671
02672
02673
02674
02675
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688 delete [] pFloatArray;
02689
02690 ERROR3IF(DocCounter >= DocElements, "Ran over end of DocCoord array");
02691
02692 if (NumPoints != NULL)
02693 *NumPoints = DocCounter+1;
02694 return TRUE;
02695 }
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715 BOOL NodeRegularShape::BuildPolygonPath(Path* RenderPath, DocCoord* pArray)
02716 {
02717 ERROR2IF(NumSides == 0, FALSE, "This shape has zero sides!");
02718 ERROR3IF(IsCircular(), "Building a polygon path for an ellipse!");
02719
02720
02721 INT32 Slots = NumSides*(EdgePath1.GetNumCoords()-1);
02722 if (IsStellated())
02723 Slots += NumSides*(EdgePath2.GetNumCoords()-1);
02724 if (IsPrimaryCurvature())
02725 Slots += NumSides*4;
02726 if (IsStellationCurvature())
02727 Slots += (NumSides-1)*4;
02728
02729 if (!RenderPath->Initialise(Slots,4) )
02730 {
02731 return FALSE;
02732 }
02733 RenderPath->SetPathPosition(0);
02734
02735 UINT32 Counter = 0;
02736 BOOL Success = TRUE;
02737
02738
02739 if (IsPrimaryCurvature())
02740 Success = RenderPath->AddMoveTo(pArray[1]);
02741 else
02742 Success = RenderPath->AddMoveTo(pArray[0]);
02743
02744 UINT32 CurrentSide;
02745 for( CurrentSide = 0; (CurrentSide < NumSides) && Success; CurrentSide++)
02746 {
02747
02748 Counter ++;
02749 if (IsPrimaryCurvature())
02750 Counter++;
02751
02752
02753 Success = InsertShapeEdge(RenderPath, &EdgePath1, pArray[Counter]);
02754
02755 if (IsStellated())
02756 {
02757
02758 if (IsStellationCurvature() && Success)
02759 {
02760 DocCoord CP1;
02761 DocCoord CP2;
02762 CP1 = DocCoord::PositionPointFromRatio(pArray[Counter], pArray[Counter+1], CurveFactor);
02763 CP2 = DocCoord::PositionPointFromRatio(pArray[Counter+2], pArray[Counter+1], CurveFactor);
02764 Success = RenderPath->AddCurveTo(CP1, CP2, pArray[Counter+2]);
02765 Counter += 2;
02766 }
02767
02768 if (Success)
02769 {
02770 Success = InsertShapeEdge(RenderPath, &EdgePath2, pArray[Counter+1]);
02771 Counter ++;
02772 }
02773 }
02774
02775
02776 if (IsPrimaryCurvature() && Success)
02777 {
02778 DocCoord CP1;
02779 DocCoord CP2;
02780 CP1 = DocCoord::PositionPointFromRatio(pArray[Counter], pArray[Counter+1], CurveFactor);
02781 CP2 = DocCoord::PositionPointFromRatio(pArray[Counter+2], pArray[Counter+1], CurveFactor);
02782 Success = RenderPath->AddCurveTo(CP1, CP2, pArray[Counter+2]);
02783 Counter ++;
02784 }
02785 }
02786
02787 if (!Success)
02788 {
02789 return FALSE;
02790 }
02791
02792
02793 RenderPath->CloseSubPath();
02794 RenderPath->IsFilled = TRUE;
02795
02796
02797 if (IsPrimaryCurvature() || IsStellationCurvature())
02798 {
02799 const UINT32 SizePath1 = EdgePath1.GetNumCoords()-1;
02800 const UINT32 SizePath2 = EdgePath2.GetNumCoords()-1;
02801 DocCoord* PathCoords = RenderPath->GetCoordArray();
02802 INT32 Current = 0;
02803
02804 for (CurrentSide = 0; CurrentSide < NumSides; CurrentSide++)
02805 {
02806
02807 Current += SizePath1;
02808
02809 if (IsStellated())
02810 {
02811
02812 if (IsStellationCurvature())
02813 {
02814 SmoothCurvatureJoin(RenderPath, PathCoords, Current, FALSE);
02815 Current += 3;
02816 SmoothCurvatureJoin(RenderPath, PathCoords, Current, TRUE);
02817 }
02818 Current += SizePath2;
02819 }
02820
02821
02822 if (IsPrimaryCurvature())
02823 {
02824 SmoothCurvatureJoin(RenderPath, PathCoords, Current, FALSE);
02825 Current += 3;
02826 SmoothCurvatureJoin(RenderPath, PathCoords, Current, TRUE);
02827 }
02828 }
02829 }
02830
02831 return TRUE;
02832 }
02833
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855 BOOL NodeRegularShape::SmoothCurvatureJoin(Path* RenderPath, DocCoord* Coords, INT32 Index, BOOL MoveLeft)
02856 {
02857
02858 if ((RenderPath->GetVerbArray()[Index] & ~PT_CLOSEFIGURE) == PT_LINETO)
02859 return TRUE;
02860
02861 ERROR3IF(Index == 0, "Index was 0. Must be one or greater");
02862 const INT32 Oppo = RenderPath->FindOppositeControlPoint(Index-1);
02863 if (Oppo == -1)
02864 return TRUE;
02865
02866 DocCoord CPLeft = Coords[Index-1];
02867 DocCoord Centre = Coords[Index];
02868 DocCoord CPRight = Coords[Oppo];
02869 DocCoord MoveCP;
02870
02871 double LeftDist = Centre.Distance(CPLeft);
02872 double RightDist = Centre.Distance(CPRight);
02873
02874 if ((LeftDist == 0.0) || (RightDist == 0.0))
02875 return TRUE;
02876
02877 if (MoveLeft)
02878 {
02879 MoveCP = DocCoord::PositionPointFromRatio(Centre, CPRight, LeftDist/RightDist);
02880 Coords[Index-1] = Centre - (MoveCP - Centre);
02881 }
02882 else
02883 {
02884 MoveCP = DocCoord::PositionPointFromRatio(Centre, CPLeft, RightDist/LeftDist);
02885 Coords[Oppo] = Centre - (MoveCP - Centre);
02886 }
02887 return TRUE;
02888 }
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907 BOOL NodeRegularShape::ToggleCurvature()
02908 {
02909 #ifndef STANDALONE
02910
02911 EditRegularShapeParam ChangeData(this);
02912 if (IsPrimaryCurvature() || IsStellationCurvature())
02913 {
02914 ChangeData.NewPrimaryCurvature = EditRegularShapeParam::CHANGE_SETFALSE;
02915 ChangeData.NewStellationCurvature = EditRegularShapeParam::CHANGE_SETFALSE;
02916 }
02917 else
02918 {
02919 ChangeData.NewPrimaryCurvature = EditRegularShapeParam::CHANGE_SETTRUE;
02920 ChangeData.NewStellationCurvature = EditRegularShapeParam::CHANGE_SETTRUE;
02921 }
02922 OpDescriptor* Apple = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpEditRegularShape));
02923 if (Apple != NULL)
02924 {
02925 Apple->Invoke(&ChangeData);
02926 return TRUE;
02927 }
02928 else
02929 return FALSE;
02930 #else
02931 return FALSE;
02932 #endif
02933 }
02934
02935
02936 #ifndef STANDALONE
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952
02953
02954
02955
02956
02957
02958
02959 BOOL NodeRegularShape::ClickEllipse(DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods,
02960 Spread* pSpread, BOOL DragCentre)
02961 {
02962 if (IsCircular())
02963 {
02964 switch (Click)
02965 {
02966 case CLICKTYPE_DOUBLE:
02967 {
02968
02969 if (!MakeRegular(PointerPos))
02970 InformError();
02971 return TRUE;
02972 break;
02973 }
02974 case CLICKTYPE_DRAG:
02975 {
02976
02977 OpDragRegularShape* pOp = new (OpDragRegularShape);
02978 if (pOp != NULL)
02979 {
02980 pOp->DoStartDragEdit( this, PointerPos, pSpread, OpDragRegularShape::DRAG_ELLIPSE, DragCentre);
02981 }
02982 return TRUE;
02983 break;
02984 }
02985 default:
02986 return FALSE;
02987 }
02988 }
02989 else
02990 return FALSE;
02991 }
02992
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016 BOOL NodeRegularShape::ClickCentre(DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods, Spread* pSpread)
03017 {
03018 switch (Click)
03019 {
03020 case CLICKTYPE_DOUBLE:
03021 {
03022
03023 EditRegularShapeParam ChangeData(this);
03024 if (IsCircular())
03025 ChangeData.NewCircular = EditRegularShapeParam::CHANGE_SETFALSE;
03026 else
03027 ChangeData.NewCircular = EditRegularShapeParam::CHANGE_SETTRUE;
03028 OpDescriptor* Apple = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpEditRegularShape));
03029 if (Apple != NULL)
03030 Apple->Invoke(&ChangeData);
03031 return TRUE;
03032 break;
03033 }
03034 case CLICKTYPE_DRAG:
03035 {
03036
03037 OpDragRegularShape* pOp = new (OpDragRegularShape);
03038 if (pOp != NULL)
03039 {
03040 pOp->DoStartDragEdit( this, PointerPos, pSpread, OpDragRegularShape::DRAG_CENTRE, TRUE);
03041 }
03042 return TRUE;
03043 break;
03044 }
03045 default:
03046 return FALSE;
03047 }
03048 return FALSE;
03049 }
03050
03051
03052
03053
03054
03055
03056
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069
03070
03071
03072
03073
03074 BOOL NodeRegularShape::ClickPrimary(DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods, Spread* pSpread, BOOL DragCentre)
03075 {
03076 switch (Click)
03077 {
03078 case CLICKTYPE_DOUBLE:
03079 {
03080
03081 BOOL Result = ToggleCurvature();
03082 ERROR2IF(!Result, FALSE, "Toggle curvature failed - OpEditRegularShape is ill");
03083 return TRUE;
03084 break;
03085 }
03086 case CLICKTYPE_DRAG:
03087 {
03088 OpDragRegularShape* pOp = new (OpDragRegularShape);
03089 if (pOp != NULL)
03090 {
03091 pOp->DoStartDragEdit( this, PointerPos, pSpread, OpDragRegularShape::DRAG_PRIMARY, DragCentre);
03092 }
03093 return TRUE;
03094 break;
03095 }
03096 default:
03097 return FALSE;
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 BOOL NodeRegularShape::ClickStellation(DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods, Spread* pSpread)
03125 {
03126 switch (Click)
03127 {
03128 case CLICKTYPE_DOUBLE:
03129 {
03130
03131 BOOL Result = ToggleCurvature();
03132 ERROR2IF(!Result, FALSE, "Toggle curvature failed - OpEditRegularShape is ill");
03133 return TRUE;
03134 break;
03135 }
03136 case CLICKTYPE_DRAG:
03137 {
03138 OpDragRegularShape* pOp = new (OpDragRegularShape);
03139 if (pOp != NULL)
03140 {
03141 pOp->DoStartDragEdit( this, PointerPos, pSpread, OpDragRegularShape::DRAG_STELLATION, TRUE);
03142 }
03143 return TRUE;
03144 break;
03145 }
03146 default:
03147 return FALSE;
03148 }
03149 }
03150
03151
03152
03153
03154
03155
03156
03157
03158
03159
03160
03161
03162
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172
03173
03174
03175
03176 BOOL NodeRegularShape::ClickPCurve(DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods, Spread* pSpread, DocCoord Start, DocCoord End)
03177 {
03178 switch (Click)
03179 {
03180 case CLICKTYPE_DOUBLE:
03181 {
03182 BOOL Result = ToggleCurvature();
03183 ERROR2IF(!Result, FALSE, "Toggle curvature failed - OpEditRegularShape is ill");
03184 return TRUE;
03185 break;
03186 }
03187 case CLICKTYPE_DRAG:
03188 {
03189
03190 OpDragRegularShape* pOp = new (OpDragRegularShape);
03191 if (pOp != NULL)
03192 {
03193 pOp->DoStartDragEditCurve( this, PointerPos, pSpread,
03194 OpDragRegularShape::DRAG_PRIMARYCURVE, Start, End);
03195 }
03196 return TRUE;
03197 break;
03198 }
03199 default:
03200 return FALSE;
03201 }
03202 }
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220
03221
03222
03223
03224
03225
03226
03227
03228
03229 BOOL NodeRegularShape::ClickSCurve(DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods, Spread* pSpread, DocCoord Start, DocCoord End)
03230 {
03231 switch (Click)
03232 {
03233 case CLICKTYPE_DOUBLE:
03234 {
03235 BOOL Result = ToggleCurvature();
03236 ERROR2IF(!Result, FALSE, "Toggle curvature failed - OpEditRegularShape is ill");
03237 return TRUE;
03238 break;
03239 }
03240 case CLICKTYPE_DRAG:
03241 {
03242
03243 OpDragRegularShape* pOp = new (OpDragRegularShape);
03244 if (pOp != NULL)
03245 {
03246 pOp->DoStartDragEditCurve( this, PointerPos, pSpread,
03247 OpDragRegularShape::DRAG_STELLATIONCURVE, Start, End);
03248 }
03249 return TRUE;
03250 break;
03251 }
03252 default:
03253 return FALSE;
03254 }
03255 }
03256
03257
03258
03259
03260
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281
03282 BOOL NodeRegularShape::ClickEdge(DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods, Spread* pSpread, BOOL EdgeOne)
03283 {
03284 switch (Click)
03285 {
03286 case CLICKTYPE_DOUBLE:
03287 {
03288 if (ClickMods.Constrain)
03289 {
03290 if (!MakeStraight(EdgeOne))
03291 InformError();
03292 }
03293 else
03294 {
03295
03296 EditRegularShapeParam ChangeData(this);
03297 if (IsStellated())
03298 ChangeData.NewStellated = EditRegularShapeParam::CHANGE_SETFALSE;
03299 else
03300 ChangeData.NewStellated = EditRegularShapeParam::CHANGE_SETTRUE;
03301 OpDescriptor* Apple = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpEditRegularShape));
03302 if (Apple != NULL)
03303 Apple->Invoke(&ChangeData);
03304 }
03305 return TRUE;
03306 break;
03307 }
03308 case CLICKTYPE_DRAG:
03309 {
03310
03311 if (!IsCircular())
03312 {
03313 double pdist;
03314 INT32 tempel;
03315 Path* RenderPath = NULL;
03316 BuildShapePath(&RenderPath);
03317 RenderPath->SqrDistanceToPoint(PointerPos, &tempel, &pdist);
03318
03319 OpReformShapeEdge* pOpReshape = new OpReformShapeEdge;
03320 if (pOpReshape == NULL)
03321 InformError( _R(IDS_OUT_OF_MEMORY), _R(IDS_OK) );
03322 else
03323 {
03324 pOpReshape->DoStartDragEdit(this, EdgeOne, PointerPos, pSpread, tempel);
03325 }
03326 }
03327 return TRUE;
03328 break;
03329 }
03330 default:
03331 return FALSE;
03332 }
03333 }
03334
03335 #endif
03336
03337
03338
03339
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351 BOOL NodeRegularShape::IsReformed()
03352 {
03353 INT32 loop;
03354 DocCoord* Coords1 = EdgePath1.GetCoordArray();
03355 INT32 NumCoords1 = EdgePath1.GetNumCoords()-1;
03356 DocCoord* Coords2 = EdgePath2.GetCoordArray();
03357 INT32 NumCoords2 = EdgePath2.GetNumCoords()-1;
03358
03359
03360 if ((NumCoords1 == 2) && (NumCoords2 ==2))
03361 return FALSE;
03362
03363 for (loop = 1; loop < NumCoords1 ; loop++)
03364 {
03365 if (DocCoord::DistanceFromLine(Coords1[0], Coords1[NumCoords1], Coords1[loop]) > 1.0)
03366 return TRUE;
03367 }
03368
03369 for (loop = 1; loop < NumCoords2 ; loop++)
03370 {
03371 if (DocCoord::DistanceFromLine(Coords2[0], Coords2[NumCoords2], Coords2[loop]) > 1.0)
03372 return TRUE;
03373 }
03374
03375 return FALSE;
03376 }
03377
03378
03379
03380
03381
03382
03383
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396 double NodeRegularShape::GetRotationAngle()
03397 {
03398 DocCoord Offset = GetMajorAxes() - GetCentrePoint();
03399 double Angle = atan2((double)Offset.y, (double)Offset.x);
03400 if (Angle == HUGE_VAL)
03401 Angle = 0.0;
03402
03403 return Angle;
03404 }
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423 UINT32 NodeRegularShape::GetNumSides() const
03424 {
03425 return NumSides;
03426 }
03427
03428
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444 void NodeRegularShape::SetNumSides(UINT32 NewNumSides)
03445 {
03446 if (NewNumSides >= REGULARSHAPE_MINSIDES)
03447 { NumSides = NewNumSides;
03448 InvalidateCache();
03449 }
03450 else
03451 {
03452 ERROR3_PF(("Attempted to set %d number of sides",NewNumSides));
03453 }
03454 }
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468
03469
03470
03471
03472 BOOL NodeRegularShape::IsCircular() const
03473 {
03474
03475 return (Circular != 0);
03476 }
03477
03478
03479
03480
03481
03482
03483
03484
03485
03486
03487
03488
03489
03490
03491
03492
03493
03494 void NodeRegularShape::SetCircular(BOOL Value)
03495 {
03496 Circular = Value;
03497 InvalidateCache();
03498 }
03499
03500
03501
03502
03503
03504
03505
03506
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516 BOOL NodeRegularShape::IsStellated() const
03517 {
03518
03519 return (Stellated != 0);
03520 }
03521
03522
03523
03524
03525
03526
03527
03528
03529
03530
03531
03532
03533
03534
03535
03536
03537
03538 void NodeRegularShape::SetStellated(BOOL Value)
03539 {
03540 Stellated = Value;
03541 InvalidateCache();
03542 }
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552
03553
03554
03555
03556
03557
03558
03559
03560 BOOL NodeRegularShape::IsPrimaryCurvature() const
03561 {
03562
03563 return (PrimaryCurvature != 0);
03564 }
03565
03566
03567
03568
03569
03570
03571
03572
03573
03574
03575
03576
03577
03578
03579
03580
03581
03582 void NodeRegularShape::SetPrimaryCurvature(BOOL Value)
03583 {
03584 PrimaryCurvature = Value;
03585 InvalidateCache();
03586 }
03587
03588
03589
03590
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601
03602
03603
03604 BOOL NodeRegularShape::IsStellationCurvature() const
03605 {
03606
03607 return (StellationCurvature != 0);
03608 }
03609
03610
03611
03612
03613
03614
03615
03616
03617
03618
03619
03620
03621
03622
03623
03624
03625
03626 void NodeRegularShape::SetStellationCurvature(BOOL Value)
03627 {
03628 StellationCurvature = Value;
03629 InvalidateCache();
03630 }
03631
03632
03633
03634
03635
03636
03637
03638
03639
03640
03641
03642
03643
03644
03645
03646
03647
03648 double NodeRegularShape::GetStellRadiusToPrimary() const
03649 {
03650 return StellRadiusToPrimary;
03651 }
03652
03653
03654
03655
03656
03657
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668
03669 void NodeRegularShape::SetStellRadiusToPrimary(double Value)
03670 {
03671 StellRadiusToPrimary = Value;
03672 InvalidateCache();
03673 }
03674
03675
03676
03677
03678
03679
03680
03681
03682
03683
03684
03685
03686
03687
03688
03689
03690
03691
03692 double NodeRegularShape::GetPrimaryCurveToPrimary() const
03693 {
03694 return PrimaryCurveToPrimary;
03695 }
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710
03711
03712
03713 void NodeRegularShape::SetPrimaryCurveToPrimary(double Value)
03714 {
03715 PrimaryCurveToPrimary = Value;
03716 InvalidateCache();
03717 }
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731
03732
03733
03734
03735
03736 double NodeRegularShape::GetStellCurveToStell() const
03737 {
03738 return StellCurveToStell;
03739 }
03740
03741
03742
03743
03744
03745
03746
03747
03748
03749
03750
03751
03752
03753
03754
03755
03756
03757 void NodeRegularShape::SetStellCurveToStell(double Value)
03758 {
03759 StellCurveToStell = Value;
03760 InvalidateCache();
03761 }
03762
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772
03773
03774
03775
03776
03777
03778
03779 double NodeRegularShape::GetStellationRatio() const
03780 {
03781 return StellOffsetRatio;
03782 }
03783
03784
03785
03786
03787
03788
03789
03790
03791
03792
03793
03794
03795
03796
03797
03798
03799
03800 void NodeRegularShape::SetStellationRatio(double Value)
03801 {
03802 StellOffsetRatio = Value;
03803 InvalidateCache();
03804 }
03805
03806
03807
03808
03809
03810
03811
03812
03813
03814
03815
03816
03817
03818
03819
03820
03821
03822 DocCoord NodeRegularShape::GetCentrePoint()
03823 {
03824 DocCoord Result = UTCentrePoint;
03825 TransformMatrix.transform(&Result);
03826 return Result;
03827 }
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845 DocCoord NodeRegularShape::GetMajorAxes()
03846 {
03847 DocCoord Result = UTMajorAxes;
03848 TransformMatrix.transform(&Result);
03849 return Result;
03850 }
03851
03852
03853
03854
03855
03856
03857
03858
03859
03860
03861
03862
03863
03864
03865
03866
03867 DocCoord NodeRegularShape::GetMinorAxes()
03868 {
03869 DocCoord Result = UTMinorAxes;
03870 TransformMatrix.transform(&Result);
03871 return Result;
03872 }
03873
03874
03875
03876
03877
03878
03879
03880
03881
03882
03883
03884
03885
03886
03887
03888
03889
03890
03891 void NodeRegularShape::SetCentrePoint(DocCoord Value)
03892 {
03893 UTCentrePoint = Value;
03894 InvalidateCache();
03895 }
03896
03897
03898
03899
03900
03901
03902
03903
03904
03905
03906
03907
03908
03909
03910
03911
03912
03913
03914 void NodeRegularShape::SetMinorAxes(DocCoord Value)
03915 {
03916 UTMinorAxes = Value;
03917 InvalidateCache();
03918 }
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930
03931
03932
03933
03934
03935
03936
03937 void NodeRegularShape::SetMajorAxes(DocCoord Value)
03938 {
03939 UTMajorAxes = Value;
03940 InvalidateCache();
03941 }
03942
03943
03944
03945
03946
03947
03948
03949
03950
03951
03952
03953
03954
03955
03956
03957
03958
03959 void NodeRegularShape::GetTransformMatrix(Matrix* store) const
03960 {
03961 *store = TransformMatrix;
03962 }
03963
03964
03965
03966
03967
03968
03969
03970
03971
03972
03973
03974
03975
03976
03977
03978
03979
03980 void NodeRegularShape::SetTransformMatrix(const Matrix* newmatrix)
03981 {
03982 TransformMatrix = *newmatrix;
03983 }
03984
03985
03986
03987
03988
03989
03990
03991
03992
03993
03994
03995
03996
03997
03998
03999
04000
04001
04002 void NodeRegularShape::PreExportRender(RenderRegion* pRegion)
04003 {
04004 #ifdef DO_EXPORT
04005 if (pRegion->IsKindOf(CC_RUNTIME_CLASS(NativeRenderRegion)))
04006 {
04007
04008 EPSExportDC *pDC = (EPSExportDC *) pRegion->GetRenderDC();
04009 pDC->OutputToken(_T("csrs"));
04010 pDC->OutputNewLine();
04011 }
04012 #endif
04013 }
04014
04015
04016
04017
04018
04019
04020
04021
04022
04023
04024
04025
04026
04027
04028
04029
04030
04031 BOOL NodeRegularShape::ExportRender(RenderRegion* pRegion)
04032 {
04033 #ifdef DO_EXPORT
04034 if (pRegion->IsKindOf(CC_RUNTIME_CLASS(NativeRenderRegion)))
04035 {
04036 EPSExportDC *pDC = (EPSExportDC *) pRegion->GetRenderDC();
04037
04038
04039 INT32 IsFilled = TRUE;
04040 StrokeColourAttribute *pStrokeColour =
04041 (StrokeColourAttribute *) pRegion->GetCurrentAttribute(ATTR_STROKECOLOUR);
04042 INT32 IsStroked = !pStrokeColour->Colour.IsTransparent();
04043
04044 ColourFillAttribute *pFillAttr =
04045 (ColourFillAttribute *) pRegion->GetCurrentAttribute(ATTR_FILLGEOMETRY);
04046
04047 if (pFillAttr->IsKindOf(CC_RUNTIME_CLASS(FlatFillAttribute)) &&
04048 pFillAttr->Colour.IsTransparent())
04049 {
04050
04051 IsFilled = FALSE;
04052 }
04053
04054
04055 pDC->OutputValue((INT32)NumSides);
04056 pDC->OutputValue((INT32)Circular);
04057 pDC->OutputValue((INT32)Stellated);
04058 pDC->OutputValue((INT32)PrimaryCurvature);
04059 pDC->OutputValue((INT32)StellationCurvature);
04060 pDC->OutputReal(StellRadiusToPrimary);
04061 pDC->OutputReal(PrimaryCurveToPrimary);
04062 pDC->OutputReal(StellCurveToStell);
04063 pDC->OutputReal(StellOffsetRatio);
04064 pDC->OutputCoord(UTCentrePoint);
04065 pDC->OutputCoord(UTMajorAxes);
04066 pDC->OutputCoord(UTMinorAxes);
04067 pDC->OutputValue(IsFilled);
04068 pDC->OutputValue(IsStroked);
04069 pDC->OutputToken(_T("crsp"));
04070 pDC->OutputNewLine();
04071
04072
04073 fixed16 billy[4];
04074 INT32 bobby[2];
04075 TransformMatrix.GetComponents(billy, bobby);
04076 pDC->OutputReal(billy[0].MakeDouble());
04077 pDC->OutputReal(billy[1].MakeDouble());
04078 pDC->OutputReal(billy[2].MakeDouble());
04079 pDC->OutputReal(billy[3].MakeDouble());
04080 pDC->OutputUserSpaceValue(bobby[0]);
04081 pDC->OutputUserSpaceValue(bobby[1]);
04082 pDC->OutputToken(_T("crstm"));
04083 pDC->OutputNewLine();
04084
04085
04086 ((EPSRenderRegion*)pRegion)->ExportPath(&EdgePath1, TRUE);
04087 pDC->OutputToken(_T("crsp1"));
04088 pDC->OutputNewLine();
04089 ((EPSRenderRegion*)pRegion)->ExportPath(&EdgePath2, TRUE);
04090 pDC->OutputToken(_T("crsp2"));
04091 pDC->OutputNewLine();
04092
04093
04094 pDC->OutputToken(_T("cers"));
04095 pDC->OutputNewLine();
04096
04097
04098 return TRUE;
04099 }
04100
04101
04102
04103 else if ( pRegion->IsKindOf ( CC_RUNTIME_CLASS ( FlashRenderRegion ) ) )
04104 {
04105
04106 return static_cast<FlashRenderRegion*> ( pRegion )->ExportRenderableNode ( this );
04107 }
04108
04109 #endif
04110
04111 return FALSE;
04112 }
04113
04114
04115
04116
04117
04118
04119
04120
04121
04122
04123
04124
04125
04126
04127
04128
04129
04130
04131 void NodeRegularShape::EmergencyFixShape()
04132 {
04133 DocCoord CurrentCentre = GetCentrePoint();
04134 DocCoord CurrentMajor = GetMajorAxes();
04135 DocCoord CurrentMinor = GetMinorAxes();
04136
04137 if ( (CurrentCentre.Distance(CurrentMajor) == 0.0) ||
04138 (CurrentCentre.Distance(CurrentMinor) == 0.0) )
04139 {
04140 SetCentrePoint(CurrentCentre);
04141 SetMajorAxes(DocCoord(CurrentCentre.x+100, CurrentCentre.y));
04142 SetMinorAxes(DocCoord(CurrentCentre.x, CurrentCentre.y+100));
04143
04144 Matrix fred( FIXED16(1), FIXED16(0), FIXED16(0), FIXED16(1), 0, 0 );
04145 SetTransformMatrix(&fred);
04146 }
04147 }
04148
04149
04150
04151
04152
04153
04154
04155
04156
04157
04158
04159
04160
04161
04162
04163
04164
04165
04166 BOOL NodeRegularShape::IsARectangle() const
04167 {
04168 return (!IsCircular() && (GetNumSides() == 4) && !IsStellated());
04169 }
04170
04171
04172
04173
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183
04184 INT32 NodeRegularShape::GetRectWidth()
04185 {
04186 if(!IsARectangle())
04187 return -1;
04188
04189 double minorRadius = GetCentrePoint().Distance(GetMinorAxes());
04190 return (INT32)(minorRadius * cos(PI/4));
04191 }
04192
04193
04194
04195
04196
04197
04198
04199
04200
04201
04202
04203
04204
04205 INT32 NodeRegularShape::GetRectHeight()
04206 {
04207 if(!IsARectangle())
04208 return -1;
04209
04210 double MajorRadius = GetCentrePoint().Distance(GetMajorAxes());
04211 return (INT32)(MajorRadius * cos(PI/4));
04212 }
04213
04214
04215
04216
04217
04218
04219
04220
04221
04222
04223
04224
04225
04226
04227
04228
04229 BOOL NodeRegularShape::OnNodePopUp(Spread* pSpread, DocCoord PointerPos, ContextMenu* pMenu)
04230 {
04231 #if !defined(EXCLUDE_FROM_RALPH)
04232 BOOL ok = TRUE;
04233
04234 ok = ok && pMenu->BuildCommand(TOOL_OPTOKEN_REGSHAPE, TRUE);
04235
04236 ok = ok && pMenu->BuildCommand(OPTOKEN_TOGGLEELIPPOLY, TRUE);
04237 ok = ok && pMenu->BuildCommand(OPTOKEN_TOGGLESTELLATION);
04238 ok = ok && pMenu->BuildCommand(OPTOKEN_TOGGLECURVATURE, TRUE);
04239
04240 ok = ok && pMenu->BuildCommand(OPTOKEN_QUICKSHAPE_NUMBERSIDES,TRUE);
04241 MenuItem* pNumberRoot = pMenu->GetLastItem();
04242 ok = ok && pMenu->BuildCommand(OPTOKEN_QUICKSHAPE_NUMBERSIDES3, FALSE, pNumberRoot);
04243 ok = ok && pMenu->BuildCommand(OPTOKEN_QUICKSHAPE_NUMBERSIDES4, FALSE, pNumberRoot);
04244 ok = ok && pMenu->BuildCommand(OPTOKEN_QUICKSHAPE_NUMBERSIDES5, FALSE, pNumberRoot);
04245 ok = ok && pMenu->BuildCommand(OPTOKEN_QUICKSHAPE_NUMBERSIDES6, FALSE, pNumberRoot);
04246 ok = ok && pMenu->BuildCommand(OPTOKEN_QUICKSHAPE_NUMBERSIDES7, FALSE, pNumberRoot);
04247 ok = ok && pMenu->BuildCommand(OPTOKEN_QUICKSHAPE_NUMBERSIDES8, FALSE, pNumberRoot);
04248 ok = ok && pMenu->BuildCommand(OPTOKEN_QUICKSHAPE_NUMBERSIDES9, FALSE, pNumberRoot);
04249 ok = ok && pMenu->BuildCommand(OPTOKEN_QUICKSHAPE_NUMBERSIDES10, FALSE, pNumberRoot);
04250
04251 return ok;
04252 #else
04253 return FALSE;
04254 #endif
04255 }
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269
04270
04271 BOOL NodeRegularShape::IsARegularShape() const
04272 {
04273 return TRUE;
04274 }
04275
04276
04277
04278
04279
04280
04281
04282
04283
04284
04285
04286
04287
04288
04289
04290
04291 double NodeRegularShape::GetMajorRadiusSize()
04292 {
04293 DocCoord OuterMajor = UTMajorAxes;
04294 if (IsStellated() && (GetStellRadiusToPrimary() > 1.0))
04295 PositionPointFromRatio(&OuterMajor, &UTMajorAxes, GetStellRadiusToPrimary());
04296
04297 return UTCentrePoint.Distance(OuterMajor);
04298 }
04299
04300
04301
04302
04303
04304
04305
04306
04307
04308
04309
04310
04311
04312
04313
04314
04315
04316
04317
04318 BOOL NodeRegularShape::MakeRectangle(const INT32 Width, const INT32 Height, const INT32 CurvatureRadius)
04319 {
04320 ERROR3IF(CurvatureRadius < 0, "CurvatureRadius was -ve");
04321
04322
04323 SetNumSides(4);
04324 SetCircular(FALSE);
04325 SetStellated(FALSE);
04326
04327
04328 const double SqrHalfHeight = ((double)Height/2)*((double)Height/2);
04329 const INT32 MajorLength = (INT32)(sqrt( SqrHalfHeight + SqrHalfHeight ));
04330
04331 SetCentrePoint(DocCoord(0,0));
04332 SetMajorAxes(DocCoord(0, MajorLength));
04333 SetMinorAxes(DocCoord(MajorLength, 0));
04334
04335
04336 if (CurvatureRadius < 1)
04337 {
04338 PrimaryCurvature = FALSE;
04339 StellationCurvature = FALSE;
04340 }
04341 else
04342 {
04343 PrimaryCurvature = TRUE;
04344 StellationCurvature = TRUE;
04345 PrimaryCurveToPrimary = ((double)CurvatureRadius) / ((double)MajorLength);
04346 StellCurveToStell = PrimaryCurveToPrimary;
04347 }
04348
04349
04350 Matrix Unity;
04351 SetTransformMatrix(&Unity);
04352
04353 DocCoord NewMinor = DocCoord::PositionPointFromRatio(UTCentrePoint, UTMinorAxes, (double)Width/Height);
04354 SetMinorAxes(NewMinor);
04355
04356 EmergencyFixShape();
04357
04358 return TRUE;
04359 }
04360
04361
04362
04363
04364
04365
04366
04367
04368
04369
04370
04371
04372
04373
04374
04375
04376 BOOL NodeRegularShape::MakeEllipse(const INT32 Width, const INT32 Height)
04377 {
04378
04379 SetNumSides(6);
04380 SetCircular(TRUE);
04381 SetStellated(FALSE);
04382
04383 SetCentrePoint(DocCoord(0,0));
04384 SetMajorAxes(DocCoord(0, Height));
04385 SetMinorAxes(DocCoord(Width, 0));
04386
04387
04388 Matrix Unity;
04389 SetTransformMatrix(&Unity);
04390
04391 EmergencyFixShape();
04392
04393 return TRUE;
04394 }
04395
04396
04397
04398
04399
04400
04401
04402
04403
04404
04405
04406
04407
04408
04409 BOOL NodeRegularShape::WritePreChildrenNative(BaseCamelotFilter * pFilter)
04410 {
04411 #ifdef DO_EXPORT
04412 ERROR2IF(this == NULL, FALSE, "this == NULL");
04413 ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
04414 TRACEUSER( "Diccon", _T("Exporting Regular Shape\n"));
04415 String_256 Details = String_256((TCHAR*)(this->GetRuntimeClass()->m_lpszClassName));
04416 TRACEUSER( "Diccon", _T("(%s - 0x%x)\n"),(TCHAR*)Details,this);
04417 return CXaraFileRegularShape::WritePreChildrenNative(pFilter, this);
04418 #else
04419 return FALSE;
04420 #endif
04421 }
04422
04423 BOOL NodeRegularShape::WritePreChildrenWeb(BaseCamelotFilter * pFilter)
04424 {
04425 #ifdef DO_EXPORT
04426 ERROR2IF(this == NULL, FALSE, "this == NULL");
04427 ERROR2IF(pFilter == NULL, FALSE, "pFilter == NULL");
04428
04429 return CXaraFileRegularShape::WritePreChildrenWeb(pFilter, this);
04430 #else
04431 return FALSE;
04432 #endif
04433 }
04434
04435
04436
04437
04438
04439
04440
04441
04442
04443
04444
04445
04446 void NodeRegularShape::DeleteCachedPath()
04447 {
04448 if (CachedRenderPath != NULL)
04449 {
04450 delete CachedRenderPath;
04451 CachedRenderPath = NULL;
04452 }
04453
04454
04455 AttrBrushType* pBrush = NULL;
04456 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBrushType), (NodeAttribute**)&pBrush);
04457 if (pBrush && pBrush->GetBrushHandle() != BrushHandle_NoBrush)
04458 pBrush->FlushCache();
04459
04460
04461 PathCacheInvalid = TRUE;
04462 }
04463
04464
04465
04466
04467
04468
04469
04470
04471
04472
04473
04474
04475
04476
04477
04478
04479
04480
04481
04482
04483 PathShape NodeRegularShape::GetPathShape()
04484 {
04485
04486 if (IsARectangle() && !IsReformed())
04487 {
04488
04489
04490
04491 if (AxesAreEqual() && AxesArePerpendicular())
04492 {
04493
04494
04495
04496 if (IsRotated())
04497 return PATHSHAPE_SQUARE_ROTATED;
04498 else
04499 return PATHSHAPE_SQUARE;
04500 }
04501 else
04502 {
04503
04504
04505
04506 if (IsRotated())
04507 return PATHSHAPE_RECTANGLE_ROTATED;
04508 else
04509 return PATHSHAPE_RECTANGLE;
04510 }
04511 }
04512
04513
04514 if (IsCircular())
04515 {
04516
04517
04518
04519 if (AxesAreEqual() && AxesArePerpendicular())
04520 {
04521
04522
04523 return PATHSHAPE_CIRCLE;
04524 }
04525 else
04526 {
04527
04528
04529
04530 if (IsRotated())
04531 return PATHSHAPE_ELLIPSE_ROTATED;
04532 else
04533 return PATHSHAPE_ELLIPSE;
04534 }
04535 }
04536
04537
04538
04539
04540 return PATHSHAPE_PATH;
04541 }
04542
04543
04544
04545
04546
04547
04548
04549
04550
04551
04552
04553
04554
04555
04556
04557
04558
04559
04560
04561
04562
04563
04564
04565
04566
04567
04568
04569
04570
04571
04572
04573
04574
04575
04576
04577
04578
04579
04580
04581 BOOL NodeRegularShape::IsRotated()
04582 {
04583
04584 double dAngle=fabs(GetRotationAngle());
04585
04586
04587
04588 double dAllowedAngle=(double) ((2*PI)/GetNumSides());
04589
04590
04591
04592 for (double dCheckAngle=0; dCheckAngle<PI; dCheckAngle+=dAllowedAngle)
04593 {
04594
04595
04596 double dDifference=fabs(dAngle-dCheckAngle);
04597
04598 if (dDifference<QUICKSHAPE_ANGLE_TOLERANCE)
04599 return FALSE;
04600 }
04601
04602
04603 return TRUE;
04604
04605 }
04606
04607
04608
04609
04610
04611
04612
04613
04614
04615
04616
04617
04618
04619
04620 BOOL NodeRegularShape::AxesAreEqual()
04621 {
04622
04623 DocCoord dcCentre=GetCentrePoint();
04624 DocCoord dcMajor=GetMajorAxes();
04625 DocCoord dcMinor=GetMinorAxes();
04626
04627
04628 double dMajorLength=dcCentre.Distance(dcMajor);
04629 double dMinorLength=dcCentre.Distance(dcMinor);
04630
04631
04632
04633 double dDifference=fabs(dMajorLength-dMinorLength);
04634
04635 return (dDifference<QUICKSHAPE_RADIUS_TOLERANCE);
04636
04637 }
04638
04639
04640
04641
04642
04643
04644
04645
04646
04647
04648
04649
04650
04651
04652 BOOL NodeRegularShape::AxesArePerpendicular()
04653 {
04654
04655 DocCoord dcCentre=GetCentrePoint();
04656 DocCoord dcMajor=GetMajorAxes();
04657 DocCoord dcMinor=GetMinorAxes();
04658
04659
04660
04661
04662 INT32 lMajorVectorX=dcMajor.x-dcCentre.x;
04663 INT32 lMajorVectorY=dcMajor.y-dcCentre.y;
04664
04665
04666 INT32 lMinorVectorX=dcMinor.x-dcCentre.x;
04667 INT32 lMinorVectorY=dcMinor.y-dcCentre.y;
04668
04669
04670 INT32 lScalarProduct=lMajorVectorX*lMinorVectorX+lMajorVectorY*lMinorVectorY;
04671
04672
04673 INT32 lDifference=labs(lScalarProduct);
04674
04675 return (lDifference<QUICKSHAPE_SCALARPRODUCT_TOLERANCE);
04676 }
04677
04678
04679
04680
04681
04682
04683
04684
04685
04686
04687
04688
04689
04690
04691
04692
04693
04694
04695
04696 DocRect NodeRegularShape::ValidateExtend(const ExtendParams& ExtParams)
04697 {
04698 DocCoord doccArray[1] = { FindExtendCentre() };
04699 DocRect drMinExtend = Extender::ValidateControlPoints(1, doccArray, ExtParams);
04700
04701
04702
04703 if (drMinExtend.lo.x == INT32_MAX &&
04704 drMinExtend.lo.y == INT32_MAX &&
04705 drMinExtend.hi.x == INT32_MAX &&
04706 drMinExtend.hi.y == INT32_MAX)
04707 drMinExtend = Node::ValidateExtend(ExtParams);
04708
04709 return drMinExtend;
04710 }
04711
04712
04713
04714
04715
04716
04717
04718
04719
04720
04721
04722
04723
04724
04725
04726
04727
04728
04729
04730
04731
04732
04733 void NodeRegularShape::Extend(const ExtendParams& ExtParams)
04734 {
04735
04736 TransformStretchObject(ExtParams);
04737 TransformTranslateObject(ExtParams);
04738
04739
04740 Node::Extend(ExtParams);
04741 }
04742
04743
04744
04745
04746
04747
04748
04749
04750
04751
04752
04753
04754
04755
04756
04757
04758
04759
04760
04761
04762
04763
04764
04765 INT32 NodeRegularShape::EstimateNodeComplexity (OpParam* details)
04766 {
04767 if (CachedRenderPath)
04768 {
04769 return (CachedRenderPath->GetUsedSlots ());
04770 }
04771 else
04772 {
04773 return ((EdgePath1.GetUsedSlots ()) + (EdgePath2.GetUsedSlots ()));
04774 }
04775 }