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 #include "camtypes.h"
00100
00101
00102
00103
00104
00105
00106 #include "cxftags.h"
00107
00108 #include "nodecntr.h"
00109 #include "ncntrcnt.h"
00110
00111 #include "gdraw.h"
00112 #include "gclips.h"
00113
00114 #include "lineattr.h"
00115 #include "blobs.h"
00116 #include "objchge.h"
00117 #include "opbevel.h"
00118 #include "ophist.h"
00119 #include "nodeblnd.h"
00120 #include "ndbldpth.h"
00121 #include "csrstack.h"
00122 #include "ppbevel.h"
00123 #include "opcntr.h"
00124 #include "nodetxts.h"
00125 #include "moldtool.h"
00126 #include "extender.h"
00127
00128 #include "rsmooth.h"
00129 #include "fitcurve.h"
00130 #include "contmenu.h"
00131 #include "blndhelp.h"
00132 #include "brshattr.h"
00133 #include "pbecomea.h"
00134 #include "ppstroke.h"
00135 #include "attrmap.h"
00136
00137 #include "gclip.h"
00138
00139 #include "ngcore.h"
00140
00141 CC_IMPLEMENT_DYNCREATE(NodeContour, NodeRenderableInk)
00142
00143
00144 #define new CAM_DEBUG_NEW
00145
00146 #define NEWVERSION
00147
00148
00149
00150 const UINT32 ClipPathToPath_Tolerance = 30 ;
00151 const UINT32 ClipPathToPath_Flatness = 200 ;
00152 const UINT32 StrokePathToPath_Flatness = 200 ;
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 NodeContour::NodeContour()
00165 {
00166 m_pPathList = NULL;
00167 m_NumPaths = 0;
00168 m_SourcePath.Initialise();
00169
00170 IsBoundingRectValid = FALSE;
00171 m_FirstRender = TRUE;
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 NodeContour::NodeContour(Node* ContextNode,
00191 AttachNodeDirection Direction,
00192 BOOL Locked,
00193 BOOL Mangled,
00194 BOOL Marked,
00195 BOOL Selected
00196 )
00197 {
00198 m_pPathList = NULL;
00199 m_NumPaths = 0;
00200 m_SourcePath.Initialise();
00201 IsBoundingRectValid = FALSE;
00202 m_FirstRender = TRUE;
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 NodeContour::~NodeContour()
00216 {
00217 if (m_pPathList)
00218 {
00219 delete [] m_pPathList;
00220 m_pPathList = NULL;
00221 }
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 DocRect NodeContour::GetBoundingRect(BOOL DontUseAttrs, BOOL HitTest)
00235 {
00236
00237 if (!(!IsBoundingRectValid || DontUseAttrs))
00238 {
00239 return BoundingRectangle;
00240 }
00241
00242 DocRect dr;
00243
00244 NodeContourController * pController = (NodeContourController *)FindParent();
00245
00246 if (!pController)
00247 return DocRect(0,0,0,0);
00248
00249 INT32 Width = pController->GetWidth();
00250
00251 Node * pNode = FindParent();
00252
00253 if (!pNode)
00254 return BoundingRectangle;
00255
00256 pNode = pNode->FindFirstChild();
00257
00258 while (pNode)
00259 {
00260 if (pNode->IsAnObject() && pNode!=this)
00261 {
00262 if (!IsBoundingRectValid)
00263 {
00264 ((NodeRenderableInk *)pNode)->InvalidateBoundingRect();
00265 }
00266
00267 dr = dr.Union(((NodeRenderableInk *)pNode)->GetBoundingRect(TRUE, HitTest));
00268 }
00269
00270 pNode = pNode->FindNext();
00271 }
00272
00273 if (Width < 0)
00274 {
00275 dr.lo.x += Width;
00276 dr.lo.y += Width;
00277 dr.hi.x -= Width;
00278 dr.hi.y -= Width;
00279 }
00280
00281 DocRect PathRect;
00282
00283
00284 for (INT32 i = 0 ; i < m_NumPaths && m_pPathList; i++)
00285 {
00286 PathRect = m_pPathList[i].GetBoundingRect();
00287
00288 if (PathRect.IsValid() && !PathRect.IsEmpty())
00289 {
00290 dr = dr.Union(PathRect);
00291 }
00292 }
00293
00294
00295 if (Width < 0)
00296 {
00297 if (m_NumPaths != 0)
00298 {
00299 dr = (m_pPathList[m_NumPaths-1].GetBoundingRect());
00300 }
00301 }
00302 else
00303 {
00304 if (m_NumPaths != 0)
00305 {
00306 dr = (m_pPathList[0].GetBoundingRect());
00307 }
00308 }
00309
00310 if (!dr.IsValid() || dr.IsEmpty())
00311 {
00312 dr = ((NodeCompound *)FindParent())->GetInsideBoundingRect();
00313
00314
00315 DocCoord Centre = dr.Centre();
00316
00317 dr.lo.x = Centre.x - 5;
00318 dr.hi.x = Centre.x + 5;
00319 dr.lo.y = Centre.y - 5;
00320 dr.hi.y = Centre.y + 5;
00321 }
00322
00323
00324 AttrLineWidth * pAttr = NULL;
00325 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrLineWidth), (NodeAttribute **)(&pAttr));
00326
00327 AttrStrokeTransp * pStrokeAttr = NULL;
00328 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeTransp), (NodeAttribute **)(&pStrokeAttr));
00329
00330 AttrStrokeColour * pStrokeColour = NULL;
00331 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeColour), (NodeAttribute **)(&pStrokeColour));
00332
00333 BOOL bTransparent = FALSE;
00334
00335 if (pStrokeAttr)
00336 {
00337 if (pStrokeAttr->Value.Transp == 255)
00338 {
00339 bTransparent = TRUE;
00340 }
00341 }
00342
00343 if (pStrokeColour)
00344 {
00345 if (pStrokeColour->Value.Colour == DocColour(COLOUR_NONE))
00346 {
00347 bTransparent = TRUE;
00348 }
00349 }
00350
00351 if (pAttr && !bTransparent)
00352 {
00353 MILLIPOINT LineWidth = pAttr->Value.LineWidth / 2;
00354
00355 dr.lo.x -= LineWidth;
00356 dr.lo.y -= LineWidth;
00357 dr.hi.x += LineWidth;
00358 dr.hi.y += LineWidth;
00359 }
00360
00361 dr.Union(pController->GetInsideBoundingRect());
00362
00363 IsBoundingRectValid = TRUE;
00364 BoundingRectangle = dr;
00365
00366 return dr;
00367 }
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 DocRect NodeContour::GetBlobBoundingRect()
00380 {
00381 DocRect dr = GetBoundingRect(FALSE, FALSE);
00382
00383 BlobManager * pMgr = GetApplication()->GetBlobManager();
00384
00385 INT32 Size = 0;
00386
00387 if (pMgr)
00388 Size = pMgr->GetBlobSize();
00389
00390 dr.lo.x -= Size*2;
00391 dr.lo.y -= Size*2;
00392 dr.hi.x += Size*2;
00393 dr.hi.y += Size*2;
00394
00395 IncludeChildrensBoundingRects(&dr);
00396
00397 return dr;
00398 }
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410 void NodeContour::Render(RenderRegion* pRender)
00411 {
00412 double Ratio = 0;
00413 double StepSize = 0;
00414
00415 NodeContourController * pControl = (NodeContourController *)FindParent();
00416
00417
00418 if (pControl)
00419 {
00420 pControl->DisableInsetPathPathProcessor();
00421
00422 if (pControl->GetInsideBoundingRect().IsEmpty())
00423 return;
00424 }
00425 else
00426 return;
00427
00428 if(m_FirstRender)
00429 {
00430 GenerateContour();
00431 m_FirstRender = FALSE;
00432 }
00433
00434
00435 ContourNodePathProcessor * pProc = (ContourNodePathProcessor *)pRender->GetFirstPathProcessor();
00436
00437 if (pProc)
00438 {
00439 if (!((PathProcessor *)pProc)->IS_KIND_OF(ContourNodePathProcessor))
00440 pProc = NULL;
00441 }
00442
00443
00444 if (m_NumPaths == 0)
00445 return;
00446
00447 pRender->SaveContext();
00448
00449
00450 LineWidthAttribute * pLineWidth = (LineWidthAttribute *)pRender->GetCurrentAttribute(ATTR_LINEWIDTH);
00451
00452 TRACEUSER( "DaivdM", _T("Contour node render 1\n"));
00453
00454 MILLIPOINT LineWidth = 0;
00455
00456 if (pLineWidth)
00457 LineWidth = pLineWidth->LineWidth;
00458
00459 if (m_pPathList != NULL && m_NumPaths > 0)
00460 {
00461
00462 CCAttrMap BlendAttrMap(30);
00463
00464
00465 NodeRenderableInk * pEndNode = NULL;
00466
00467 if (pControl->GetWidth() > 0)
00468 pEndNode = (NodeRenderableInk *)FindPrevious(CC_RUNTIME_CLASS(NodeRenderableInk));
00469 else
00470 pEndNode = (NodeRenderableInk *)FindNext(CC_RUNTIME_CLASS(NodeRenderableInk));
00471
00472 if (!pEndNode)
00473 return;
00474
00475 if (pEndNode->IsCompound())
00476 pEndNode = FindNodeToContour(pEndNode);
00477
00478 if (pEndNode->IS_KIND_OF(NodeBlend))
00479 pEndNode = (NodeRenderableInk *)pEndNode->FindFirstChild(CC_RUNTIME_CLASS(NodeRenderableInk));
00480
00481
00482 CCAttrMap * pAttrMapStart = CCAttrMap::MakeAttrMapFromRenderRegion(pRender);
00483 WindingRuleAttribute * pWinding = NULL;
00484
00485 if(!pAttrMapStart)
00486 {
00487 ENSURE(FALSE,"Not enough mem to create start attr map for rendering NodeContour.");
00488 return;
00489 }
00490 CCAttrMap * pAttrMapEnd = CCAttrMap::MakeAppliedAttrMap(pEndNode);
00491
00492 StepSize = 1.0 / m_NumPaths;
00493
00494 for (INT32 i = m_NumPaths - 1; i >= 0; i--)
00495 {
00496 TRACEUSER( "Diccon", _T("Rendering contour path %d\n"), i);
00497 if (pControl->GetWidth() < 0)
00498 {
00499
00500 TRACEUSER( "DaivdM", _T("Contour node render %d\n"), i);
00501
00502 if (i == m_NumPaths - 1)
00503 {
00504 if (pProc)
00505 pProc->SetActive(FALSE);
00506
00507 pRender->DrawPath(&(m_pPathList[i]));
00508
00509 }
00510 else
00511 {
00512 if (pProc)
00513 pProc->SetActive(TRUE);
00514
00515 Ratio = (StepSize * i) + StepSize;
00516
00517
00518 CProfileBiasGain Profile = pControl->GetAttrProfile();
00519 Profile.SetBias(-Profile.GetBias());
00520 Ratio = (double)Profile.MapZeroToOne((AFp)Ratio);
00521
00522 Ratio = 1.0 - Ratio;
00523
00524 if (!BlendAttributes(pRender, pAttrMapStart, pAttrMapEnd, &BlendAttrMap,
00525 Ratio))
00526 {
00527 ERROR3("Blend attributes failed");
00528
00529
00530 pRender->PopPathProcessor();
00531 return;
00532
00533 }
00534
00535
00536
00537
00538
00539 BlendAttrMap.PostBlendInit(&(m_pPathList[i]), GetRuntimeClass());
00540
00541 pRender->SaveContext();
00542 BlendAttrMap.Render(pRender);
00543
00544
00545
00546
00547
00548 PathProcessor* pPP = pRender->GetFirstPathProcessor();
00549 if (pPP && pPP->IsAPathProcessorStroke())
00550 pPP->SetDisabled(TRUE);
00551
00552 pRender->DrawPath(&(m_pPathList[i]));
00553
00554 if (pPP)
00555 pPP->SetDisabled(FALSE);
00556
00557 pRender->RestoreContext();
00558
00559
00560
00561 BlendAttrMap.PostBlendDeinit();
00562 }
00563 }
00564 else
00565 {
00566 if (pProc)
00567 pProc->SetActive(FALSE);
00568
00569 Ratio = StepSize * i;
00570
00571
00572 CProfileBiasGain Profile = pControl->GetAttrProfile();
00573 Profile.SetBias(-Profile.GetBias());
00574 Ratio = (double)Profile.MapZeroToOne((AFp)Ratio);
00575
00576 if (Ratio > 0 && Ratio < 1.0)
00577 {
00578 if (!BlendAttributes(pRender, pAttrMapStart, pAttrMapEnd, &BlendAttrMap,
00579 Ratio))
00580 {
00581 ERROR3("Blend attributes failed");
00582
00583 pRender->PopPathProcessor();
00584 return;
00585 }
00586 pRender->SaveContext();
00587
00588
00589
00590
00591 BlendAttrMap.PostBlendInit(&(m_pPathList[(m_NumPaths-1) - i]), GetRuntimeClass());
00592
00593 BlendAttrMap.Render(pRender);
00594 }
00595 else if (Ratio == 0)
00596 {
00597 pRender->SaveContext();
00598 pAttrMapStart->Render(pRender);
00599 }
00600 else
00601 {
00602 pRender->SaveContext();
00603 pAttrMapEnd->Render(pRender);
00604 }
00605
00606
00607 pWinding = (WindingRuleAttribute *)pRender->GetCurrentAttribute(ATTR_WINDINGRULE);
00608
00609 pWinding->WindingRule = NegativeWinding;
00610
00611 pRender->DrawPath(&(m_pPathList[(m_NumPaths-1) - i]));
00612 pRender->RestoreContext();
00613
00614 if (Ratio > 0 && Ratio < 1.0)
00615 {
00616
00617
00618 BlendAttrMap.PostBlendDeinit();
00619 }
00620 }
00621 }
00622
00623 pAttrMapStart->DeleteAttributes();
00624 delete pAttrMapStart;
00625 delete pAttrMapEnd;
00626
00627 BlendAttrMap.DeleteAttributes();
00628 }
00629
00630 pRender->RestoreContext();
00631
00632
00633 if (pProc)
00634 pRender->PopPathProcessor();
00635
00636
00637 pControl->EnableInsetPathPathProcessor();
00638 }
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 NodeRenderableInk * NodeContour::FindNodeToContour(NodeRenderableInk * pInk)
00652 {
00653 if (!pInk->IsCompound())
00654 return pInk;
00655
00656 Node * pNodeStep = pInk->FindFirstDepthFirst();
00657
00658 AttrFillGeometry * pFill = NULL;
00659
00660 while (pNodeStep && pNodeStep != pInk)
00661 {
00662 if (pNodeStep->IsAnObject())
00663 {
00664 if (!pNodeStep->NeedsParent(NULL))
00665 {
00666
00667 if (((NodeRenderableInk *)pNodeStep)->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillGeometry),
00668 (NodeAttribute **)(&pFill)))
00669 {
00670
00671 if (pFill->GetStartColour())
00672 {
00673 if (!pFill->GetStartColour()->IsTransparent())
00674 return (NodeRenderableInk *)pNodeStep;
00675 }
00676 }
00677 }
00678 }
00679
00680 pNodeStep = pNodeStep->FindNextDepthFirst(pInk);
00681 }
00682
00683 return pInk;
00684 }
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696 BOOL NodeContour::DoBecomeA(BecomeA* pBecomeA)
00697 {
00698
00699 ERROR2IF_PF(pBecomeA == NULL,FALSE,("pBecomeA is NULL"));
00700
00701 if (!pBecomeA->BAPath())
00702 {
00703 return FALSE;
00704 }
00705
00706 BOOL ValidReason = (pBecomeA->GetReason() == BECOMEA_REPLACE || pBecomeA->GetReason() == BECOMEA_PASSBACK);
00707 ERROR2IF_PF(!ValidReason,FALSE,("Unkown BecomeA reason %d",pBecomeA->GetReason()));
00708
00709 UndoableOperation* pOp = pBecomeA->GetUndoOp();
00710
00711 double StepSize = 0;
00712 double Ratio = 0;
00713
00714 NodeContourController * pController = (NodeContourController *)FindParent();
00715
00716 if (!pController)
00717 {
00718 ERROR3("No contour controller for become a");
00719 return FALSE;
00720 }
00721
00722 INT32 Width = pController->GetWidth();
00723
00724
00725
00726 BOOL bPassback = FALSE;
00727
00728 if (pBecomeA->GetReason() == BECOMEA_PASSBACK)
00729 bPassback = TRUE;
00730
00731
00732
00733
00734 if (m_pPathList != NULL && m_NumPaths > 0)
00735 {
00736
00737 CCAttrMap BlendAttrMap(30);
00738
00739
00740 NodeRenderableInk * pEndNode = NULL;
00741
00742 if (pController->GetWidth() > 0)
00743 {
00744 pEndNode = (NodeRenderableInk *)FindPrevious(CC_RUNTIME_CLASS(NodeRenderableInk));
00745 }
00746 else
00747 {
00748 pEndNode = (NodeRenderableInk *)FindNext(CC_RUNTIME_CLASS(NodeRenderableInk));
00749 }
00750
00751 if (!pEndNode)
00752 {
00753 ERROR3("No node present to contour");
00754 return FALSE;
00755 }
00756
00757
00758
00759 if (pEndNode->IsCompound())
00760 {
00761 pEndNode = FindNodeToContour(pEndNode);
00762 }
00763
00764 if (pEndNode->IS_KIND_OF(NodeBlend))
00765 {
00766 pEndNode = (NodeRenderableInk *)pEndNode->FindFirstChild(CC_RUNTIME_CLASS(NodeRenderableInk));
00767 }
00768
00769
00770 CCAttrMap * pAttrMapStart = CCAttrMap::MakeAppliedAttrMap(this);
00771 CCAttrMap * pAttrMapEnd = CCAttrMap::MakeAppliedAttrMap(pEndNode);
00772
00773 ERROR3IF (pAttrMapStart == NULL, "pAttrMapStart is NULL!");
00774 ERROR3IF (pAttrMapEnd == NULL, "pAttrMapEnd is NULL!");
00775
00776 StepSize = 1.0 / ((double)(m_NumPaths));
00777
00778 NodePath* pPath = NULL;
00779 Node* pInsertContext = this;
00780
00781
00782
00783
00784
00785
00786 if (Width < 0)
00787 {
00788
00789
00790
00791 INT32 i = m_NumPaths-1;
00792
00793 if (pOp)
00794 {
00795 ALLOC_WITH_FAIL(pPath, new NodePath, pOp);
00796 }
00797 else
00798 {
00799 pPath = new NodePath;
00800
00801 ERRORIF(pPath == NULL, _R(IDE_NOMORE_MEMORY), FALSE);
00802 }
00803
00804 pPath->InkPath.Initialise();
00805 pPath->InkPath.CloneFrom(m_pPathList[i]);
00806 pPath->InkPath.IsFilled = TRUE;
00807 pPath->InkPath.InitialiseFlags(0, pPath->InkPath.GetNumCoords());
00808
00809
00810 if (!bPassback)
00811 {
00812 pPath->ApplyAttributes(pAttrMapStart, TRUE);
00813
00814 if (pOp)
00815 pOp->DoInsertNewNode(pPath, pInsertContext, NEXT, TRUE, FALSE, TRUE, TRUE);
00816 else
00817 {
00818 pPath->AttachNode(pInsertContext, NEXT, FALSE, FALSE);
00819 pPath->NormaliseAttributes();
00820 }
00821 pInsertContext = pPath;
00822 pPath->SetSelected(TRUE);
00823
00824 pBecomeA->PassBack(pPath, this, pAttrMapStart->Copy());
00825 }
00826 else
00827 {
00828 pBecomeA->PassBack(pPath, this, pAttrMapStart->Copy());
00829 }
00830
00831
00832 for (i = m_NumPaths-2; i>=0; i--)
00833 {
00834
00835 Ratio = (StepSize * ((double)i)) + StepSize;
00836
00837
00838 CProfileBiasGain Profile = pController->GetAttrProfile();
00839 Profile.SetBias(-Profile.GetBias());
00840 Ratio = (double)Profile.MapZeroToOne((AFp)Ratio);
00841
00842 Ratio = 1.0 - Ratio;
00843
00844 if (!BlendAttributes(NULL, pAttrMapStart, pAttrMapEnd, &BlendAttrMap,
00845 Ratio))
00846 {
00847 ERROR3("Blend attributes failed");
00848 return FALSE;
00849 }
00850
00851 if (pOp)
00852 {
00853 ALLOC_WITH_FAIL(pPath, new NodePath, pOp);
00854 }
00855 else
00856 {
00857 pPath = new NodePath;
00858
00859 ERRORIF(pPath == NULL, _R(IDE_NOMORE_MEMORY), FALSE);
00860 }
00861
00862 pPath->InkPath.Initialise();
00863 pPath->InkPath.CloneFrom(m_pPathList[i]);
00864
00865 pPath->InkPath.IsFilled = TRUE;
00866 pPath->InkPath.InitialiseFlags(0, pPath->InkPath.GetNumCoords());
00867
00868
00869 if (!bPassback)
00870 {
00871
00872
00873 pPath->ApplyAttributes(&BlendAttrMap, TRUE);
00874
00875 if (pOp)
00876 pOp->DoInsertNewNode(pPath, pInsertContext, NEXT, TRUE, FALSE, TRUE, TRUE);
00877 else
00878 {
00879 pPath->AttachNode(pInsertContext, NEXT, FALSE, FALSE);
00880 pPath->NormaliseAttributes();
00881 }
00882
00883 pInsertContext = pPath;
00884 pPath->SetSelected(TRUE);
00885
00886 pBecomeA->PassBack(pPath, this, BlendAttrMap.Copy());
00887 }
00888 else
00889 {
00890 pBecomeA->PassBack(pPath, this, BlendAttrMap.Copy());
00891 }
00892 }
00893 }
00894 else
00895 {
00896
00897 INT32 i = 0;
00898 for (i = m_NumPaths-1; i!=0 ; i--)
00899 {
00900
00901
00902
00903 Path* pStepPath = &(m_pPathList[(m_NumPaths - 1) - i]);
00904 if (pStepPath && pStepPath->GetNumCoords() > 0)
00905 {
00906
00907 Ratio = (StepSize * ((double)i));
00908
00909
00910 CProfileBiasGain Profile = pController->GetAttrProfile();
00911 Profile.SetBias(-Profile.GetBias());
00912 Ratio = (double)Profile.MapZeroToOne((AFp)Ratio);
00913
00914 if (!BlendAttributes(NULL, pAttrMapStart, pAttrMapEnd, &BlendAttrMap,
00915 Ratio))
00916 {
00917 ERROR3("Blend attributes failed");
00918 return FALSE;
00919 }
00920
00921 pPath = new NodePath;
00922
00923 pPath->InkPath.Initialise();
00924 pPath->InkPath.CloneFrom(*pStepPath);
00925 pPath->InkPath.IsFilled = TRUE;
00926 pPath->InkPath.InitialiseFlags(0, pPath->InkPath.GetNumCoords());
00927
00928 if (!bPassback)
00929 {
00930 pPath->ApplyAttributes(&BlendAttrMap, TRUE);
00931 if (pOp)
00932 pOp->DoInsertNewNode(pPath, pInsertContext, NEXT, TRUE, FALSE, TRUE, TRUE);
00933 else
00934 {
00935 pPath->AttachNode(pInsertContext, NEXT, FALSE, FALSE);
00936 pPath->NormaliseAttributes();
00937 }
00938
00939 pInsertContext = pPath;
00940 pBecomeA->PassBack(pPath, pPath, BlendAttrMap.Copy());
00941 }
00942 else
00943 {
00944 pBecomeA->PassBack(pPath, pPath, BlendAttrMap.Copy());
00945 }
00946 }
00947 }
00948
00949
00950 Path* pStepPath = &(m_pPathList[m_NumPaths - 1]);
00951 if (pStepPath && pStepPath->GetNumCoords() > 0)
00952 {
00953 pPath = new NodePath;
00954 pPath->InkPath.Initialise();
00955
00956 pPath->InkPath.CloneFrom(*pStepPath);
00957 pPath->InkPath.IsFilled = TRUE;
00958 pPath->InkPath.InitialiseFlags(0, pPath->InkPath.GetNumCoords());
00959
00960
00961 if (!bPassback)
00962 {
00963
00964 pPath->ApplyAttributes(pAttrMapStart, TRUE);
00965 if (pOp)
00966 pOp->DoInsertNewNode(pPath, pInsertContext, NEXT, TRUE, FALSE, TRUE, TRUE);
00967 else
00968 {
00969 pPath->AttachNode(pInsertContext, NEXT, FALSE, FALSE);
00970 pPath->NormaliseAttributes();
00971 }
00972
00973 pInsertContext = pPath;
00974
00975 pBecomeA->PassBack(pPath, pPath, pAttrMapStart->Copy());
00976 }
00977 else
00978 {
00979 pBecomeA->PassBack(pPath, pPath, pAttrMapStart->Copy());
00980 }
00981 }
00982 }
00983
00984 BlendAttrMap.DeleteAttributes();
00985
00986 delete pAttrMapStart;
00987 delete pAttrMapEnd;
00988
00989
00990 if (!bPassback)
00991 {
00992 if (pOp)
00993 {
00994 NodeHidden * pHidden = NULL;
00995 pOp->DoHideNode(this, TRUE, &pHidden, TRUE);
00996 }
00997 else
00998 {
00999 CascadeDelete();
01000 delete this;
01001 }
01002 }
01003
01004 return TRUE;
01005 }
01006
01007 return FALSE;
01008 }
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020 BOOL NodeContour::CopyAttributes(NodeRenderableInk * pNode, CCAttrMap * pAttrMap)
01021 {
01022 ERROR2IF(pNode == NULL, FALSE, "Node is null");
01023 ERROR2IF(pAttrMap == NULL, FALSE, "Attribute map is null");
01024
01025 CCAttrMap::iterator end = pAttrMap->GetEndPosition();
01026 CCAttrMap::iterator PosStart = pAttrMap->GetStartPosition();
01027
01028 while( PosStart != end )
01029 {
01030 CCRuntimeClass *pTypeStart = NULL;
01031 void *pValStart = NULL;
01032
01033 pAttrMap->GetNextAssoc( PosStart, pTypeStart, pValStart );
01034 NodeAttribute* pNodeAttr = (NodeAttribute *)pValStart;
01035
01036
01037 if (pNodeAttr)
01038 {
01039 if (pNodeAttr->CanBeAppliedToObject())
01040 {
01041 if (!pNodeAttr->CopyNode(pNode, FIRSTCHILD))
01042 {
01043 ERROR3("Copy node failed");
01044 return FALSE;
01045 }
01046 }
01047 }
01048 }
01049
01050 return TRUE;
01051 }
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071 BOOL NodeContour::CanBecomeA(BecomeA* pBecomeA)
01072 {
01073 if (pBecomeA->BAPath())
01074 {
01075 if (pBecomeA->IsCounting())
01076 {
01077 NodeContourController * pControl = (NodeContourController *)FindParent();
01078
01079 if (pControl->GetInsetPathFlag())
01080 {
01081 pBecomeA->AddCount(1);
01082 }
01083 else
01084 {
01085 pBecomeA->AddCount(pControl->GetNumberOfSteps());
01086 }
01087 }
01088
01089 return TRUE;
01090 }
01091
01092 return FALSE;
01093 }
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105 BOOL NodeContour::NeedsParent(Node* pClassNode) const
01106 {
01107 if (!pClassNode)
01108 return TRUE;
01109
01110 if (pClassNode->IsKindOf(CC_RUNTIME_CLASS(NodeContourController)))
01111 return TRUE;
01112
01113 return FALSE;
01114 }
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126 String NodeContour::Describe(BOOL Plural, BOOL Verbose)
01127 {
01128 String Name;
01129 Name.Load(_R(IDS_CONTOUR_NODE_NAME));
01130
01131 if (Plural)
01132 {
01133 Name += _T("s");
01134 }
01135
01136 return Name;
01137 }
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184 BOOL NodeContour::GenerateContourPathForNode( Path* pDestPath,
01185 Node* pSourceNode,
01186 const List* pSourceList,
01187 const MILLIPOINT nWidth,
01188 const BOOL fOuterContour,
01189 const JointType jt,
01190 const MILLIPOINT nFlatness,
01191 const BOOL fUseLineWidths,
01192 const BOOL fIncludeShadows )
01193 {
01194
01195 ERROR2IF(pDestPath == NULL ||
01196 (pSourceNode == NULL && pSourceList == NULL), FALSE,
01197 "NodeContour::GenerateContourPathForNode; Invalid input parameters!");
01198
01199 pDestPath->ClearPath();
01200 pDestPath->Initialise();
01201
01202
01203
01204
01205
01206
01207 PathBecomeA baOutline( BECOMEA_PASSBACK,
01208 CC_RUNTIME_CLASS(NodePath),
01209 NULL,
01210 FALSE,
01211 pDestPath,
01212 PathBecomeA::ADD_OUTLINES
01213 );
01214
01215 baOutline.SetDoSilhouette(TRUE);
01216 baOutline.SetDoShadowSilhouettes(TRUE);
01217
01218 BOOL fSuccess = pSourceNode->DoBecomeA(&baOutline);
01219
01220 if (fSuccess && pDestPath->GetNumCoords() > 2)
01221 {
01222 Path WorkPath;
01223 WorkPath.Initialise();
01224 WorkPath.CloneFrom(*pDestPath);
01225 WorkPath.InitializeContourValues(2 * nWidth);
01226 fSuccess = (WorkPath.GetContourForStep(pDestPath) > 0);
01227 }
01228
01229
01230 return fSuccess;
01231 }
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245 BOOL NodeContour::GenerateContour(List * pList, CCAttrMap * pAttrMap)
01246 {
01247
01248 NodeContourController * pControl = (NodeContourController *)FindParent();
01249 Node * pNode = pControl;
01250
01251
01252 if (!pNode)
01253 return FALSE;
01254
01255
01256 if (pControl->IsPrinting())
01257 {
01258 ERROR3("Generate contour called when printing");
01259 return FALSE;
01260 }
01261
01262
01263 if (pControl->GetInsetPathFlag())
01264 m_NumPaths = 0;
01265
01266 if (pControl->GetInsideBoundingRect().IsEmpty())
01267 return FALSE;
01268
01269 DeleteCache();
01270
01271 pNode = pNode->FindFirstChild();
01272
01273 if (!pNode)
01274 return FALSE;
01275
01276 m_SourcePath.ClearPath();
01277
01278 if (m_pPathList)
01279 {
01280 delete [] m_pPathList;
01281 m_pPathList = NULL;
01282 }
01283
01284 INT32 Width = 0;
01285 INT32 NumSteps = 0;
01286 BOOL bOuter = FALSE;
01287
01288 if (pControl)
01289 {
01290 NumSteps = pControl->GetNumberOfSteps();
01291 Width = pControl->GetWidth();
01292
01293 if (Width < 0)
01294 {
01295 Width = -Width;
01296 bOuter = TRUE;
01297 }
01298
01299 NumSteps ++;
01300
01301 if (pControl->GetInsetPathFlag())
01302 NumSteps = 1;
01303 }
01304
01305 ERROR3IF (NumSteps <= 0, "I'm not going to work with that!");
01306
01307
01308 m_pPathList = new Path[NumSteps];
01309
01310 if (!m_pPathList)
01311 {
01312 ERROR3("Can't create path list");
01313 return FALSE;
01314 }
01315
01316 for (INT32 i = 0; i < NumSteps; i++)
01317 m_pPathList[i].Initialise();
01318
01319
01320
01321
01322
01323 AttrJoinType * pJT = NULL;
01324 AttrStartCap * pCT = NULL;
01325 JointType generateJoinType = BevelledJoin;
01326 LineCapType ct = LineCapRound;
01327
01328 if (!pList)
01329 {
01330 if (FindAppliedAttribute(CC_RUNTIME_CLASS(AttrJoinType), (NodeAttribute **)&pJT))
01331 {
01332
01333 if (pJT)
01334 generateJoinType = pJT->Value.JoinType;
01335 }
01336
01337 if (FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStartCap), (NodeAttribute **)&pCT))
01338 {
01339
01340 if (pCT)
01341 ct = pCT->Value.StartCap;
01342 }
01343 }
01344
01345 double Flatness = 200.0;
01346
01348
01349
01350
01351
01352 Node* pNodeToBevel = pControl->FindFirstChildInk();
01353
01354 while(pNodeToBevel == this && pNodeToBevel)
01355 pNodeToBevel = pNodeToBevel->FindNextInk();
01356
01357 if(pNodeToBevel)
01358 {
01359 DocRect DR = ((NodeRenderableInk*)pNodeToBevel)->GetBoundingRect();
01360
01361 if(!DR.IsEmpty())
01362 {
01363
01364 double Smallest = DR.Height() < DR.Width() ? (double)DR.Height() : (double)DR.Width();
01365
01366
01367 Flatness = Smallest / 375.0;
01368 }
01369
01370
01371 if(1.0 > Flatness) Flatness = 1.0;
01372 if(375.0 < Flatness) Flatness = 375.0;
01373 }
01375
01376
01377 CProfileBiasGain ObjectProfile( pControl->GetObjectProfile() );
01378 ContourBecomeA MyBecomeA( BECOMEA_PASSBACK, CC_RUNTIME_CLASS(NodePath),
01379 NULL, FALSE, m_pPathList, &m_SourcePath, Width, NumSteps, bOuter, ObjectProfile,
01380 generateJoinType, Flatness, FALSE );
01381
01382
01383 MyBecomeA.SetCallNode(this);
01384
01385 Path BecomeAStrokedPath;
01386 BecomeAStrokedPath.Initialise();
01387
01388 Path CopyPath;
01389 CopyPath.Initialise();
01390
01391 Path TempPath;
01392 TempPath.Initialise();
01393 NodePath * pPathNode = NULL;
01394
01395
01396 if (!pList)
01397 {
01398 while (pNode)
01399 {
01400
01401 if (!pNode->IS_KIND_OF(NodeBlendPath))
01402 {
01403 MyBecomeA.ResetCount();
01404
01405 if (pNode->IsNodePath())
01406 {
01407
01408
01409
01410 BOOL IsStroked = (((NodeRenderableInk*)pNode)->GetActiveStroke() != NULL);
01411
01412 if(IsStroked)
01413 pPathNode = (NodePath*)pNode;
01414 else
01415 pPathNode = ((NodePath *)pNode)->MakeNodePathFromAttributes(Flatness,NULL,FALSE,FALSE);
01416
01417 pPathNode->DoBecomeA(&MyBecomeA);
01418
01419 if(!IsStroked)
01420 {
01421 delete pPathNode;
01422 pPathNode = NULL;
01423 }
01424 }
01425 else if (pNode->CanBecomeA(&MyBecomeA) && pNode != this)
01426 {
01427 if (MyBecomeA.GetCount() > 0)
01428 {
01429 if (pNode->IsABaseTextClass())
01430 {
01431
01432 if (pNode->IS_KIND_OF(TextStory))
01433 {
01434 ((TextStory *)pNode)->FormatAndChildren();
01435 }
01436 else
01437 {
01438 if (((BaseTextClass *)pNode)->FindParentStory())
01439 {
01440 ((BaseTextClass *)pNode)->FindParentStory()->FormatAndChildren();
01441 }
01442 else
01443 {
01444 ERROR3("Found a base text class with no parent story");
01445 }
01446 }
01447 }
01448
01449 pNode->DoBecomeA(&MyBecomeA);
01450
01451 if(MyBecomeA.GetCount() > 1)
01452 {
01453
01454 CopyPath.ClearPath();
01455 CopyPath.CloneFrom(*m_pPathList);
01456 m_pPathList->ClearPath();
01457
01458 TempPath.ClipPathToPath(CopyPath,m_pPathList,7|(1<<4),50,Flatness,Flatness);
01459 }
01460 }
01461 }
01462 }
01463
01464 pNode = pNode->FindNext();
01465 }
01466 }
01467 else
01468 {
01469 SumAllPathsElem *pElem = (SumAllPathsElem *)pList->GetHead();
01470
01471 while (pElem)
01472 {
01473 Path BlankPath;
01474 BlankPath.Initialise();
01475
01476 NodePath * pPathNode = new NodePath;
01477 ERRORIF(pPathNode == NULL, _R(IDE_NOMORE_MEMORY), FALSE);
01478
01479 pPathNode->InkPath.Initialise();
01480
01481 pElem->GetPath()->ClipPathToPath(BlankPath, &(pPathNode->InkPath), 6);
01482
01483 AttrJoinType * pJoinType = NULL;
01484 AttrStartCap * pStartType = NULL;
01485
01486 pElem->GetAttrMap ()->Lookup( CC_RUNTIME_CLASS(AttrJoinType), (void *&)pJoinType );
01487 pElem->GetAttrMap ()->Lookup( CC_RUNTIME_CLASS(AttrStartCap), (void *&)pStartType );
01488
01489 if (pJoinType)
01490 generateJoinType = pJoinType->Value.JoinType;
01491
01492 if (pStartType)
01493 ct = pStartType->Value.StartCap;
01494
01495 NodePath * pStrokedPathNode = pPathNode->MakeNodePathFromAttributes(Flatness, pElem->GetAttrMap(),FALSE,FALSE);
01496
01497 if (pStrokedPathNode)
01498 {
01499 pStrokedPathNode->DoBecomeA(&MyBecomeA);
01500 delete pStrokedPathNode;
01501 }
01502
01503 if(pPathNode)
01504 {
01505 delete pPathNode;
01506 pPathNode = NULL;
01507 }
01508
01509 pElem = (SumAllPathsElem *)pList->GetNext(pElem);
01510 }
01511 }
01512
01513
01514 for( INT32 i = NumSteps-1; i >= 0; i-- )
01515 m_pPathList[i].IsStroked = TRUE;
01516
01517 m_NumPaths = NumSteps;
01518
01519 InvalidateBoundingRect();
01520
01521 if (FindParent())
01522 ((NodeRenderableInk *)FindParent())->InvalidateBoundingRect(TRUE);
01523
01524 return TRUE;
01525 }
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537 void NodeContour::DeleteCache()
01538 {
01539 if (m_pPathList)
01540 {
01541 delete [] m_pPathList;
01542 m_pPathList = NULL;
01543 m_NumPaths = 0;
01544 }
01545 }
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557 void NodeContour::Transform(TransformBase &Trans)
01558 {
01559 DocRect dr ;
01560
01561 for (INT32 i = 0 ; i < m_NumPaths; i++)
01562 {
01563 Trans.Transform(m_pPathList[i].GetCoordArray(), m_pPathList[i].GetNumCoords());
01564 dr = dr.Union(m_pPathList[i].GetBoundingRect());
01565 }
01566
01567 InvalidateBoundingRect(TRUE);
01568
01569 Node * pNode = NULL;
01570 NodeContourController * pControl = (NodeContourController *)FindParent();
01571
01572 if (!pControl)
01573 return;
01574
01575 if (pControl->GetWidth() > 0)
01576 pNode = FindPrevious(CC_RUNTIME_CLASS(NodeRenderableInk));
01577 else
01578 pNode = FindNext(CC_RUNTIME_CLASS(NodeRenderableInk));
01579
01580
01581 Trans2DMatrix * pMat2D = NULL;
01582
01583 if (Trans.IsInvertable())
01584 pMat2D = (Trans2DMatrix*)(&Trans);
01585
01586 if (pMat2D)
01587 {
01588 if (!pMat2D->GetMatrix().IsTranslation())
01589 {
01590 while (pNode)
01591 {
01592 if (pNode->IsABaseTextClass())
01593 {
01594
01595 if (pNode->IS_KIND_OF(TextStory))
01596 {
01597 ((TextStory *)pNode)->FormatAndChildren();
01598 }
01599 else
01600 {
01601 if (((BaseTextClass *)pNode)->FindParentStory())
01602 {
01603 ((BaseTextClass *)pNode)->FindParentStory()->FormatAndChildren();
01604 }
01605 else
01606 {
01607 ERROR3("Found a base text class with no parent story");
01608 }
01609 }
01610 }
01611
01612 if (pControl->GetWidth() > 0)
01613 pNode = pNode->FindPrevious(CC_RUNTIME_CLASS(NodeRenderableInk));
01614 else
01615 pNode = pNode->FindNext(CC_RUNTIME_CLASS(NodeRenderableInk));
01616 }
01617 }
01618 }
01619
01620 TransformChildren(Trans);
01621 }
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633 void NodeContour::RenderEorDrag(RenderRegion * pRender)
01634 {
01635 if (!m_pPathList || m_NumPaths == 0)
01636 return;
01637
01638 if (m_pPathList[0].GetNumCoords()>0)
01639 pRender->DrawPath(&(m_pPathList[0]));
01640
01641 if (m_pPathList[m_NumPaths-1].GetNumCoords()>0)
01642 pRender->DrawPath(&(m_pPathList[m_NumPaths-1]));
01643 }
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655 BOOL NodeContour::WritePreChildrenWeb(BaseCamelotFilter* pFilter)
01656 {
01657 CXaraFileRecord Rec(TAG_CONTOUR, TAG_CONTOUR_SIZE);
01658
01659 BOOL ok = Rec.Init();
01660 if (ok) ok = pFilter->Write(&Rec);
01661
01662 return ok;
01663 }
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675 BOOL NodeContour::WritePreChildrenNative(BaseCamelotFilter* pFilter)
01676 {
01677 return WritePreChildrenWeb(pFilter);
01678 }
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690 Node* NodeContour::SimpleCopy()
01691 {
01692 NodeContour * pNode = new NodeContour;
01693
01694 if (!pNode)
01695 {
01696 ERROR3("Can't create node contour");
01697 return NULL;
01698 }
01699
01700 CopyNodeContents(pNode);
01701
01702 return pNode;
01703 }
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715 void NodeContour::CopyNodeContents(NodeContour* pNewNode)
01716 {
01717 if (pNewNode->m_pPathList)
01718 {
01719 for (INT32 i = 0 ; i < pNewNode->m_NumPaths; i++)
01720 {
01721 pNewNode->m_pPathList[i].ClearPath();
01722 }
01723 delete[] pNewNode->m_pPathList;
01724 }
01725
01726 pNewNode->m_NumPaths = m_NumPaths;
01727 pNewNode->m_pPathList = new Path[m_NumPaths];
01728 pNewNode->m_FirstRender = m_FirstRender;
01729
01730 if (pNewNode->m_pPathList)
01731 {
01732 for (INT32 i = 0 ; i < m_NumPaths; i++)
01733 {
01734 pNewNode->m_pPathList[i].Initialise();
01735 pNewNode->m_pPathList[i].CloneFrom(m_pPathList[i]);
01736 pNewNode->m_pPathList[i].IsFilled = TRUE;
01737 pNewNode->m_pPathList[i].IsStroked = TRUE;
01738 }
01739 }
01740
01741 pNewNode->m_SourcePath.CloneFrom(m_SourcePath);
01742
01743 NodeRenderableInk::CopyNodeContents(pNewNode);
01744 }
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761 void NodeContour::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
01762 {
01763 ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node");
01764 ENSURE(IS_A(pNodeCopy, NodeContour), "PolyCopyNodeContents given wrong dest node type");
01765
01766 if (IS_A(pNodeCopy, NodeContour))
01767 CopyNodeContents((NodeContour*)pNodeCopy);
01768 }
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785 BOOL NodeContour::BlendAttributes(RenderRegion * pRender, CCAttrMap * pAttrMapStart,
01786 CCAttrMap * pAttrMapEnd, CCAttrMap * pBlendedAttrMap,
01787 double BlendRatio)
01788 {
01789
01790
01791
01792
01793 CCRuntimeClass *pTypeStart = NULL;
01794 void *pValStart = NULL;
01795 void *pValEnd = NULL;
01796
01797 NodeContourController * pController = (NodeContourController *)FindParent(CC_RUNTIME_CLASS(NodeContourController));
01798
01799 if (!pController)
01800 return FALSE;
01801
01802 BOOL useStartAttrMap = FALSE;
01803
01804 CCAttrMap::iterator PosStart = pAttrMapStart->GetStartPosition();
01805 CCAttrMap::iterator end = pAttrMapStart->GetEndPosition();
01806 while ( PosStart != end )
01807 {
01808
01809 pAttrMapStart->GetNextAssoc(PosStart,pTypeStart,pValStart);
01810 NodeAttribute* pNodeAttrStart = (NodeAttribute *)pValStart;
01811
01812 if (pNodeAttrStart->CanBeAppliedToObject())
01813 {
01814
01815 NodeAttribute* pBlendedNodeAttr = NULL;
01816
01817 if (pAttrMapEnd)
01818 {
01819
01820
01821 if (pAttrMapEnd->Lookup(pTypeStart,pValEnd))
01822 {
01823
01824 BlendAttrParam BlendParam;
01825
01826
01827 if (BlendParam.Init(pRender,
01828 (NodeAttribute *)pValEnd,BlendRatio,pController->GetColourBlendType(),
01829 pAttrMapStart, pAttrMapEnd))
01830 {
01831
01832 if (pNodeAttrStart->Blend(&BlendParam))
01833 {
01834
01835
01836
01837 pBlendedNodeAttr = BlendParam.GetBlendedAttr();
01838 }
01839 }
01840
01841 }
01842 }
01843 else
01844 {
01845 useStartAttrMap = TRUE;
01846 }
01847
01848
01849 if (pBlendedNodeAttr != NULL)
01850 {
01851
01852 CCRuntimeClass *pTypeBlend = pBlendedNodeAttr->GetAttributeType();
01853
01854 void* pValBlend;
01855
01856
01857
01858 if (pBlendedAttrMap->Lookup(pTypeBlend,pValBlend))
01859 {
01860 if (pValBlend != NULL)
01861 {
01862 pBlendedAttrMap->RemoveKey(pTypeBlend);
01863 delete (NodeAttribute*)pValBlend;
01864 }
01865 }
01866
01867 pBlendedAttrMap->SetAt(pTypeBlend,pBlendedNodeAttr);
01868 }
01869 }
01870 }
01871
01872 if (useStartAttrMap)
01873 {
01874 pBlendedAttrMap = pAttrMapStart->Copy ();
01875 }
01876
01877 return TRUE;
01878 }
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898 BOOL NodeContour::AllowOp(ObjChangeParam *pParam, BOOL SetOpPermissionState,
01899 BOOL DoPreTriggerEdit)
01900 {
01901 ERROR2IF(pParam==NULL,FALSE,"NodeContourController::AllowOp() - pParam==NULL");
01902
01903
01904 pParam->SetCallingChild(NULL);
01905
01906
01907 BOOL allowed=TRUE;
01908
01909 UndoableOperation* pOp = pParam->GetOpPointer();
01910
01911
01912 if (allowed && Parent != NULL && pParam->GetDirection() != OBJCHANGE_CALLEDBYPARENT)
01913 {
01914 ObjChangeDirection OldDirection=pParam->GetDirection();
01915 pParam->SetCallingChild(this);
01916 pParam->SetDirection(OBJCHANGE_CALLEDBYCHILD);
01917 allowed=Parent->AllowOp(pParam,SetOpPermissionState,DoPreTriggerEdit);
01918 pParam->SetDirection(OldDirection);
01919 }
01920
01921
01922 if (allowed)
01923 {
01924
01925 if(pOp != NULL)
01926 {
01927 if(
01928 pOp->IS_KIND_OF(OpCreateBevel) ||
01929 pOp->IS_KIND_OF(OpCreateNewMould) ||
01930 pOp->IS_KIND_OF(OpPasteEnvelope) ||
01931 pOp->IS_KIND_OF(OpPastePerspective) ||
01932 false )
01933 {
01934 allowed = FALSE;
01935 }
01936 }
01937 }
01938
01939
01940 if (SetOpPermissionState)
01941 SetOpPermission(allowed ? PERMISSION_ALLOWED : PERMISSION_DENIED, TRUE);
01942
01943 if (allowed)
01944 {
01945 UndoableOperation* pChangeOp = pParam->GetOpPointer();
01946
01947
01948 BOOL InformGeomLinkedAttrs = SetOpPermissionState && pChangeOp && pChangeOp->MayChangeNodeBounds();
01949 if (InformGeomLinkedAttrs)
01950 {
01951 NodeAttribute* pNA = FindFirstGeometryLinkedAttr();
01952 while(pNA)
01953 {
01954 pNA->LinkedNodeGeometryHasChanged(pChangeOp);
01955 pNA = pNA->FindNextGeometryLinkedAttr();
01956 }
01957 }
01958
01959
01960
01961
01962 if (DoPreTriggerEdit && pChangeOp && pChangeOp->MayChangeNodeBounds() && NameGallery::Instance())
01963 {
01964 allowed = NameGallery::Instance()->PreTriggerEdit(pChangeOp, pParam, this);
01965 }
01966 }
01967
01968
01969 return allowed;
01970 }
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984 void NodeContour::RenderTinyBlobs(RenderRegion * pRender)
01985 {
01986
01987 pRender->SaveContext();
01988 pRender->SetLineColour(COLOUR_NONE);
01989 pRender->SetFillColour(COLOUR_UNSELECTEDBLOB);
01990
01991
01992 BlobManager* BlobMgr = GetApplication()->GetBlobManager();
01993
01994 DocCoord Coord(BoundingRectangle.lo.x + (BlobMgr->GetBlobSize() / 2),
01995 BoundingRectangle.hi.y - (BlobMgr->GetBlobSize() / 2));
01996 pRender->DrawBlob(Coord, BT_UNSELECTED);
01997 pRender->RestoreContext();
01998 }
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010 NodeCompound* NodeContour::GetParentController() const
02011 {
02012 NodeContourController* pBob = (NodeContourController*)FindParent();
02013 if (pBob != NULL && !IS_A(pBob, NodeContourController))
02014 {
02015 ERROR3("Parent of Contour was not a NodeContourController!");
02016 pBob = NULL;
02017 }
02018
02019 return pBob;
02020 }
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044 DocRect NodeContour::ValidateExtend(const ExtendParams& ExtParams)
02045 {
02046 Node* pBob = GetParentController();
02047 if (pBob == NULL)
02048 {
02049 ERROR3("NodeContour::ValidateExtend- no controller Node found!");
02050 return DocRect(INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX);
02051 }
02052 else
02053 {
02054 return pBob->ValidateExtend(ExtParams);
02055 }
02056 }
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080 void NodeContour::Extend(const ExtendParams& ExtParams)
02081 {
02082 Node* pBob = GetParentController();
02083 if (pBob == NULL)
02084 {
02085 ERROR3("NodeContour::ValidateExtend- no controller Node found!");
02086 }
02087 else
02088 {
02089 pBob->Extend(ExtParams);
02090 }
02091
02092 return;
02093 }
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110 BOOL NodeContour::OnNodePopUp(Spread* pSpread, DocCoord PointerPos, ContextMenu* pMenu)
02111 {
02112 return pMenu->BuildCommand(TOOL_OPTOKEN_CONTOUR, TRUE);
02113 }
02114
02115
02116
02117
02118
02119
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134 BOOL ContourBecomeA::PassBack(NodeRenderableInk* pNewNode,NodeRenderableInk* pCreatedByNode,
02135 CCAttrMap* pAttrMap)
02136 {
02137
02138 ERROR2IF(pNewNode == NULL || pCreatedByNode == NULL, FALSE, "Parameter null");
02139
02140
02141 if (!pNewNode->IsNodePath())
02142 {
02143
02144 if (!pNewNode->IsCompound())
02145 return FALSE;
02146
02147
02148 NodePath * pPath = (NodePath *)(((NodeCompound *)pNewNode)->GetNodeToBlend()->PublicCopy());
02149
02150
02151 pNewNode->CascadeDelete();
02152 delete pNewNode;
02153 pNewNode = pPath;
02154
02155 }
02156
02157
02158 if (((NodePath *)pNewNode)->InkPath.GetNumCoords() < 0)
02159 return TRUE;
02160
02161
02162
02163 BOOL bDeleteAttrMap = TRUE;
02164
02165 if (!pAttrMap)
02166 {
02167
02168 pAttrMap = CCAttrMap::MakeAppliedAttrMap(pCreatedByNode);
02169
02170
02171 bDeleteAttrMap = FALSE;
02172 }
02173
02174 DocRect br;
02175
02176
02177
02178 BOOL bStroke = FALSE;
02179 AttrLineWidth * pLineWidth = NULL;
02180 AttrStrokeColour * pStrokeColour = NULL;
02181 NodePath* pStrokedPath = NULL;
02182
02183 if(pAttrMap)
02184 {
02185 pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStrokeColour), (void *&)pStrokeColour );
02186
02187 if(pStrokeColour && !pStrokeColour->Value.GetStartColour()->IsTransparent())
02188 pStrokedPath = pCreatedByNode->GetSmoothVariableWidthStrokePath();
02189 }
02190 else
02191 pStrokedPath = pCreatedByNode->GetSmoothVariableWidthStrokePath();
02192
02193 if(pStrokedPath)
02194 {
02195
02196 delete pNewNode;
02197 pNewNode = pStrokedPath;
02198 pStrokedPath = NULL;
02199 bStroke = TRUE;
02200 m_bIncludeLineWidths = FALSE;
02201
02202 }
02203
02204 Path CopyPath;
02205 CopyPath.Initialise();
02206
02207 Path ClipPath;
02208 ClipPath.Initialise();
02209
02210
02211
02212
02213 BOOL IsClosed = ((NodePath *)pNewNode)->InkPath.IsClosed();
02214
02215
02216 if (IsClosed && !bStroke)
02217 {
02218 ClipPath.CloneFrom(((NodePath *)pNewNode)->InkPath);
02219 ((NodePath *)pNewNode)->InkPath.ClearPath();
02220
02221 if(CopyPath.ClipPathToPath(ClipPath, &(((NodePath *)pNewNode)->InkPath), 3, ClipPathToPath_Tolerance, m_Flatness, m_Flatness) < 0)
02222 {
02223 ERROR3("BAD PATH ALERT!");
02224 }
02225 }
02226
02227 CopyPath.ClearPath();
02228 ClipPath.ClearPath();
02229
02230
02231
02232 if (pNewNode->IS_KIND_OF(NodeBlendPath))
02233 {
02234
02235 if (pAttrMap)
02236 {
02237 if (bDeleteAttrMap)
02238 pAttrMap->DeleteAttributes();
02239
02240 delete pAttrMap;
02241 }
02242
02243 pNewNode->CascadeDelete();
02244 delete pNewNode;
02245 return TRUE;
02246 }
02247
02248 if (pNewNode->IsNodePath())
02249 {
02250 BOOL bDontUseThisNodePath = FALSE;
02251
02252
02253
02254 if (((NodePath*)pNewNode)->InkPath.GetNumCoords() < 2)
02255 bDontUseThisNodePath = TRUE;
02256
02257
02258
02259 else if (pNewNode->FindFirstChild())
02260 bDontUseThisNodePath = TRUE;
02261
02262 if (bDontUseThisNodePath)
02263 {
02264 if (pAttrMap)
02265 {
02266 if (bDeleteAttrMap)
02267 pAttrMap->DeleteAttributes();
02268
02269 delete pAttrMap;
02270 pAttrMap = NULL;
02271 }
02272
02273 pNewNode->CascadeDelete();
02274 delete pNewNode;
02275 pNewNode = NULL;
02276
02277 return TRUE;
02278 }
02279 }
02280
02281 JointType jt = m_Join;
02282
02283
02284
02285 if (IsClosed)
02286 {
02287 if(m_bIncludeLineWidths && pAttrMap != NULL)
02288 {
02289 pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrLineWidth), (void *&)pLineWidth );
02290 pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStrokeColour), (void *&)pStrokeColour );
02291
02292 if (pStrokeColour && pLineWidth)
02293 {
02294 UINT32 Width = pLineWidth->Value.LineWidth;
02295
02296 if (pStrokeColour->GetStartColour() && Width > 0)
02297 {
02298 if (!pStrokeColour->GetStartColour()->IsTransparent())
02299 {
02300
02301 Path OrigStrokedPath;
02302 OrigStrokedPath.Initialise();
02303
02304 JoinStyles JoinS = (jt==MitreJoin) ? JOIN_MITER : (jt==RoundJoin) ? JOIN_ROUND : JOIN_BEVEL;
02305
02306 OrigStrokedPath.CloneFrom(((NodePath *)pNewNode)->InkPath);
02307 ((NodePath *)pNewNode)->InkPath.ClearPath();
02308
02309 OrigStrokedPath.InitializeContourValues(Width,JoinS,true,m_Flatness);
02310 if(OrigStrokedPath.GetContourForStep(&((NodePath *)pNewNode)->InkPath,1.0) < 0)
02311 {
02312 ERROR3("BAD PATH ALERT!");
02313 }
02314 }
02315 }
02316 }
02317 }
02318
02319 ((NodePath *)pNewNode)->InkPath.TryToClose();
02320 ((NodePath *)pNewNode)->InkPath.IsFilled = TRUE;
02321 ((NodePath *)pNewNode)->InkPath.IsStroked = FALSE;
02322 }
02323 else
02324 {
02325
02326 NodePath * pWholePath = ((NodePath *)pNewNode)->MakeNodePathFromAttributes(m_Flatness, pAttrMap);
02327
02328 if (pWholePath)
02329 {
02330
02331
02332
02333 pNewNode->CascadeDelete();
02334 delete pNewNode;
02335 pNewNode = pWholePath;
02336 }
02337 }
02338
02339
02340
02341 if (m_pPathList && m_pSummedPath)
02342 {
02343
02344 if (pNewNode->IsNodePath() && ((NodePath *)pNewNode)->InkPath.GetNumCoords() > 2)
02345 {
02346 if(m_Width != 0)
02347 if(!GenerateContourPaths(&(((NodePath *)pNewNode)->InkPath), m_pPathList, m_Join, (m_bOuter == TRUE)))
02348 return FALSE;
02349
02350 m_pSummedPath->MergeTwoPaths(((NodePath *)pNewNode)->InkPath);
02351 }
02352 }
02353
02354 if (pAttrMap)
02355 {
02356 if (bDeleteAttrMap)
02357 pAttrMap->DeleteAttributes();
02358
02359 delete pAttrMap;
02360 }
02361
02362
02363
02364 pNewNode->CascadeDelete();
02365 delete pNewNode;
02366
02367 return TRUE;
02368 }
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383 BOOL ContourBecomeA::GenerateContourPaths(Path* pPathToContour, Path* pPathList, JointType jt, bool Outer,
02384 bool UseContourMode, LineCapType ct)
02385 {
02386
02387 JoinStyles JoinS = (jt==MitreJoin) ? JOIN_MITER : (jt==RoundJoin) ? JOIN_ROUND : JOIN_BEVEL;
02388 CapStyles CapS = (ct==LineCapButt) ? CAPS_BUTT : (ct==LineCapRound) ? CAPS_ROUND : CAPS_SQUARE;
02389
02390
02391 pPathToContour->InitializeContourValues(m_Width * 2, JoinS, Outer, m_Flatness, true, UseContourMode, CapS);
02392
02393 Path* pTempPath = NULL;
02394 double StepValue = 1.0;
02395
02396
02397 CProfileBiasGain Profile = m_Profile;
02398 Profile.SetBias(-Profile.GetBias());
02399
02400
02401 for (INT32 i = m_NumSteps; i > 0; i--)
02402 {
02403
02404 if (m_NumSteps >= 2)
02405 StepValue = (double)i / m_NumSteps;
02406
02407
02408 StepValue = (double)Profile.MapZeroToOne((AFp)StepValue);
02409
02410
02411 pTempPath = &pPathList[i-1];
02412
02413
02414 if(pPathToContour->GetContourForStep(pTempPath, StepValue) < 0)
02415 ERROR2(FALSE,"Failed to Get Controur! NODECNTR");
02416 }
02417
02418 return TRUE;
02419 }
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443 INT32 NodeContour::EstimateNodeComplexity (OpParam* details)
02444 {
02445 INT32 total = 0;
02446
02447 for (INT32 i = 0 ; i < m_NumPaths && m_pPathList; i++)
02448 total += m_pPathList[i].GetUsedSlots();
02449
02450 return (total);
02451 }