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 "nodeblnd.h"
00104
00105
00106
00107
00108
00109 #include "ophist.h"
00110
00111 #include "aw_eps.h"
00112 #include "cameleps.h"
00113 #include "objchge.h"
00114 #include "nodebldr.h"
00115
00116 #include "blobs.h"
00117 #include "contmenu.h"
00118 #include "blndtool.h"
00119
00120 #include "ndbldpth.h"
00121 #include "attrmap.h"
00122
00123
00124 #include "cxftags.h"
00125
00126 #include "rechblnd.h"
00127 #include "nodershp.h"
00128
00129
00130 #include "extender.h"
00131 #include "ngcore.h"
00132 #include "brshattr.h"
00133 #include "slicehelper.h"
00134
00135 DECLARE_SOURCE("$Revision: 1688 $");
00136
00137 CC_IMPLEMENT_DYNAMIC(NodeBlend,NodeGroup)
00138 CC_IMPLEMENT_DYNCREATE(InitBlendAction,Action)
00139 CC_IMPLEMENT_DYNAMIC(BlendRecordHandler, CamelotRecordHandler)
00140
00141 #define new CAM_DEBUG_NEW
00142
00143 #define NUM_DEFAULT_BLENDSTEPS 5
00144
00145 BOOL NodeBlend::s_DefaultNotAntialiased = FALSE;
00146 NodeBlender* BlendRecordHandler::m_pLastInsertedNodeBlender = NULL;
00147 NodeBlend* BlendRecordHandler::m_pLastInsertedNodeBlend = NULL;
00148 NodeBlendPath* BlendRecordHandler::m_pLastNodeBlendPath = NULL;
00149 CProfileBiasGain BlendRecordHandler::m_LastObjectProfile;
00150 CProfileBiasGain BlendRecordHandler::m_LastAttrProfile;
00151 CProfileBiasGain BlendRecordHandler::m_LastPositionProfile;
00152 BOOL BlendRecordHandler::m_bLoadedProfiles = FALSE;
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 NodeBlend::NodeBlend(): NodeGroup()
00171 {
00172 ResetVars();
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 NodeBlend::NodeBlend(Node* ContextNode,
00220 AttachNodeDirection Direction,
00221 BOOL Locked,
00222 BOOL Mangled,
00223 BOOL Marked,
00224 BOOL Selected
00225 ):NodeGroup(ContextNode, Direction, Locked, Mangled, Marked,
00226 Selected)
00227 {
00228 ResetVars();
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 void NodeBlend::ResetVars()
00247 {
00248 m_NumBlendSteps = NUM_DEFAULT_BLENDSTEPS;
00249 m_OneToOne = FALSE;
00250 m_NotAntialiased = s_DefaultNotAntialiased;
00251 m_ColBlendType = COLOURBLEND_FADE;
00252 m_Tangential = FALSE;
00253 m_BlendedOnCurve = FALSE;
00254 m_Edit = EDIT_STEPS;
00255 m_DistanceEntered = -1;
00256 m_LastEdited = NONE;
00257 m_NumNodeBlendPaths = 0;
00258 objectProfileProcessing = FALSE;
00259 UpdateStepDistance();
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 String NodeBlend::Describe(BOOL Plural, BOOL Verbose)
00283 {
00284 if (Plural)
00285 return(String(_R(IDS_BLEND_DESCRP)));
00286 else
00287 return(String(_R(IDS_BLEND_DESCRS)));
00288 };
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309 Node* NodeBlend::SimpleCopy()
00310 {
00311 NodeBlend* pCopyOfNode = new NodeBlend();
00312 ERROR1IF(pCopyOfNode == NULL,NULL,_R(IDE_NOMORE_MEMORY));
00313 CopyNodeContents(pCopyOfNode);
00314 return (pCopyOfNode);
00315 }
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 void NodeBlend::CopyNodeContents(NodeBlend* pCopyOfNode)
00334 {
00335 NodeGroup::CopyNodeContents(pCopyOfNode);
00336
00337
00338 pCopyOfNode->m_NumBlendSteps = m_NumBlendSteps;
00339 pCopyOfNode->m_OneToOne = m_OneToOne;
00340 pCopyOfNode->m_NotAntialiased = m_NotAntialiased;
00341 pCopyOfNode->m_ColBlendType = m_ColBlendType;
00342 pCopyOfNode->m_Tangential = m_Tangential;
00343 pCopyOfNode->m_BlendedOnCurve = m_BlendedOnCurve;
00344 pCopyOfNode->m_Edit = m_Edit;
00345 pCopyOfNode->m_DistanceEntered = m_DistanceEntered;
00346 pCopyOfNode->m_NumNodeBlendPaths = m_NumNodeBlendPaths;
00347 pCopyOfNode->m_ObjectProfile = m_ObjectProfile;
00348 pCopyOfNode->m_AttrProfile = m_AttrProfile;
00349 pCopyOfNode->m_PositionProfile = m_PositionProfile;
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 void NodeBlend::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
00367 {
00368 ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node");
00369 ENSURE(IS_A(pNodeCopy, NodeBlend), "PolyCopyNodeContents given wrong dest node type");
00370
00371 if (IS_A(pNodeCopy, NodeBlend))
00372 CopyNodeContents((NodeBlend*)pNodeCopy);
00373 }
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392 UINT32 NodeBlend::GetNodeSize() const
00393 {
00394 return (sizeof(NodeBlend));
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 BOOL NodeBlend::OnClick( DocCoord PointerPos, ClickType Click, ClickModifiers ClickMods,
00415 Spread* pSpread )
00416 {
00417
00418 return FALSE;
00419 }
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 BOOL NodeBlend::HidingNode()
00435 {
00436
00437 if (!NodeGroup::HidingNode())
00438 return FALSE;
00439
00440 BOOL ok = TRUE;
00441 Node* pNode = FindFirstChild();
00442 while (pNode != NULL && ok)
00443 {
00444 ok = pNode->HidingNode();
00445 pNode = pNode->FindNext();
00446 }
00447
00448 return ok;
00449 }
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 BOOL NodeBlend::ShowingNode()
00465 {
00466
00467 if (!NodeGroup::ShowingNode())
00468 return FALSE;
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 return TRUE;
00482 }
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502 BOOL NodeBlend::DoBecomeA(BecomeA* pBecomeA)
00503 {
00504 if (!Reinit()) return FALSE;
00505
00506 switch (pBecomeA->GetReason())
00507 {
00508 case BECOMEA_REPLACE:
00509 {
00510
00511 UndoableOperation* pUndoOp = pBecomeA->GetUndoOp();
00512
00513
00514 if (pUndoOp)
00515 {
00516 if (!pUndoOp->DoLocaliseCommonAttributes(this))
00517 return FALSE;
00518 }
00519 else
00520 {
00521 if (!LocaliseCommonAttributes())
00522 return FALSE;
00523 }
00524
00525
00526 BOOL IsSelected = this->IsSelected();
00527 SetSelected(FALSE);
00528
00529
00530
00531
00532
00533
00534
00535 std::list<Node *> ListOfNodes;
00536
00537
00538 Node* pNode = FindFirstChild();
00539 while (pNode != NULL)
00540 {
00541 Node* pThisNode = pNode;
00542 pNode = pNode->FindNext();
00543
00544
00545
00546
00547 if (IS_A(pThisNode,NodeBlender))
00548 pThisNode->DoBecomeA(pBecomeA);
00549 else
00550 ListOfNodes.push_back(pThisNode);
00551 }
00552
00553 while( !ListOfNodes.empty() )
00554 {
00555
00556 pNode = ListOfNodes.back(); ListOfNodes.pop_back();
00557
00558
00559
00560
00561 if (!pNode->IsController ())
00562 {
00563 pNode->DoBecomeA(pBecomeA);
00564 }
00565 else
00566 {
00567
00568 if (pBecomeA->GetInsertComplexBlendStepsAsPaths ())
00569 {
00570 pNode->DoBecomeA(pBecomeA);
00571 }
00572 }
00573 }
00574
00575
00576
00577
00578
00579
00580
00581 NodeGroup* pNodeGroup;
00582 ALLOC_WITH_FAIL(pNodeGroup, (new NodeGroup), pUndoOp);
00583 if (pNodeGroup == NULL)
00584 return FALSE;
00585
00586
00587 if (pUndoOp)
00588 {
00589 if (!pUndoOp->DoInsertNewNode(pNodeGroup,this,NEXT,FALSE,FALSE,FALSE,FALSE))
00590 return FALSE;
00591 }
00592 else
00593 {
00594 pNodeGroup->AttachNode(this, NEXT);
00595 }
00596
00597
00598 if (IsSelected && pUndoOp)
00599 {
00600 if (!pUndoOp->DoSelectNode(pNodeGroup,FALSE))
00601 return FALSE;
00602 }
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613 BOOL ok = TRUE;
00614 BOOL bInEffectArea = FALSE;
00615 Node* pNextKid = NULL;
00616 Node* pThisKid = FindFirstChild();
00617 while (ok && pThisKid != NULL)
00618 {
00619 pNextKid = pThisKid->FindNext();
00620
00621 if (pThisKid->IsBounded())
00622 bInEffectArea = TRUE;
00623
00624
00625 if (pThisKid->IsAnObject())
00626 {
00627 if (pUndoOp)
00628 {
00629 CALL_WITH_FAIL(pUndoOp->DoMoveNode(pThisKid, pNodeGroup, LASTCHILD), pUndoOp, ok)
00630 }
00631 else
00632 {
00633 pThisKid->MoveNode(pNodeGroup, LASTCHILD);
00634 }
00635 }
00636
00637 else
00638 if (pThisKid->IsAnAttribute() &&
00639 (!((NodeAttribute*)pThisKid)->ShouldBeOptimized() ||
00640 bInEffectArea)
00641 )
00642 CALL_WITH_FAIL(pThisKid->CopyNode(pNodeGroup, LASTCHILD), pUndoOp, ok)
00643
00644 pThisKid = pNextKid;
00645 }
00646 if (!ok)
00647 return FALSE;
00648
00649
00650 NodeHidden* pNodeHidden;
00651 if (pUndoOp)
00652 {
00653 if(!pUndoOp->DoHideNode(this, FALSE, &pNodeHidden, FALSE))
00654 return FALSE;
00655 }
00656 else
00657 {
00658 CascadeDelete();
00659 delete this;
00660 }
00661
00662
00663 if (pUndoOp)
00664 {
00665 if (!pUndoOp->DoFactorOutCommonChildAttributes(pNodeGroup))
00666 return FALSE;
00667 }
00668 else
00669 {
00670 if (!pNodeGroup->FactorOutCommonChildAttributes())
00671 return FALSE;
00672 }
00673 }
00674 break;
00675
00676 case BECOMEA_PASSBACK:
00677
00678 {
00679
00680
00681
00682
00683 Node* pNode = FindFirstChild();
00684 while (pNode != NULL)
00685 {
00686 if (!pNode->DoBecomeA(pBecomeA))
00687 return FALSE;
00688
00689 pNode = pNode->FindNext();
00690 }
00691 }
00692 break;
00693
00694 default:
00695 ERROR3_PF(("Unknown BecomeA reason %d",pBecomeA->GetReason()));
00696 break;
00697 }
00698
00699 return TRUE;
00700 }
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716 void NodeBlend::SetNumBlendSteps(UINT32 NumSteps)
00717 {
00718 m_NumBlendSteps = NumSteps;
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735 UINT32 NodeBlend::GetNumBlendSteps()
00736 {
00737 return m_NumBlendSteps;
00738 }
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754 void NodeBlend::SetColourBlendType(ColourBlendType Type)
00755 {
00756 m_ColBlendType = Type;
00757 }
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773 ColourBlendType NodeBlend::GetColourBlendType()
00774 {
00775 return m_ColBlendType;
00776 }
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792 BOOL NodeBlend::IsOneToOne()
00793 {
00794 return m_OneToOne;
00795 }
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811 void NodeBlend::SetOneToOne(BOOL state)
00812 {
00813 m_OneToOne = state;
00814 }
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830 BOOL NodeBlend::IsNotAntialiased()
00831 {
00832 return m_NotAntialiased;
00833 }
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849 void NodeBlend::SetNotAntialiased(BOOL state)
00850 {
00851 m_NotAntialiased = state;
00852 s_DefaultNotAntialiased = state;
00853 }
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869 BOOL NodeBlend::IsTangential()
00870 {
00871 return m_Tangential;
00872 }
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888 void NodeBlend::SetTangential(BOOL state)
00889 {
00890 m_Tangential = state;
00891 }
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908 BOOL NodeBlend::IsOnACurve()
00909 {
00910 return m_BlendedOnCurve;
00911 }
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928 void NodeBlend::SetBlendedOnCurve(BOOL state)
00929 {
00930 m_BlendedOnCurve = state;
00931 }
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949 EditState NodeBlend::GetEditState()
00950 {
00951 return m_Edit;
00952
00953 }
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976 void NodeBlend::SetEditState(EditState State)
00977 {
00978 m_Edit = State;
00979 if (m_DistanceEntered == -1.0)
00980 {
00981
00982 UpdateStepDistance();
00983 m_DistanceEntered = GetStepDistance();
00984 }
00985 }
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002 BOOL NodeBlend::IsChildOfGroup()
01003 {
01004 Node* pParent = ((Node*)this)->FindParent(CC_RUNTIME_CLASS(NodeGroup));
01005 if (pParent == NULL)
01006 {
01007
01008 return FALSE;
01009 }
01010 return TRUE;
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021 }
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038 BOOL NodeBlend::ContainsBrushedNode()
01039 {
01040 Node* pNode = FindFirstChild();
01041 NodeAttribute* pAttr = NULL;
01042 while (pNode != NULL)
01043 {
01044 if (pNode->IsAnObject())
01045 {
01046 ((NodeRenderableInk*)pNode)->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBrushType), &pAttr);
01047 if (pAttr != NULL)
01048 {
01049 AttrBrushType* pAttrBrush = (AttrBrushType*)pAttr;
01050 if (pAttrBrush->GetBrushHandle() != BrushHandle_NoBrush)
01051 return TRUE;
01052 }
01053 }
01054 pNode = pNode->FindNext();
01055 }
01056 return FALSE;
01057 }
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073 UINT32 NodeBlend::GetNumBlenders()
01074 {
01075 UINT32 Count = 0;
01076 Node* pNode = FindFirstChild();
01077 while (pNode != NULL)
01078 {
01079 if (IS_A(pNode,NodeBlender)) Count++;
01080 pNode = pNode->FindNext();
01081 }
01082
01083 return Count;
01084 }
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100 BOOL NodeBlend::Reinit(BOOL ProgressBar)
01101 {
01102 Node* pNode = FindFirstChild();
01103 while (pNode != NULL)
01104 {
01105 if (IS_A(pNode,NodeBlender))
01106 {
01107 if (!((NodeBlender*)pNode)->Reinit(NULL,NULL,ProgressBar))
01108 return FALSE;
01109 }
01110 pNode = pNode->FindNext();
01111 }
01112
01113 return TRUE;
01114 }
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130 void NodeBlend::Deinit(BOOL bNodesMayBeChanged)
01131 {
01132 Node* pNode = FindFirstChild();
01133 while (pNode != NULL)
01134 {
01135 if (IS_A(pNode,NodeBlender))
01136 ((NodeBlender*)pNode)->Deinit(bNodesMayBeChanged);
01137
01138 pNode = pNode->FindNext();
01139 }
01140 }
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158 BOOL NodeBlend::PostImport()
01159 {
01160 Deinit();
01161 InvalidateBlendBoundingRect();
01162 return Reinit(FALSE);
01163 }
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179 void NodeBlend::InvalidateBlendBoundingRect()
01180 {
01181 Node* pNode = FindFirstChild();
01182 while (pNode != NULL)
01183 {
01184 if (pNode->IsBounded())
01185 ((NodeRenderableBounded*)pNode)->InvalidateBoundingRect();
01186
01187 pNode = pNode->FindNext();
01188 }
01189 }
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203 DocRect NodeBlend::GetBlobBoundingRect()
01204 {
01205 #if !defined(EXCLUDE_FROM_RALPH)
01206
01207 DocRect Rect = NodeGroup::GetBlobBoundingRect();
01208
01209
01210 DocRect TempRect;
01211 GetApplication()->GetBlobManager()->GetBlobRect(Rect.lo,&TempRect);
01212 INT32 Delta = ((TempRect.hi.x - TempRect.lo.x)*1)/1;
01213 Rect.Inflate(Delta);
01214
01215 return Rect;
01216 #else
01217 return DocRect(0,0,0,0);
01218 #endif
01219 }
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237 DocRect NodeBlend::GetBoundingRect(BOOL DontUseAttrs, BOOL HitTest)
01238 {
01239 if (IsBoundingRectValid && !DontUseAttrs)
01240 return BoundingRectangle;
01241
01242
01243
01244
01245
01246 return NodeGroup::GetBoundingRect(DontUseAttrs, HitTest);
01247 }
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260 void NodeBlend::RenderObjectBlobs(RenderRegion* pRegion)
01261 {
01262 #if !defined(EXCLUDE_FROM_RALPH)
01263
01264 DocRect BoundingRect = GetBoundingRect();
01265
01266
01267 DocRect TempRect;
01268 GetApplication()->GetBlobManager()->GetBlobRect(BoundingRect.lo,&TempRect);
01269 INT32 Delta = ((TempRect.hi.x - TempRect.lo.x)*3)/4;
01270 BoundingRect.Inflate(Delta);
01271
01272
01273 DocCoord Low = BoundingRect.LowCorner();
01274 DocCoord High = BoundingRect.HighCorner();
01275
01276
01277 pRegion->SetFillColour(COLOUR_UNSELECTEDBLOB);
01278 pRegion->SetLineColour(COLOUR_NONE);
01279
01280
01281 pRegion->DrawBlob(Low, BT_UNSELECTED);
01282 pRegion->DrawBlob(High, BT_UNSELECTED);
01283 pRegion->DrawBlob(DocCoord(Low.x, High.y), BT_UNSELECTED);
01284 pRegion->DrawBlob(DocCoord(High.x, Low.y), BT_UNSELECTED);
01285
01286
01287
01288
01289 #endif
01290 }
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309 void NodeBlend::RenderBlendBlobs(RenderRegion* pRender)
01310 {
01311 #if !defined(EXCLUDE_FROM_RALPH)
01312
01313
01314
01315
01316
01317
01318
01319 Node* pLast = NULL;
01320
01321
01322 Node* pNode = FindFirstChild();
01323 while (pNode != NULL)
01324 {
01325 if (IS_A(pNode,NodeBlender)) pLast = pNode;
01326 pNode = pNode->FindNext();
01327 }
01328
01329
01330 pNode = FindFirstChild();
01331
01332
01333
01334
01335 if (m_BlendedOnCurve == FALSE)
01336 {
01337 while (pNode != NULL)
01338 {
01339 if (IS_A(pNode,NodeBlender))
01340 {
01341 BOOL RenderStart = TRUE;
01342 BOOL RenderEnd = FALSE;
01343
01344 if (pNode == pLast) RenderEnd = TRUE;
01345
01346 ((NodeBlender*)pNode)->RenderBlendBlobs(pRender,RenderStart,RenderEnd);
01347 }
01348 pNode = pNode->FindNext();
01349 }
01350 }
01351 else
01352 RenderBlendOnCurveBlobs(pRender);
01353 #endif
01354 }
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374 void NodeBlend::RenderBlendOnCurveBlobs(RenderRegion* pRegion)
01375 {
01376 NodeBlender* pNodeBlender = FindFirstBlender();
01377
01378 while (pNodeBlender != NULL)
01379 {
01380 NodeBlender* pNextBlender = FindNextBlender(pNodeBlender);
01381 if (pNodeBlender->IsBlendedOnCurve())
01382 {
01383 Node* pStart = pNodeBlender->GetNodeStart();
01384 Node* pEnd = pNodeBlender->GetNodeEnd();
01385
01386 if (pStart == NULL || pEnd == NULL)
01387 {
01388 ERROR3("This blender has no start and end");
01389 return;
01390 }
01391 else
01392 {
01393 BOOL bFinish = FALSE;
01394 Node* pNodeToRender = pStart;
01395 DocCoord FirstPoint(0,0);
01396 while (bFinish == FALSE)
01397 {
01398
01399 if (pNodeToRender->IsABaseTextClass())
01400 {
01401 pRegion->SetLineColour(COLOUR_BEZIERBLOB);
01402 pRegion->SetFillColour(COLOUR_BEZIERBLOB);
01403 }
01404 else
01405 {
01406
01407 pRegion->SetLineColour(COLOUR_UNSELECTEDBLOB);
01408 pRegion->SetFillColour(COLOUR_UNSELECTEDBLOB);
01409 }
01410
01411
01412 DocRect BlobSize;
01413 BlobManager* pBlobMgr = GetApplication()->GetBlobManager();
01414 if (pBlobMgr != NULL)
01415 {
01416 DocRect BoundingRect = ((NodeRenderableBounded*)pNodeToRender)->GetBoundingRect();
01417 DocCoord Point = BoundingRect.Centre();
01418
01419
01420
01421 if (pNodeToRender == pStart)
01422 FirstPoint = Point;
01423 else
01424 {
01425
01426 double Distance = Point.Distance((Coord)FirstPoint);
01427 if (Distance < 10)
01428 break;
01429 }
01430 pBlobMgr->GetBlobRect(Point, &BlobSize);
01431
01432 if (pNodeToRender->IsABaseTextClass())
01433 {
01434 pRegion->DrawBlob(Point, BT_UNSELECTED);
01435 }
01436 else
01437 {
01438 pRegion->DrawLine(DocCoord(BlobSize.hi.x, BlobSize.hi.y), DocCoord(BlobSize.lo.x, BlobSize.lo.y));
01439 pRegion->DrawLine(DocCoord(BlobSize.lo.x, BlobSize.hi.y), DocCoord(BlobSize.hi.x, BlobSize.lo.y));
01440 pRegion->DrawPixel(DocCoord(BlobSize.hi.x, BlobSize.lo.y));
01441 pRegion->DrawPixel(DocCoord(BlobSize.lo.x, BlobSize.lo.y));
01442 }
01443 }
01444 if (pNodeToRender == pStart && pNextBlender == NULL)
01445 pNodeToRender = pEnd;
01446 else
01447 bFinish = TRUE;
01448 }
01449 }
01450 }
01451 pNodeBlender = pNextBlender;
01452 }
01453 return;
01454 }
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
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
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570 BOOL NodeBlend::IsPointOverBlob(DocCoord* pPointerPos,
01571 BlendPath** ppBlendPath,
01572 INT32* pIndex,
01573 BOOL* pAStart,
01574 UINT32* pRemapRef)
01575 {
01576 if (pPointerPos == NULL)
01577 return FALSE;
01578
01579 #if !defined(EXCLUDE_FROM_RALPH)
01580 BOOL Found = FALSE;
01581 Node* pNode = FindFirstChild();
01582 while (pNode != NULL && !Found)
01583 {
01584 if (IS_A(pNode,NodeBlender))
01585 {
01586 Found = ((NodeBlender*)pNode)->IsPointOverBlob(pPointerPos,ppBlendPath,pIndex,pAStart);
01587 if (Found) *pRemapRef = pNode->GetTag();
01588 }
01589 pNode = pNode->FindNext();
01590 }
01591
01592 return Found;
01593 #else
01594 return FALSE;
01595 #endif
01596 }
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620 BOOL NodeBlend::Remap(UINT32 RemapRef,DocCoord PosStart,DocCoord PosEnd,DocCoord* pInvPosStart,DocCoord* pInvPosEnd)
01621 {
01622 BOOL Mapped = FALSE;
01623 Node* pNode = FindFirstChild();
01624 while (pNode != NULL && !Mapped)
01625 {
01626 if (pNode->GetTag() == RemapRef && IS_A(pNode,NodeBlender))
01627 Mapped = ((NodeBlender*)pNode)->Remap(PosStart,PosEnd,pInvPosStart,pInvPosEnd);
01628 pNode = pNode->FindNext();
01629 }
01630
01631 return Mapped;
01632 }
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655 void NodeBlend::PreExportRender(RenderRegion* pRegion)
01656 {
01657 #ifdef DO_EXPORT
01658 if (IS_A(pRegion, CamelotEPSRenderRegion))
01659
01660 return;
01661
01662 if (pRegion->IS_KIND_OF(ArtWorksEPSRenderRegion))
01663 {
01664 EPSExportDC *pDC = (EPSExportDC *) pRegion->GetRenderDC();
01665
01666 if (pRegion->IS_KIND_OF(CamelotEPSRenderRegion))
01667 {
01668
01669 pDC->OutputValue(INT32(0));
01670 pDC->OutputValue(INT32(0));
01671 pDC->OutputValue(INT32(0));
01672 pDC->OutputValue(INT32(m_ColBlendType));
01673 pDC->OutputValue(INT32(m_OneToOne));
01674 pDC->OutputValue(INT32(m_NotAntialiased));
01675 pDC->OutputValue(INT32(m_NumBlendSteps));
01676 pDC->OutputValue(INT32(1));
01677 pDC->OutputToken(_T("csbd"));
01678 pDC->OutputNewLine();
01679 }
01680 else
01681 {
01682
01683
01684
01685 m_AWEPSCompatibleCache = FALSE;
01686
01687 if (IsArtWorksEPSCompatible())
01688 {
01689
01690 pDC->OutputValue(INT32(1));
01691 pDC->OutputValue(INT32(0));
01692 pDC->OutputValue(GetNumInkObjects());
01693 pDC->OutputToken(_T("asbd"));
01694 pDC->OutputNewLine();
01695 }
01696 }
01697 }
01698 #endif
01699 }
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717 BOOL NodeBlend::ExportRender(RenderRegion* pRegion)
01718 {
01719 #ifdef DO_EXPORT
01720 if (IS_A(pRegion, CamelotEPSRenderRegion))
01721
01722 return FALSE;
01723
01724 if (pRegion->IS_KIND_OF(ArtWorksEPSRenderRegion))
01725 {
01726 EPSExportDC *pDC = (EPSExportDC *) pRegion->GetRenderDC();
01727
01728 if (pRegion->IS_KIND_OF(CamelotEPSRenderRegion))
01729 {
01730 pDC->OutputToken(_T("cebd"));
01731 pDC->OutputNewLine();
01732 }
01733 else if (IsArtWorksEPSCompatible())
01734 {
01735 pDC->OutputToken(_T("aebd"));
01736 pDC->OutputNewLine();
01737 }
01738
01739 return TRUE;
01740 }
01741 #endif
01742
01743 return FALSE;
01744 }
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771 BOOL NodeBlend::IsArtWorksEPSCompatible()
01772 {
01773 if (!m_AWEPSCompatibleCache)
01774 {
01775 m_AWEPSCompatible = (m_ColBlendType == COLOURBLEND_FADE);
01776 Node* pNode = FindFirstChild();
01777
01778 while (pNode != NULL && m_AWEPSCompatible)
01779 {
01780 if (IS_A(pNode,NodeBlender))
01781 m_AWEPSCompatible = ((NodeBlender*)pNode)->IsArtWorksEPSCompatible();
01782
01783 pNode = pNode->FindNext();
01784 }
01785
01786 m_AWEPSCompatibleCache = TRUE;
01787 }
01788
01789 return m_AWEPSCompatible;
01790 }
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806 INT32 NodeBlend::GetNumInkObjects()
01807 {
01808 INT32 Count = 0;
01809 Node* pNode = FindFirstChild();
01810
01811 while (pNode != NULL)
01812 {
01813 if (!IS_A(pNode,NodeBlender) && pNode->IS_KIND_OF(NodeRenderableInk))
01814 Count++;
01815
01816 pNode = pNode->FindNext();
01817 }
01818
01819 return Count;
01820 }
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851 BOOL NodeBlend::AllowOp(ObjChangeParam* pParam, BOOL SetOpPermissionState,
01852 BOOL DoPreTriggerEdit)
01853 {
01854 ERROR2IF(pParam==NULL,FALSE,"NodeBlend::AllowOp() - pParam==NULL");
01855
01856
01857 pParam->SetCallingChild(NULL);
01858
01859
01860 BOOL allowed=TRUE;
01861 ObjChangeFlags Flags=pParam->GetChangeFlags();
01862 if (pParam->GetDirection()==OBJCHANGE_CALLEDBYCHILD)
01863 {
01864 if (Flags.DeleteNode || Flags.MultiReplaceNode || Flags.MoveNode)
01865 {
01866 pParam->SetReasonForDenial(_R(IDS_BLEND_CANT_OP_ON_CHILDREN));
01867 allowed=FALSE;
01868 }
01869 }
01870
01871
01872 if (allowed && pParam->GetDirection()!=OBJCHANGE_CALLEDBYPARENT && Parent!=NULL)
01873 {
01874 ObjChangeDirection OldDirection=pParam->GetDirection();
01875 pParam->SetCallingChild(this);
01876 pParam->SetDirection(OBJCHANGE_CALLEDBYCHILD);
01877 allowed=Parent->AllowOp(pParam,SetOpPermissionState,DoPreTriggerEdit);
01878 pParam->SetDirection(OldDirection);
01879 }
01880
01881 if (allowed && pParam->GetDirection() == OBJCHANGE_CALLEDBYCHILD)
01882 {
01883
01884
01885 UndoableOperation* pChangeOp = pParam->GetOpPointer();
01886 BOOL InformGeomLinkedAttrs = SetOpPermissionState && pChangeOp && pChangeOp->MayChangeNodeBounds();
01887 if(InformGeomLinkedAttrs)
01888 {
01889 NodeAttribute* pNA = FindFirstGeometryLinkedAttr();
01890 while(pNA)
01891 {
01892 pNA->LinkedNodeGeometryHasChanged(pChangeOp);
01893 pNA = pNA->FindNextGeometryLinkedAttr();
01894 }
01895 }
01896 }
01897
01898
01899 if (SetOpPermissionState)
01900 {
01901 if (allowed)
01902 {
01903 if (Parent!=NULL)
01904 Parent->SetOpPermission(PERMISSION_ALLOWED);
01905
01906
01907
01908 if (pParam->GetDirection()==OBJCHANGE_CALLEDBYCHILD || Flags.Attribute || Flags.RegenerateNode)
01909 {
01910 SetOpPermission(PERMISSION_ALLOWED);
01911 UndoableOperation* pOp=pParam->GetOpPointer();
01912 if (pOp!=NULL)
01913 {
01914 if (allowed) allowed=(InitBlendAction::Init(pOp,pOp->GetUndoActionList(),this)!=AC_FAIL);
01915 if (allowed) allowed=pOp->DoInvalidateNodeRegion(this, TRUE, FALSE, FALSE, !pParam->GetRetainCachedData());
01916 }
01917 }
01918 }
01919 else
01920 SetOpPermission(PERMISSION_DENIED,TRUE);
01921 }
01922
01923
01924
01925 if (allowed && pParam->GetDirection()!=OBJCHANGE_CALLEDBYCHILD)
01926 AllowOp_AccountForCompound(pParam, SetOpPermissionState, DoPreTriggerEdit);
01927
01928 if (allowed && Flags.Attribute && SetOpPermissionState)
01929 Deinit();
01930
01931
01932
01933
01934 if (allowed && DoPreTriggerEdit)
01935 {
01936
01937 UndoableOperation* pChangeOp = pParam->GetOpPointer();
01938 if (pChangeOp != NULL && pChangeOp->MayChangeNodeBounds())
01939 {
01940 if (NameGallery::Instance())
01941 allowed = NameGallery::Instance()->PreTriggerEdit(pChangeOp, pParam, this);
01942 }
01943 }
01944
01945
01946 return allowed;
01947 }
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970 ChangeCode NodeBlend::OnChildChange(ObjChangeParam* pParam)
01971 {
01972 ERROR2IF(pParam == NULL,CC_FAIL,"pParam == NULL");
01973
01974 ObjChangeType cType = pParam->GetChangeType();
01975 ObjChangeFlags cFlags = pParam->GetChangeFlags();
01976
01977 if (cType == OBJCHANGE_FINISHED)
01978 {
01979 UndoableOperation* pUndoOp = pParam->GetOpPointer();
01980
01981
01982 UINT32 NBPCounter = 0;
01983 NodeBlendPath* pNodeBlendPath = GetNodeBlendPath(NBPCounter++);
01984
01985
01986
01987
01988
01989
01990 while (pNodeBlendPath != NULL)
01991 {
01992 pNodeBlendPath->OnEdited(pParam);
01993 if (!TransformBlendEndObjects(pUndoOp))
01994 return CC_FAIL;
01995 pNodeBlendPath = GetNodeBlendPath(NBPCounter++);
01996 }
01997
01998 if (pUndoOp != NULL)
01999 {
02000 if (InitBlendAction::Init(pUndoOp,pUndoOp->GetUndoActionList(),this, FALSE, FALSE, cFlags.RegenerateNode) == AC_FAIL)
02001 return CC_FAIL;
02002
02003 if (!pUndoOp->DoInvalidateNodeRegion(this, TRUE, FALSE, FALSE, !pParam->GetRetainCachedData()))
02004 return CC_FAIL;
02005 }
02006 else
02007 {
02008
02009 InvalidateBlendBoundingRect();
02010 Deinit(cFlags.RegenerateNode);
02011
02012 DocRect rect = GetUnionBlobBoundingRect();
02013 Document* pDoc = (Document*)FindOwnerDoc();
02014 Spread* pSpread = FindParentSpread();
02015 if (pDoc != NULL && pSpread != NULL && pDoc->IS_KIND_OF(Document))
02016 pDoc->ForceRedraw(pSpread, rect, FALSE, this);
02017 }
02018
02019
02020 }
02021
02022 return CC_OK;
02023 }
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041 BOOL NodeBlend::OnNodePopUp(Spread* pSpread, DocCoord PointerPos, ContextMenu* pMenu)
02042 {
02043
02044 #ifndef WEBSTER
02045
02046 #if !defined(EXCLUDE_FROM_RALPH)
02047 BOOL ok = TRUE;
02048
02049 ok = ok && pMenu->BuildCommand(TOOL_OPTOKEN_BLEND, TRUE);
02050
02051
02052
02053
02054
02055 return ok;
02056 #else
02057 return FALSE;
02058 #endif
02059
02060 #else //webster
02061 return FALSE;
02062
02063 #endif //webster
02064 }
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078 NodeBlendPath* NodeBlend::GetNodeBlendPath(UINT32 Index)
02079 {
02080 Node* pNode = FindFirstChild();
02081 UINT32 NBPCounter = 0;
02082 while (pNode)
02083 {
02084 if (IS_A(pNode,NodeBlendPath))
02085 {
02086
02087 if (NBPCounter == Index)
02088 return (NodeBlendPath*)pNode;
02089
02090 NBPCounter++;
02091 }
02092
02093 pNode = pNode->FindNext();
02094 }
02095
02096 return NULL;
02097 }
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117 BOOL NodeBlend::BlendAlongThisPath(NodePath* pNodePath,CCAttrMap* pAttrMap,UndoableOperation* pUndoOp, BOOL BlendPathOnTop)
02118 {
02119 ERROR2IF(pUndoOp == NULL,FALSE,"I need an undoable op to perform this task");
02120 ERROR2IF(pNodePath == NULL,FALSE,"Er, where is the path then?");
02121
02122 BOOL ok = TRUE;
02123
02124 NodeBlendPath* pNodeBlendPath = GetNodeBlendPath(0);
02125 if (pNodeBlendPath != NULL)
02126 ok = pUndoOp->DoHideNode(pNodeBlendPath,TRUE);
02127
02128 if (ok) pNodeBlendPath = new NodeBlendPath();
02129 if (ok) ok = (pNodeBlendPath != NULL);
02130 if (ok) ok = pNodeBlendPath->CopyNodePath(pNodePath);
02131 if (ok) ok = pUndoOp->DoLocaliseCommonAttributes(this);
02132
02133 if (ok)
02134 {
02135 if (BlendPathOnTop)
02136 ok = pUndoOp->DoInsertNewNode(pNodeBlendPath,this,LASTCHILD,FALSE,FALSE,FALSE,FALSE);
02137 else
02138 ok = pUndoOp->DoInsertNewNode(pNodeBlendPath,this,FIRSTCHILD,FALSE,FALSE,FALSE,FALSE);
02139 }
02140
02141 if (ok) ok = pNodeBlendPath->ApplyAttributes(pAttrMap);
02142 if (ok) ok = pUndoOp->DoFactorOutCommonChildAttributes(this);
02143
02144 if (ok) ok = InitBlenderPathProportions(pUndoOp);
02145 if (ok) ok = TransformBlendEndObjects(pUndoOp);
02146
02147
02148
02149
02150
02151
02152 return ok;
02153 }
02154
02155 BOOL NodeBlend::InitBlenderPathProportions(UndoableOperation* pUndoOp)
02156 {
02157 BOOL ok = TRUE;
02158
02159 UINT32 NumBlenders = GetNumBlenders();
02160 UINT32 CurBlender = 0;
02161 double CurProp = 0.0;
02162 double PropIncrement = 1.0 / NumBlenders;
02163 NodeBlender* pNodeBlender = FindFirstBlender();
02164 while (ok && pNodeBlender != NULL)
02165 {
02166 CurBlender++;
02167 pNodeBlender->SetBlendedOnCurve(TRUE);
02168 pNodeBlender->SetProportionOfPathDistStart(CurProp);
02169 CurProp += PropIncrement;
02170 pNodeBlender->SetProportionOfPathDistEnd(CurProp);
02171 pNodeBlender = FindNextBlender(pNodeBlender);
02172
02173 }
02174
02175 return ok;
02176 }
02177
02178 BOOL NodeBlend::RotateBlendEndObjectsBack(UndoableOperation* pUndoOp)
02179 {
02180 BOOL ok = TRUE;
02181
02182 Node* pLast = NULL;
02183 NodeBlender* pNodeBlender = FindFirstBlender();
02184 while (ok && pNodeBlender != NULL)
02185 {
02186 NodeRenderableInk* pStart = pNodeBlender->GetNodeStart();
02187 NodeRenderableInk* pEnd = pNodeBlender->GetNodeEnd();
02188
02189 if (pStart && pStart != pLast)
02190 {
02191 double AngleChange = -pNodeBlender->GetAngleStart();
02192 ok = TransformNodeToPoint(pStart,NULL,pUndoOp,AngleChange);
02193 if (ok && pUndoOp && AngleChange != 0.0)
02194 {
02195 ChangeBlenderOpParam ChangeParam(CHANGEBLENDER_ANGLESTART);
02196 ChangeParam.m_NewAngleStart = 0.0;
02197 ActionCode Ac = ChangeBlenderAction::Init( pUndoOp,pUndoOp->GetUndoActionList(),
02198 pNodeBlender,ChangeParam);
02199 ok = (Ac !=AC_FAIL);
02200 }
02201 }
02202
02203 if (pEnd && ok)
02204 {
02205 double AngleChange = -pNodeBlender->GetAngleEnd();
02206 ok = TransformNodeToPoint(pEnd,NULL,pUndoOp,AngleChange);
02207 if (ok && pUndoOp && AngleChange != 0.0)
02208 {
02209 ChangeBlenderOpParam ChangeParam(CHANGEBLENDER_ANGLEEND);
02210 ChangeParam.m_NewAngleEnd = 0.0;
02211 ActionCode Ac = ChangeBlenderAction::Init( pUndoOp,pUndoOp->GetUndoActionList(),
02212 pNodeBlender,ChangeParam);
02213 ok = (Ac !=AC_FAIL);
02214 }
02215 pLast = pEnd;
02216 }
02217
02218 pNodeBlender = FindNextBlender(pNodeBlender);
02219 }
02220
02221 return ok;
02222 }
02223
02224 BOOL NodeBlend::TransformBlendEndObjects(UndoableOperation* pUndoOp)
02225 {
02226 BOOL ok = TRUE;
02227
02228 Node* pLast = NULL;
02229 NodeBlender* pNodeBlender = FindFirstBlender();
02230 while (ok && pNodeBlender != NULL)
02231 {
02232 NodeRenderableInk* pStart = pNodeBlender->GetNodeStart();
02233 NodeRenderableInk* pEnd = pNodeBlender->GetNodeEnd();
02234 ERROR3IF(pStart == NULL,"No start node");
02235 ERROR3IF(pEnd == NULL,"No end node");
02236
02237 if ((pStart == NULL) || (pEnd == NULL)) { return (FALSE); }
02238
02239
02240 DocCoord Point;
02241 double Angle = 0.0;
02242 if (pStart && pStart != pLast)
02243 {
02244 if (pNodeBlender->GetPointOnNodeBlendPath(0.0,&Point,&Angle))
02245 {
02246 double AngleStart = pNodeBlender->GetAngleStart();
02247 double AngleChange = Angle - AngleStart;
02248 ok = TransformNodeToPoint(pStart,&Point,pUndoOp,AngleChange);
02249 if (ok && pUndoOp && AngleChange != 0.0)
02250 {
02251 ChangeBlenderOpParam ChangeParam(CHANGEBLENDER_ANGLESTART);
02252 ChangeParam.m_NewAngleStart = AngleStart + AngleChange;
02253 ActionCode Ac = ChangeBlenderAction::Init( pUndoOp,pUndoOp->GetUndoActionList(),
02254 pNodeBlender,ChangeParam);
02255 ok = (Ac !=AC_FAIL);
02256 }
02257 }
02258 }
02259
02260 if (pEnd && ok)
02261 {
02262 if (pNodeBlender->GetPointOnNodeBlendPath(1.0,&Point,&Angle))
02263 {
02264 double AngleEnd = pNodeBlender->GetAngleEnd();
02265 double AngleChange = Angle - AngleEnd;
02266 ok = TransformNodeToPoint(pEnd,&Point,pUndoOp,AngleChange);
02267
02268 ERROR3IF (!ok, "one does not find this amusing!");
02269
02270 if (ok && pUndoOp && AngleChange != 0.0)
02271 {
02272 ChangeBlenderOpParam ChangeParam(CHANGEBLENDER_ANGLEEND);
02273 ChangeParam.m_NewAngleEnd = AngleEnd + AngleChange;
02274 ActionCode Ac = ChangeBlenderAction::Init( pUndoOp,pUndoOp->GetUndoActionList(),
02275 pNodeBlender,ChangeParam);
02276 ok = (Ac !=AC_FAIL);
02277 }
02278 }
02279 pLast = pEnd;
02280 }
02281
02282 pNodeBlender = FindNextBlender(pNodeBlender);
02283 }
02284
02285 return ok;
02286 }
02287
02288 BOOL NodeBlend::TransformNodeToPoint(NodeRenderableInk* pNode,DocCoord* pPoint,UndoableOperation* pUndoOp,double Angle)
02289 {
02290 ERROR2IF(pNode == NULL,FALSE,"Null node ptr");
02291
02292 BOOL ok = TRUE;
02293
02294
02295
02296 pNode->InvalidateBoundingRect(TRUE);
02297 DocRect Rect = pNode->GetBoundingRect();
02298
02299
02300 DocCoord centre = Rect.Centre();
02301
02302 INT32 dx = 0;
02303 INT32 dy = 0;
02304 if (pPoint)
02305 {
02306 dx = pPoint->x - centre.x;
02307 dy = pPoint->y - centre.y;
02308 }
02309
02310 if (pUndoOp)
02311 {
02312
02313 if (Angle != 0.0)
02314 {
02315 Trans2DMatrix* pRotate = new Trans2DMatrix(centre,Angle);
02316 if (ok)
02317 {
02318 RangeControl rc(TRUE,TRUE);
02319 rc.SiblingsOnly = TRUE;
02320
02321 Range r(pNode,pNode, rc);
02322 ok = pUndoOp->DoTransformNodes(r,pRotate);
02323 }
02324 }
02325
02326 if (dx != 0 || dy != 0)
02327 {
02328 Trans2DMatrix* pTrans = new Trans2DMatrix(dx,dy);
02329 if (ok)
02330 {
02331 RangeControl rc(TRUE,TRUE);
02332 rc.SiblingsOnly = TRUE;
02333
02334 Range r(pNode,pNode, rc);
02335 ok = pUndoOp->DoTransformNodes(r,pTrans);
02336 }
02337
02338 }
02339 }
02340 else
02341 {
02342
02343 if (Angle != 0.0)
02344 {
02345 Trans2DMatrix Rotate(centre,Angle);
02346 pNode->Transform(Rotate);
02347 }
02348
02349 if (dx != 0 || dy != 0)
02350 {
02351 Trans2DMatrix Trans(dx,dy);
02352 pNode->Transform(Trans);
02353 }
02354 }
02355
02356 return ok;
02357 }
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372 BOOL NodeBlend::DetachNodeBlendPath(Node* pContextNode, AttachNodeDirection AttDir,UndoableOperation* pUndoOp)
02373 {
02374 ERROR2IF(pContextNode == NULL,FALSE,"NULL pContextNode");
02375 ERROR2IF(pUndoOp == NULL,FALSE,"NULL pUndoOp");
02376
02377 BOOL ok = TRUE;
02378 UINT32 NBPCounter = 0;
02379 NodeBlendPath* pNodeBlendPath = GetNodeBlendPath(NBPCounter++);
02380 while (pNodeBlendPath != NULL)
02381 {
02382 NodePath* pNodePath = pNodeBlendPath->CreateNodePathCopy();
02383 if (pNodePath != NULL)
02384 {
02385 CCAttrMap* pAttrMap = new CCAttrMap(30);
02386 ok = (pAttrMap != NULL);
02387 if (ok) ok = pNodeBlendPath->FindAppliedAttributes(pAttrMap);
02388 if (ok) ok = pUndoOp->DoInsertNewNode(pNodePath,pContextNode,AttDir,FALSE,FALSE,FALSE,FALSE);
02389 if (ok) ok = pUndoOp->DoHideNode(pNodeBlendPath,TRUE);
02390 if (ok) ok = pUndoOp->DoSelectNode(pNodePath);
02391 if (ok) pNodePath->ApplyAttributes(pAttrMap,TRUE);
02392
02393 if (pAttrMap != NULL)
02394 {
02395 delete pAttrMap;
02396 pAttrMap = NULL;
02397 }
02398 }
02399
02400
02401 NodeBlender* pBlender = FindFirstBlender();
02402 while (pBlender != NULL)
02403 {
02404 pBlender->SetNodeBlendPathIndex(-1);
02405 pBlender = FindNextBlender(pBlender);
02406
02407 }
02408 pNodeBlendPath = GetNodeBlendPath(NBPCounter++);
02409 }
02410 return ok;
02411 }
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428 NodeBlender* NodeBlend::FindFirstBlender()
02429 {
02430 Node* pNode = FindFirstChild();
02431 while (pNode != NULL)
02432 {
02433 if (IS_A(pNode,NodeBlender))
02434 return ((NodeBlender*)pNode);
02435
02436 pNode = pNode->FindNext();
02437 }
02438
02439 return NULL;
02440 }
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458 NodeBlender* NodeBlend::FindNextBlender(NodeBlender* pNodeBlender)
02459 {
02460 if (pNodeBlender)
02461 {
02462 Node* pNode = pNodeBlender->FindNext();
02463
02464 while (pNode != NULL)
02465 {
02466 if (IS_A(pNode,NodeBlender))
02467 return ((NodeBlender*)pNode);
02468
02469 pNode = pNode->FindNext();
02470 }
02471 }
02472
02473 return NULL;
02474 }
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492 NodeBlender* NodeBlend::FindLastBlender()
02493 {
02494 Node* pNode = FindLastChild();
02495 while (pNode != NULL)
02496 {
02497 if (pNode->IS_KIND_OF(NodeBlender))
02498 {
02499 return (NodeBlender*)pNode;
02500 }
02501 pNode = pNode->FindPrevious();
02502 }
02503 return NULL;
02504
02505 }
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521
02522 BOOL NodeBlend::FindFirstAndLastBlenders(NodeBlender** ppFirstBlender, NodeBlender** ppLastBlender)
02523 {
02524 NodeBlender* pTempBlender = FindFirstBlender();
02525 if (pTempBlender == NULL)
02526 return FALSE;
02527 else
02528 *ppFirstBlender = pTempBlender;
02529
02530 pTempBlender = NULL;
02531 pTempBlender = FindLastBlender();
02532 if (pTempBlender == NULL)
02533 return FALSE;
02534
02535 *ppLastBlender = pTempBlender;
02536
02537 return TRUE;
02538 }
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559 Node* NodeBlend::HasEditableChild(CCRuntimeClass* ChildClass, Node* pPreviousChild)
02560 {
02561 if (ChildClass != CC_RUNTIME_CLASS(NodePath))
02562 return NULL;
02563
02564 NodeBlendPath* pNodeBlendPath = GetNodeBlendPath(0);
02565
02566 if (((Node*)pNodeBlendPath) == pPreviousChild)
02567 return NULL;
02568
02569 return pNodeBlendPath;
02570 }
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586 BOOL NodeBlend::GetBlendDistance( BOOL FullDistance, double* Distance)
02587 {
02588 NodeBlender* pBlender = FindFirstBlender();
02589 double TempDistance = 0.0;
02590
02591 while (pBlender != NULL)
02592 {
02593 if (pBlender->IsBlendedOnCurve())
02594 {
02595 NodeBlendPath* pPath = pBlender->GetNodeBlendPath();
02596 if (pPath == NULL)
02597 return FALSE;
02598
02599 double PathDistance = pPath->GetPathLength();
02600 double StartProportion = 0.0;
02601 double EndProportion = 1.0;
02602
02603 if (FullDistance ==FALSE)
02604 {
02605
02606
02607
02608 StartProportion = pBlender->GetProportionOfPathDistStart();
02609 EndProportion = pBlender->GetProportionOfPathDistEnd();
02610 }
02611
02612 TempDistance += (PathDistance * (EndProportion - StartProportion));
02613
02614 }
02615 else
02616 {
02617 TempDistance += pBlender->GetLinearDistance();
02618 }
02619 pBlender = FindNextBlender(pBlender);
02620 }
02621
02622 ERROR2IF((TempDistance < 0), FALSE, "Negative path length");
02623
02624 *Distance = TempDistance;
02625 return TRUE;
02626 }
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643 BOOL NodeBlend::GetNumStepsFromDistance(double Distance, UINT32* NumSteps)
02644 {
02645 ASSERT(Distance);
02646 double BlendLength = 0.0;
02647 BOOL Valid = GetBlendDistance(TRUE, &BlendLength);
02648
02649 if (!Valid)
02650 return FALSE;
02651
02652 UINT32 TempNumSteps = (UINT32)(BlendLength / Distance);
02653
02654 ERROR3IF((TempNumSteps < 0), "Negative number of blend steps");
02655 *NumSteps = TempNumSteps;
02656 return TRUE;
02657 }
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671
02672
02673 double NodeBlend::GetStepDistance()
02674 {
02675 double BlendLength = 0.0;
02676 GetBlendDistance(FALSE, &BlendLength);
02677
02678 double StepDistance = BlendLength/m_NumBlendSteps;
02679
02680 ERROR2IF((StepDistance < 0), 0, "Negative step distance");
02681 return StepDistance;
02682 }
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697 void NodeBlend::UpdateStepDistance()
02698 {
02699 double BlendLength = 0.0;
02700 GetBlendDistance(FALSE, &BlendLength);
02701
02702 m_StepDistance = BlendLength/m_NumBlendSteps;
02703 }
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722 double NodeBlend::GetDistanceEntered()
02723 {
02724 return m_DistanceEntered;
02725 }
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740 void NodeBlend::SetDistanceEntered(double Distance)
02741 {
02742 m_DistanceEntered = Distance;
02743 }
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759 EndObject NodeBlend::GetLastEdited()
02760 {
02761 return m_LastEdited;
02762 }
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775
02776
02777 void NodeBlend::SetLastEdited(EndObject LastEdited)
02778 {
02779 m_LastEdited = LastEdited;
02780 }
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796 UINT32 NodeBlend::GetNumNodeBlendPaths()
02797 {
02798 UINT32 NBPCounter = 0;
02799 Node* pNode = FindFirstChild();
02800 while (pNode != NULL)
02801 {
02802 if (pNode->IS_KIND_OF(NodeBlendPath))
02803 NBPCounter++;
02804 pNode = pNode->FindNext();
02805 }
02806
02807 return NBPCounter;
02808 }
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821
02822
02823
02824
02825 void NodeBlend::SetNumNodeBlendPathsInc(BOOL Increase)
02826 {
02827 if (Increase)
02828 m_NumNodeBlendPaths++;
02829 else
02830 {
02831 if (m_NumNodeBlendPaths == 0)
02832 {
02833 ERROR3("Blend has no nodeblend paths");
02834 return;
02835 }
02836 m_NumNodeBlendPaths--;
02837 }
02838 }
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855 void NodeBlend::SetNumNodeBlendPaths(INT32 Index)
02856 {
02857 if (Index < 0)
02858 {
02859 ERROR3("Index is less than zero");
02860 return;
02861 }
02862 else
02863 m_NumNodeBlendPaths = Index;
02864 }
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878
02879
02880
02881
02882 BOOL NodeBlend::GetStartAndEndProportions(double *StartProp, double* EndProp)
02883 {
02884 if (m_BlendedOnCurve == FALSE)
02885 {
02886 ERROR3("Blend is not on a curve");
02887 return FALSE;
02888 }
02889 NodeBlender* pNodeBlender = FindFirstBlender();
02890
02891 if (pNodeBlender == NULL)
02892 {
02893 ERROR3("Can't find first blender");
02894 return FALSE;
02895 }
02896
02897 double TempStartProp = pNodeBlender->GetProportionOfPathDistStart();
02898
02899 if (TempStartProp < 0.0 || TempStartProp > 1.0)
02900 {
02901 ERROR3("Invalid value for start proportion");
02902 return FALSE;
02903 }
02904
02905 double TempEndProp = 1.0;
02906
02907 while (pNodeBlender != NULL)
02908 {
02909 TempEndProp = pNodeBlender->GetProportionOfPathDistEnd();
02910 pNodeBlender = FindNextBlender(pNodeBlender);
02911 }
02912
02913 if (TempEndProp < 0.0 || TempEndProp > 1.0)
02914 {
02915 ERROR3("Invalid value for end proportion");
02916 return FALSE;
02917 }
02918
02919 *StartProp = TempStartProp;
02920 *EndProp = TempEndProp;
02921 return TRUE;
02922 }
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938 BOOL NodeBlend::GetStartAndEndNodes(Node** ppStart, Node** ppEnd)
02939 {
02940
02941 NodeBlender* pFirstBlender = FindFirstBlender();
02942 if (pFirstBlender == NULL)
02943 {
02944 ERROR3("No first blender");
02945 return FALSE;
02946 }
02947
02948 *ppStart = pFirstBlender->GetNodeStart();
02949 if (*ppStart == NULL)
02950 {
02951 ERROR3("No start node");
02952 return FALSE;
02953 }
02954
02955
02956 NodeBlender* pLastBlender = FindLastBlender();
02957 if (pLastBlender == NULL)
02958 {
02959 ERROR3("No last blender");
02960 return FALSE;
02961 }
02962
02963 *ppEnd = pLastBlender->GetNodeEnd();
02964 if (*ppEnd == NULL)
02965 {
02966 ERROR3("No last node");
02967 return FALSE;
02968 }
02969
02970 return TRUE;
02971 }
02972
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986 BOOL NodeBlend::NonLinearObjectProfile()
02987 {
02988 if (m_ObjectProfile.GetBias() != 0.0)
02989 return TRUE;
02990 if (m_ObjectProfile.GetGain() != 0.0)
02991 return TRUE;
02992 return FALSE;
02993 }
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010 BOOL NodeBlend::HitOnEndDragBlob(DocCoord Point, Node** ppHitNode)
03011 {
03012
03013 NodeBlender* pBlender = FindFirstBlender();
03014 BOOL ok = FALSE;
03015 while (pBlender != NULL)
03016 {
03017 FindNextBlender(pBlender);
03018
03019 if (pBlender->IsBlendedOnCurve())
03020 {
03021 Node* pFirstNode = pBlender->GetNodeStart();
03022 Node* pLastNode = pBlender->GetNodeEnd();
03023 if (pFirstNode == NULL || pLastNode == NULL)
03024 {
03025 return FALSE;
03026 }
03027 ok = HitOnDragBlob((NodeRenderableInk*)pFirstNode, Point);
03028 if (ok)
03029 {
03030 *ppHitNode = pFirstNode;
03031 return TRUE;
03032 }
03033 ok = HitOnDragBlob((NodeRenderableInk*)pLastNode, Point);
03034 if (ok)
03035 {
03036 *ppHitNode = pLastNode;
03037 return TRUE;
03038 }
03039 }
03040 pBlender = FindNextBlender(pBlender);
03041 }
03042
03043
03044 return ok;
03045 }
03046
03047
03048
03049
03050
03051
03052
03053
03054
03055
03056
03057
03058
03059
03060
03061
03062 BOOL NodeBlend::HitOnDragBlob(NodeRenderableInk* pInk, DocCoord PointerPos)
03063 {
03064 if (pInk == NULL)
03065 {
03066 ERROR3("Ink node is NULL");
03067 return FALSE;
03068 }
03069 BOOL ok = FALSE;
03070
03071 DocRect BlobSize;
03072 BlobManager* pBlobMgr = GetApplication()->GetBlobManager();
03073 if (pBlobMgr != NULL)
03074 {
03075 DocRect BoundingRect = pInk->GetBoundingRect();
03076 DocCoord CentrePoint = BoundingRect.Centre();
03077 pBlobMgr->GetBlobRect(CentrePoint, &BlobSize);
03078
03079 ok = BlobSize.ContainsCoord(PointerPos);
03080 }
03081
03082 return ok;
03083 }
03084
03085
03086
03087
03088
03089
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102
03103
03104
03105
03106
03107 INT32 NodeBlend::EstimateNodeComplexity (OpParam* details)
03108 {
03109 NodeBlender* pBlender = FindFirstBlender();
03110 INT32 total = 0;
03111
03112 while (pBlender)
03113 {
03114 total += pBlender->EstimateNodeComplexity (details);
03115 pBlender = FindNextBlender(pBlender);
03116 }
03117
03118 return (total);
03119 }
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136 NodeBlender* NodeBlend::NodeIsPartOfBlender(Node* pNode, BOOL FirstNode)
03137 {
03138 if (pNode == NULL)
03139 {
03140 ERROR3("Node is NULL");
03141 return NULL;
03142 }
03143
03144 NodeBlender* pNodeBlender = FindFirstBlender();
03145
03146 if (pNodeBlender == NULL)
03147 {
03148 ERROR3("No nodeblender");
03149 return NULL;
03150 }
03151
03152 while (pNodeBlender != NULL)
03153 {
03154 if (FirstNode)
03155 {
03156 Node* pCheckFirstNode = pNodeBlender->GetNodeStart();
03157 if (pCheckFirstNode == pNode)
03158 return pNodeBlender;
03159 }
03160 else
03161 {
03162 Node* pCheckLastNode = pNodeBlender->GetNodeEnd();
03163 if (pCheckLastNode == pNode)
03164 return pNodeBlender;
03165 }
03166
03167 pNodeBlender = FindNextBlender(pNodeBlender);
03168 }
03169 return NULL;
03170 }
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183
03184
03185
03186
03187 NodeBlender* NodeBlend::NodeIsPartOfBlender(Node* pNode, NodeBlender* pBlender, BOOL* First)
03188 {
03189 if (pNode == NULL)
03190 {
03191 ERROR3("Node is NULL");
03192 return NULL;
03193 }
03194
03195 NodeBlender* pNodeBlender = FindFirstBlender();
03196
03197 if (pNodeBlender == NULL)
03198 {
03199 ERROR3("No nodeblender");
03200 return NULL;
03201 }
03202
03203
03204 while (pNodeBlender != NULL)
03205 {
03206 if (pNodeBlender != pBlender)
03207 {
03208 Node* pStart = pNodeBlender->GetNodeStart();
03209 Node* pEnd = pNodeBlender->GetNodeEnd();
03210
03211 if (pStart == NULL || pEnd == NULL)
03212 {
03213 ERROR3("Start or end node is NULL");
03214 return NULL;
03215 }
03216
03217 if (pStart == pNode)
03218 {
03219 *First = TRUE;
03220 return pNodeBlender;
03221 }
03222 else if (pEnd == pNode)
03223 {
03224 *First = FALSE;
03225 return pNodeBlender;
03226 }
03227 }
03228 pNodeBlender = FindNextBlender(pNodeBlender);
03229 }
03230 return NULL;
03231 }
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243
03244
03245
03246
03247 NodeCompound* NodeBlend::GetParentController() const
03248 {
03249 Node* pParent = (Node*)this->FindParent();
03250
03251 if (pParent == NULL)
03252 {
03253 ERROR3("This blend has no parents");
03254 return NULL;
03255 }
03256
03257 while ((pParent != NULL) && (!pParent->IsLayer()))
03258 {
03259 if (pParent->IsCompoundClass() && pParent->IsController())
03260 return static_cast<NodeCompound*>(pParent);
03261
03262 pParent = pParent->FindParent();
03263 }
03264 return NULL;
03265
03266 }
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281
03282
03283
03284
03285
03286
03287 InitBlendAction::InitBlendAction()
03288 {
03289 m_pNodeBlend = NULL;
03290 m_pNodeBlender = NULL;
03291 m_pStartNode = NULL;
03292 m_pEndNode = NULL;
03293 m_bReverse = FALSE;
03294 m_bStoreStartAndEndNodes = FALSE;
03295 m_enInitType = IBAT_INVALID;
03296 }
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314
03315
03316
03317
03318
03319
03320
03321
03322
03323
03324
03325
03326
03327
03328
03329
03330
03331 ActionCode InitBlendAction::Init(UndoableOperation* pOp,ActionList* pActionList,NodeBlend* pThisNodeBlend,
03332 BOOL StoreStartAndEndNodes, BOOL bReverse, BOOL bNodesMayBeChanged)
03333 {
03334 UINT32 ActSize = sizeof(InitBlendAction);
03335
03336 InitBlendAction* pNewAction;
03337 ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(InitBlendAction),(Action**)&pNewAction);
03338
03339 NodeBlender * pBlender = (NodeBlender *)pThisNodeBlend->FindFirstChild(CC_RUNTIME_CLASS(NodeBlender));
03340
03341 if (pNewAction)
03342 pNewAction->m_enInitType = IBAT_INIT;
03343
03344 if (Ac != AC_FAIL && pNewAction != NULL)
03345 {
03346 pNewAction->m_pNodeBlend = pThisNodeBlend;
03347
03348 if (StoreStartAndEndNodes && pBlender)
03349 {
03350 pNewAction->m_pStartNode = pBlender->GetNodeStart();
03351 pNewAction->m_pEndNode = pBlender->GetNodeEnd();
03352 }
03353
03354 pNewAction->m_bReverse = bReverse;
03355 pNewAction->m_bStoreStartAndEndNodes = StoreStartAndEndNodes;
03356 pNewAction->m_bNodesMayBeChanged = bNodesMayBeChanged;
03357
03358 if (bReverse)
03359 {
03360
03361 pActionList->RemoveItem(pNewAction);
03362 pActionList->AddHead(pNewAction);
03363 }
03364
03365 pThisNodeBlend->InvalidateBlendBoundingRect();
03366 pThisNodeBlend->Deinit(bNodesMayBeChanged);
03367
03368
03369 }
03370
03371 return Ac;
03372 }
03373
03374 ActionCode InitBlendAction::InitOnBlender(UndoableOperation* pOp,ActionList* pActionList,
03375 NodeBlender* pThisNodeBlender, BOOL StoreStartAndEndNodes, BOOL bReverse)
03376 {
03377 UINT32 ActSize = sizeof(InitBlendAction);
03378
03379 InitBlendAction* pNewAction;
03380 ActionCode Ac = Action::Init(pOp,pActionList,ActSize,CC_RUNTIME_CLASS(InitBlendAction),(Action**)&pNewAction);
03381
03382 NodeBlend* pThisNodeBlend = (NodeBlend *)pThisNodeBlender->FindParent(CC_RUNTIME_CLASS(NodeBlend));
03383
03384 pNewAction->m_enInitType = IBAT_INITONBLENDER;
03385 pNewAction->m_pNodeBlender = pThisNodeBlender;
03386
03387 if (Ac != AC_FAIL && pNewAction != NULL)
03388 {
03389 pNewAction->m_pNodeBlend = pThisNodeBlend;
03390
03391 if (StoreStartAndEndNodes && pThisNodeBlender)
03392 {
03393 pNewAction->m_pStartNode = pThisNodeBlender->GetNodeStart();
03394 pNewAction->m_pEndNode = pThisNodeBlender->GetNodeEnd();
03395 }
03396
03397 pNewAction->m_bReverse = bReverse;
03398 pNewAction->m_bStoreStartAndEndNodes = StoreStartAndEndNodes;
03399 pNewAction->m_bNodesMayBeChanged = FALSE;
03400
03401 if (bReverse)
03402 {
03403
03404 pActionList->RemoveItem(pNewAction);
03405 pActionList->AddHead(pNewAction);
03406 }
03407
03408 pThisNodeBlend->InvalidateBlendBoundingRect();
03409 pThisNodeBlend->Deinit();
03410
03411
03412 }
03413
03414 return Ac;
03415 }
03416
03417
03418
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434 ActionCode InitBlendAction::Execute()
03435 {
03436 if (pOperation->IS_KIND_OF(UndoableOperation))
03437 {
03438 switch (m_enInitType)
03439 {
03440 case IBAT_INIT:
03441 {
03442 if (InitBlendAction::Init((UndoableOperation*)pOperation,pOppositeActLst,m_pNodeBlend,
03443 m_bStoreStartAndEndNodes, m_bReverse, m_bNodesMayBeChanged) != AC_OK)
03444 return AC_FAIL;
03445 }
03446 break;
03447 case IBAT_INITONBLENDER:
03448 {
03449 if (InitBlendAction::InitOnBlender((UndoableOperation*)pOperation,pOppositeActLst,m_pNodeBlender,
03450 m_bStoreStartAndEndNodes, m_bReverse) != AC_OK)
03451 return AC_FAIL;
03452 }
03453 break;
03454 default:
03455 {
03456 ERROR3 ("Er - I don't know what to do!");
03457 return (AC_FAIL);
03458 }
03459 break;
03460 }
03461
03462
03463
03464 if (m_pStartNode != NULL && m_pEndNode != NULL)
03465 {
03466 NodeBlender * pBlender = NULL;
03467
03468 switch (m_enInitType)
03469 {
03470 case IBAT_INIT:
03471 {
03472 pBlender = (NodeBlender *)m_pNodeBlend->FindFirstChild(CC_RUNTIME_CLASS(NodeBlender));
03473 }
03474 break;
03475 case IBAT_INITONBLENDER:
03476 {
03477 pBlender = m_pNodeBlender;
03478 }
03479 break;
03480 default:
03481 {
03482 ERROR3 ("Er - I don't know what to do!");
03483 return (AC_FAIL);
03484 }
03485 break;
03486 }
03487
03488 if (pBlender)
03489 {
03490 pBlender->Reinit((NodeRenderableInk *)m_pStartNode, (NodeRenderableInk *)m_pEndNode, FALSE);
03491 }
03492 }
03493
03494 return AC_OK;
03495 }
03496 else
03497 {
03498 ERROR3("InitBlendAction::Execute() called with op that's not an undoable op");
03499 return AC_FAIL;
03500 }
03501 }
03502
03503 InitBlendAction::~InitBlendAction()
03504 {
03505 }
03506
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518
03519
03520
03521
03522
03523
03524 BOOL NodeBlend::WritePreChildren(BaseCamelotFilter* pFilter)
03525 {
03526 #ifdef DO_EXPORT
03527 ERROR2IF(pFilter == NULL,FALSE,"NULL filter param");
03528
03529 BOOL ok = TRUE;
03530
03531
03532 if (ok)
03533 {
03534 CXaraFileRecord ProfileRec(TAG_BLENDPROFILES, TAG_BLENDPROFILES_SIZE);
03535 ok = ProfileRec.Init();
03536 if (ok) ok = ProfileRec.WriteDOUBLE(m_ObjectProfile.GetBias());
03537 if (ok) ok = ProfileRec.WriteDOUBLE(m_ObjectProfile.GetGain());
03538 if (ok) ok = ProfileRec.WriteDOUBLE(m_AttrProfile.GetBias());
03539 if (ok) ok = ProfileRec.WriteDOUBLE(m_AttrProfile.GetGain());
03540 if (ok) ok = ProfileRec.WriteDOUBLE(0.0);
03541 if (ok) ok = ProfileRec.WriteDOUBLE(0.0);
03542 if (ok) ok = pFilter->Write(&ProfileRec);
03543
03544 }
03545
03546 CXaraFileRecord Rec(TAG_BLEND,TAG_BLEND_SIZE);
03547
03548 UINT16 NumSteps = UINT16(m_NumBlendSteps);
03549 BYTE Flags =( m_OneToOne << 0) |
03550 ((m_NotAntialiased == 0) << 1) |
03551 ( m_Tangential << 2);
03552
03553
03554 ERROR3IF(BYTE(m_ColBlendType) > (1 << TAG_BLEND_COLEFFECT_SHIFT),"Col blend type will not fit into the flags byte");
03555 BYTE ColEffect = (BYTE(m_ColBlendType) << TAG_BLEND_COLEFFECT_SHIFT) & TAG_BLEND_COLEFFECT_MASK;
03556
03557 Flags = Flags | ColEffect;
03558
03559 if (ok) ok = Rec.Init();
03560 if (ok) ok = Rec.WriteUINT16(NumSteps);
03561 if (ok) ok = Rec.WriteBYTE(Flags);
03562 if (ok) ok = pFilter->Write(&Rec);
03563
03564
03565
03566
03567 return ok;
03568 #else
03569 return FALSE;
03570 #endif
03571 }
03572
03573
03574
03575
03576
03577
03578
03579
03580
03581
03582
03583
03584
03585
03586
03587
03588
03589
03590 BOOL NodeBlend::WritePreChildrenWeb(BaseCamelotFilter* pFilter)
03591 {
03592 #ifdef DO_EXPORT
03593 if (pFilter->GetConvertBlendsToOutlines())
03594 return pFilter->WriteNodeAsOutlines(this);
03595
03596 return WritePreChildren(pFilter);
03597 #else
03598 return FALSE;
03599 #endif
03600 }
03601
03602
03603
03604
03605 BOOL NodeBlend::WritePreChildrenNative(BaseCamelotFilter* pFilter)
03606 {
03607 #ifdef DO_EXPORT
03608 if (pFilter->IsCompactNativeFilter())
03609 {
03610 if (pFilter->GetConvertBlendsToOutlines())
03611 return pFilter->WriteNodeAsOutlines(this);
03612 }
03613
03614 return WritePreChildren(pFilter);
03615 #else
03616 return FALSE;
03617 #endif
03618 }
03619
03620
03621
03622
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632
03633
03634
03635
03636 BOOL NodeBlend::CanWriteChildrenWeb(BaseCamelotFilter* pFilter)
03637 {
03638 #ifdef DO_EXPORT
03639
03640 if (pFilter->GetConvertBlendsToOutlines())
03641 return FALSE;
03642
03643 return TRUE;
03644 #else
03645 return FALSE;
03646 #endif
03647 }
03648
03649
03650
03651
03652
03653
03654
03655
03656
03657
03658
03659
03660
03661
03662
03663
03664
03665 BOOL NodeBlend::CanWriteChildrenNative(BaseCamelotFilter* pFilter)
03666 {
03667 #ifdef DO_EXPORT
03668
03669 if (pFilter->IsCompactNativeFilter())
03670 {
03671 if (pFilter->GetConvertBlendsToOutlines())
03672 return FALSE;
03673 }
03674
03675 return TRUE;
03676 #else
03677 return FALSE;
03678 #endif
03679 }
03680
03681
03682
03683
03684
03685
03686
03687
03688
03689
03690
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700
03701
03702
03703 BOOL NodeBlend::ReinitialiseOnChildChanged( UndoableOperation* pOp,
03704 NodeRenderableInk* pOldChild,
03705 NodeRenderableInk* pNewChild )
03706 {
03707
03708 ERROR2IF(pOp == NULL || pOldChild == NULL || pNewChild == NULL, FALSE,
03709 "NodeBlend::ReinitialiseOnChildChanged; NULL input parameters!");
03710
03711
03712 NodeBlender* pBlender = FindFirstBlender();
03713 while (pBlender != NULL)
03714 {
03715
03716 if (pBlender->GetNodeStart() == pOldChild)
03717 {
03718 if (InitBlendAction::InitOnBlender(pOp, pOp->GetUndoActionList(), pBlender, TRUE, TRUE) == AC_FAIL)
03719 {
03720 ERROR3("NodeBlend::ReinitialiseOnChildChanged; couldn't init blend action");
03721 }
03722
03723 pBlender->Reinit(pNewChild, NULL, FALSE);
03724 }
03725
03726
03727
03728 if (pBlender->GetNodeEnd() == pOldChild)
03729 {
03730 if (InitBlendAction::InitOnBlender(pOp, pOp->GetUndoActionList(), pBlender, TRUE, TRUE) == AC_FAIL)
03731 {
03732 ERROR3("NodeBlend::ReinitialiseOnChildChanged; couldn't init blend action");
03733 }
03734
03735 pBlender->Reinit(NULL, pNewChild, FALSE);
03736 }
03737
03738 pBlender = FindNextBlender(pBlender);
03739 }
03740
03741 return TRUE;
03742 }
03743
03744
03745
03746
03747
03748
03749
03750
03751
03752
03753
03754
03755
03756
03757
03758
03759
03760
03761
03762
03763
03764
03765
03766
03767 DocRect NodeBlend::ValidateExtend(const ExtendParams& ExtParams)
03768 {
03769
03770
03771 if (!(ExtParams.fExtendFlags & X_EXTEND) && !(ExtParams.fExtendFlags & Y_EXTEND))
03772 return DocRect(INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX);
03773
03774
03775 std::list<NodeRenderableInk*> lpInks;
03776 std::list<NodeBlendPath*> lpBlendPaths;
03777 FindExtendingChildren(lpInks, lpBlendPaths);
03778
03779
03780
03781
03782 DocRect drMinExtend(INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX), drThisMinExtend;
03783 for ( std::list<NodeBlendPath*>::iterator iterPath = lpBlendPaths.begin();
03784 iterPath != lpBlendPaths.end();
03785 iterPath ++ )
03786 {
03787 drThisMinExtend = ((NodeBlendPath*)(*iterPath))->ValidateExtend(ExtParams);
03788 if (drMinExtend.lo.x > drThisMinExtend.lo.x) drMinExtend.lo.x = drThisMinExtend.lo.x;
03789 if (drMinExtend.lo.y > drThisMinExtend.lo.y) drMinExtend.lo.y = drThisMinExtend.lo.y;
03790 if (drMinExtend.hi.x > drThisMinExtend.hi.x) drMinExtend.hi.x = drThisMinExtend.hi.x;
03791 if (drMinExtend.hi.y > drThisMinExtend.hi.y) drMinExtend.hi.y = drThisMinExtend.hi.y;
03792 }
03793
03794
03795
03796
03797
03798
03799
03800
03801
03802
03803
03804
03805
03806
03807
03808
03809
03810
03811
03812
03813
03814
03815
03816
03817
03818 lpInks.size();
03819 for ( std::list<NodeRenderableInk*>::iterator iterInk = lpInks.begin();
03820 iterInk != lpInks.end();
03821 iterInk ++ )
03822 {
03823 drThisMinExtend = ((NodeRenderableInk*)(*iterInk))->ValidateExtend(ExtParams);
03824 if (drMinExtend.lo.x > drThisMinExtend.lo.x) drMinExtend.lo.x = drThisMinExtend.lo.x;
03825 if (drMinExtend.lo.y > drThisMinExtend.lo.y) drMinExtend.lo.y = drThisMinExtend.lo.y;
03826 if (drMinExtend.hi.x > drThisMinExtend.hi.x) drMinExtend.hi.x = drThisMinExtend.hi.x;
03827 if (drMinExtend.hi.y > drThisMinExtend.hi.y) drMinExtend.hi.y = drThisMinExtend.hi.y;
03828 }
03829
03830 return drMinExtend;
03831 }
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848
03849
03850
03851
03852
03853
03854
03855
03856
03857
03858
03859 void NodeBlend::Extend(const ExtendParams& ExtParams)
03860 {
03861
03862 TransformStretchObject(ExtParams);
03863
03864
03865
03866 if ( !(ExtParams.fExtendFlags & (X_EXTEND | Y_EXTEND)) )
03867 return;
03868
03869
03870 std::list<NodeRenderableInk*> lpInks;
03871 std::list<NodeBlendPath*> lpBlendPaths;
03872 FindExtendingChildren(lpInks, lpBlendPaths);
03873
03874
03875 for ( std::list<NodeBlendPath*>::iterator iterPath = lpBlendPaths.begin();
03876 iterPath != lpBlendPaths.end();
03877 iterPath ++ )
03878 {
03879 ((NodeBlendPath*)(*iterPath))->Extend(ExtParams);
03880 }
03881
03882
03883
03884
03885
03886
03887 for ( std::list<NodeRenderableInk*>::iterator iterInk = lpInks.begin();
03888 iterInk != lpInks.end();
03889 iterInk ++ )
03890 {
03891
03892 ((NodeRenderableInk*)(*iterInk))->Extend(ExtParams);
03893 }
03894 }
03895
03896
03897
03898
03899
03900
03901
03902
03903
03904
03905
03906
03907
03908
03909
03910
03911
03912
03913
03914
03915
03916
03917
03918
03919
03920
03921
03922 void NodeBlend::FindExtendingChildren( std::list<NodeRenderableInk*>& lpInks,
03923 std::list<NodeBlendPath*>& lpBlendPaths )
03924 {
03925 std::list<NodeBlend*> lpBlends;
03926 std::list<NodeGroup*> lpGroups;
03927
03928
03929 lpBlends.push_back(this);
03930
03931 NodeBlend* pNodeBlend = NULL;
03932 NodeGroup* pNodeGroup = NULL;
03933 NodeRenderableInk* pInk = NULL;
03934 NodeBlendPath* pNodeBlendPath = NULL;
03935
03936
03937 while (!lpBlends.empty() || !lpGroups.empty())
03938 {
03939
03940 if (!lpBlends.empty())
03941 {
03942
03943 pNodeBlend = lpBlends.front();
03944 lpBlends.pop_front();
03945
03946
03947
03948
03949
03950 std::list<NodeRenderableInk*> lpBlendedObjects;
03951 std::list<NodeRenderableInk*> lpBlendPathObjects;
03952 NodeBlender* pBlender = pNodeBlend->FindFirstBlender();
03953 while (pBlender != NULL)
03954 {
03955
03956 pNodeBlendPath = pBlender->GetNodeBlendPath();
03957 if (pNodeBlendPath != NULL)
03958 {
03959
03960 lpBlendPaths.push_back(pNodeBlendPath);
03961
03962
03963 pInk = pBlender->GetNodeStart();
03964 if (pInk != NULL)
03965 lpBlendPathObjects.push_back(pInk);
03966 pInk = pBlender->GetNodeEnd();
03967 if (pInk != NULL)
03968 lpBlendPathObjects.push_back(pInk);
03969 }
03970
03971
03972 else
03973 {
03974 pInk = pBlender->GetNodeStart();
03975 if (pInk != NULL)
03976 lpBlendedObjects.push_back(pInk);
03977 pInk = pBlender->GetNodeEnd();
03978 if (pInk != NULL)
03979 lpBlendedObjects.push_back(pInk);
03980 }
03981
03982 pBlender = pNodeBlend->FindNextBlender(pBlender);
03983 }
03984
03985
03986
03987 lpBlendPathObjects.sort();
03988 lpBlendedObjects.sort();
03989 std::list<NodeRenderableInk*>::iterator iterNode = lpBlendedObjects.begin();
03990 while (!lpBlendPathObjects.empty() && !lpBlendPathObjects.empty())
03991 {
03992
03993 pInk = lpBlendPathObjects.front();
03994 lpBlendPathObjects.pop_front();
03995
03996
03997
03998 while (iterNode != lpBlendedObjects.end() && (*iterNode) < pInk)
03999 iterNode ++;
04000
04001
04002
04003 while (iterNode != lpBlendedObjects.end() && (*iterNode) == pInk)
04004 iterNode = lpBlendedObjects.erase(iterNode);
04005 }
04006
04007
04008
04009
04010 pInk = NULL;
04011 while (!lpBlendedObjects.empty())
04012 {
04013 if (pInk == lpBlendedObjects.front())
04014 {
04015 lpBlendedObjects.pop_front();
04016 continue;
04017 }
04018
04019 pInk = lpBlendedObjects.front();
04020 lpBlendedObjects.pop_front();
04021
04022 if (IS_A(pInk, NodeGroup))
04023 lpGroups.push_front((NodeGroup*)pInk);
04024
04025 else if (IS_A(pInk, NodeBlend))
04026 lpBlends.push_front((NodeBlend*)pInk);
04027
04028
04029 else if (pInk->IsAnObject())
04030 lpInks.push_back(pInk);
04031 }
04032 }
04033
04034
04035
04036 if (!lpGroups.empty())
04037 {
04038
04039
04040 pNodeGroup = lpGroups.front();
04041 lpGroups.pop_front();
04042 Node* pChild = pNodeGroup->FindFirstChild();
04043 while (pChild != NULL)
04044 {
04045 if (IS_A(pChild, NodeGroup))
04046 lpGroups.push_front((NodeGroup*)pChild);
04047
04048 else if (IS_A(pChild, NodeBlend))
04049 lpBlends.push_front((NodeBlend*)pChild);
04050
04051 else if (pChild->IsAnObject())
04052 lpInks.push_back((NodeRenderableInk*)pChild);
04053
04054 pChild = pChild->FindNext();
04055 }
04056 }
04057 }
04058 }
04059
04060
04061
04062
04063
04064
04065
04066
04067
04068
04069
04070
04071
04072
04073
04074
04075
04076
04077
04078
04079 UINT32* BlendRecordHandler::GetTagList()
04080 {
04081 static UINT32 TagList[] = { TAG_BLEND,
04082 TAG_BLENDER,
04083 TAG_BLENDER_CURVEPROP,
04084 TAG_BLENDER_CURVEANGLES,
04085 TAG_BLEND_PATH,
04086 TAG_BLENDPROFILES,
04087 TAG_BLENDERADDITIONAL,
04088 TAG_NODEBLENDPATH_FILLED,
04089 CXFRH_TAG_LIST_END};
04090
04091 return (UINT32*)&TagList;
04092 }
04093
04094
04095
04096
04097
04098
04099
04100
04101
04102
04103
04104
04105
04106
04107
04108
04109 BOOL BlendRecordHandler::HandleRecord(CXaraFileRecord* pCXaraFileRecord)
04110 {
04111 ERROR2IF(pCXaraFileRecord == NULL,FALSE,"pCXaraFileRecord is NULL");
04112
04113 BOOL ok = TRUE;
04114
04115 switch (pCXaraFileRecord->GetTag())
04116 {
04117 case TAG_BLEND:
04118 ok = HandleBlendRecord(pCXaraFileRecord);
04119 break;
04120
04121 case TAG_BLENDER:
04122 ok = HandleBlenderRecord(pCXaraFileRecord);
04123 break;
04124
04125 case TAG_BLENDER_CURVEPROP:
04126 ok = HandleBlenderCurvePropRecord(pCXaraFileRecord);
04127 break;
04128
04129 case TAG_BLENDER_CURVEANGLES:
04130 ok = HandleBlenderCurveAnglesRecord(pCXaraFileRecord);
04131 break;
04132
04133 case TAG_BLEND_PATH:
04134 ok = HandleBlendPathRecord(pCXaraFileRecord);
04135 break;
04136 case TAG_NODEBLENDPATH_FILLED:
04137 ok = HandleBlendPathFlags(pCXaraFileRecord);
04138 break;
04139 case TAG_BLENDPROFILES:
04140 ok = HandleBlendProfileRecord(pCXaraFileRecord);
04141 break;
04142 case TAG_BLENDERADDITIONAL:
04143 ok = HandleBlenderExtraRecord(pCXaraFileRecord);
04144 break;
04145 default:
04146 ok = FALSE;
04147 ERROR3_PF(("I don't handle records with the tag (%d)\n",pCXaraFileRecord->GetTag()));
04148 break;
04149 }
04150
04151 return ok;
04152 }
04153
04154
04155
04156
04157
04158
04159
04160
04161
04162
04163
04164
04165
04166
04167
04168
04169
04170 BOOL BlendRecordHandler::HandleBlendRecord(CXaraFileRecord* pCXaraFileRecord)
04171 {
04172 ERROR2IF(pCXaraFileRecord == NULL,FALSE,"pCXaraFileRecord is NULL");
04173 ERROR2IF(pCXaraFileRecord->GetTag() != TAG_BLEND,FALSE,"I don't handle this tag type");
04174
04175 UINT16 NumSteps = 0;
04176 BYTE Flags = 0;
04177
04178 BOOL ok = pCXaraFileRecord->ReadUINT16(&NumSteps);
04179 if (ok) ok = pCXaraFileRecord->ReadBYTE(&Flags);
04180
04181 if (ok)
04182 {
04183 NodeBlend* pBlend = new NodeBlend;
04184 if (pBlend != NULL)
04185 {
04186 BOOL OneToOne = Flags & TAG_BLEND_FLAG_ONETOONE;
04187 BOOL Antialias = Flags & TAG_BLEND_FLAG_ANTIALIAS;
04188 BOOL Tangential= Flags & TAG_BLEND_FLAG_TANGENTIAL;
04189 BYTE ColEffect = (Flags & TAG_BLEND_COLEFFECT_MASK) >> TAG_BLEND_COLEFFECT_SHIFT;
04190
04191 pBlend->SetOneToOne(OneToOne != 0);
04192 pBlend->SetNotAntialiased(Antialias == 0);
04193 pBlend->SetTangential(Tangential != 0);
04194 pBlend->SetNumBlendSteps(NumSteps);
04195 pBlend->SetColourBlendType(ColourBlendType(ColEffect));
04196
04197 ok = InsertNode(pBlend);
04198 if (ok)
04199 SetLastInsertedNodeBlend(pBlend);
04200
04201
04202 if (m_bLoadedProfiles && ok)
04203 {
04204 CProfileBiasGain* pObjProfile = pBlend->GetObjectProfile();
04205 if (pObjProfile == NULL)
04206 ok = FALSE;
04207 else
04208 {
04209 pObjProfile->SetBiasGain(m_LastObjectProfile.GetBias(), m_LastObjectProfile.GetGain());
04210 pBlend->RequestObjectProfileProcessing (TRUE);
04211 }
04212 if (ok)
04213 {
04214 CProfileBiasGain* pAttrProfile = pBlend->GetAttrProfile();
04215 if (pAttrProfile == NULL)
04216 ok = FALSE;
04217 else
04218 {
04219 pAttrProfile->SetBiasGain(m_LastAttrProfile.GetBias(), m_LastAttrProfile.GetGain());
04220 pBlend->RequestObjectProfileProcessing (TRUE);
04221 }
04222 }
04223 if (ok)
04224 {
04225 CProfileBiasGain* pPosProfile = pBlend->GetPositionProfile();
04226 if (pPosProfile == NULL)
04227 ok = FALSE;
04228 else
04229 pPosProfile->SetBiasGain(m_LastPositionProfile.GetBias(), m_LastPositionProfile.GetGain());
04230 }
04231 }
04232
04233
04234 }
04235 else
04236 ok = FALSE;
04237 }
04238
04239 m_bLoadedProfiles = FALSE;
04240 return ok;
04241 }
04242
04243
04244
04245
04246
04247
04248
04249
04250
04251
04252
04253
04254
04255
04256
04257
04258
04259 BOOL BlendRecordHandler::HandleBlenderRecord(CXaraFileRecord* pCXaraFileRecord)
04260 {
04261 ERROR2IF(pCXaraFileRecord == NULL,FALSE,"pCXaraFileRecord is NULL");
04262 ERROR2IF(pCXaraFileRecord->GetTag() != TAG_BLENDER,FALSE,"I don't handle this tag type");
04263
04264 INT32 PathIndexStart= -1;
04265 INT32 PathIndexEnd = -1;
04266
04267 BOOL ok = pCXaraFileRecord->ReadINT32(&PathIndexStart);
04268 if (ok) ok = pCXaraFileRecord->ReadINT32(&PathIndexEnd);
04269
04270 if (ok)
04271 {
04272 NodeBlender* pBlender = new NodeBlender;
04273 if (pBlender != NULL)
04274 {
04275 pBlender->SetPathIndexStart(PathIndexStart);
04276 pBlender->SetPathIndexEnd(PathIndexEnd);
04277
04278 ok = InsertNode(pBlender);
04279 if (ok) SetLastInsertedNodeBlender(pBlender);
04280
04281 }
04282 else
04283 ok = FALSE;
04284 }
04285
04286 return ok;
04287 }
04288
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298
04299
04300
04301
04302
04303
04304
04305 BOOL BlendRecordHandler::HandleBlenderCurvePropRecord(CXaraFileRecord* pCXaraFileRecord)
04306 {
04307 ERROR2IF(pCXaraFileRecord == NULL,FALSE,"pCXaraFileRecord is NULL");
04308 ERROR2IF(pCXaraFileRecord->GetTag() != TAG_BLENDER_CURVEPROP,FALSE,"I don't handle this tag type");
04309
04310 BOOL ok = TRUE;
04311 NodeBlender* pNodeBlender = GetLastInsertedNodeBlender();
04312
04313 if (pNodeBlender != NULL)
04314 {
04315 double ProportionOfPathDistStart = -1.0;
04316 double ProportionOfPathDistEnd = -1.0;
04317
04318 ok = pCXaraFileRecord->ReadDOUBLE(&ProportionOfPathDistStart);
04319 if (ok) ok = pCXaraFileRecord->ReadDOUBLE(&ProportionOfPathDistEnd);
04320
04321 if (ok)
04322 {
04323 pNodeBlender->SetProportionOfPathDistStart(ProportionOfPathDistStart);
04324 pNodeBlender->SetProportionOfPathDistEnd(ProportionOfPathDistEnd);
04325 }
04326 }
04327
04328 return ok;
04329 }
04330
04331
04332
04333
04334
04335
04336
04337
04338
04339
04340
04341
04342
04343
04344
04345
04346
04347 BOOL BlendRecordHandler::HandleBlenderCurveAnglesRecord(CXaraFileRecord* pCXaraFileRecord)
04348 {
04349 ERROR2IF(pCXaraFileRecord == NULL,FALSE,"pCXaraFileRecord is NULL");
04350 ERROR2IF(pCXaraFileRecord->GetTag() != TAG_BLENDER_CURVEANGLES,FALSE,"I don't handle this tag type");
04351
04352 BOOL ok = TRUE;
04353 NodeBlender* pNodeBlender = GetLastInsertedNodeBlender();
04354
04355 if (pNodeBlender != NULL)
04356 {
04357 double AngleStart = 0.0;
04358 double AngleEnd = 0.0;
04359
04360 ok = pCXaraFileRecord->ReadDOUBLE(&AngleStart);
04361 if (ok) ok = pCXaraFileRecord->ReadDOUBLE(&AngleEnd);
04362
04363 if (ok)
04364 {
04365 pNodeBlender->SetAngleStart(AngleStart);
04366 pNodeBlender->SetAngleEnd(AngleEnd);
04367 }
04368 }
04369
04370 return ok;
04371 }
04372
04373
04374
04375
04376
04377
04378
04379
04380
04381
04382
04383
04384
04385
04386
04387
04388
04389 BOOL BlendRecordHandler::HandleBlendPathRecord(CXaraFileRecord* pCXaraFileRecord)
04390 {
04391 ERROR2IF(pCXaraFileRecord == NULL,FALSE,"pCXaraFileRecord is NULL");
04392 ERROR2IF(pCXaraFileRecord->GetTag() != TAG_BLEND_PATH,FALSE,"I don't handle this tag type");
04393
04394 BOOL ok = FALSE;
04395
04396 NodeBlendPath* pNodeBlendPath = new NodeBlendPath;
04397
04398 if (pNodeBlendPath != NULL && pNodeBlendPath->SetUpPath())
04399 {
04400 ok = pCXaraFileRecord->ReadPath(&pNodeBlendPath->InkPath);
04401 if (ok) pNodeBlendPath->InkPath.InitialiseFlags();
04402 if (ok) ok = InsertNode(pNodeBlendPath);
04403 if (ok)
04404 {
04405 SetLastNodePathInserted(pNodeBlendPath);
04406 SetLastInsertedNodeBlendPath(pNodeBlendPath);
04407 }
04408 if (ok)
04409 {
04410 Node* pParent = pNodeBlendPath->FindParent();
04411 if ((pParent != NULL) && (pParent->IS_KIND_OF(NodeBlend)))
04412 {
04413 NodeBlend* pNodeBlend = (NodeBlend*)pParent;
04414 pNodeBlend->SetBlendedOnCurve(TRUE);
04415 pNodeBlend->SetNumNodeBlendPathsInc(TRUE);
04416
04417
04418
04419
04420
04421
04422 NodeBlender* pBlender = pNodeBlend->FindFirstBlender();
04423 while (pBlender != NULL)
04424 {
04425 if (pBlender->GetNodeBlendPathIndex() == -2)
04426 pBlender->SetNodeBlendPathIndex(0);
04427
04428 pBlender = pNodeBlend->FindNextBlender(pBlender);
04429 }
04430 }
04431 }
04432 }
04433
04434 return ok;
04435 }
04436
04437
04438
04439
04440
04441
04442
04443
04444
04445
04446
04447
04448
04449
04450
04451
04452
04453 BOOL BlendRecordHandler::HandleBlendPathFlags(CXaraFileRecord* pXFRecord)
04454 {
04455 ERROR2IF(pXFRecord == NULL,FALSE,"pCXaraFileRecord is NULL");
04456 ERROR2IF(pXFRecord->GetTag() != TAG_NODEBLENDPATH_FILLED,FALSE,"I don't handle this tag type");
04457
04458 INT32 Flag;
04459 BOOL ok = pXFRecord->ReadINT32(&Flag);
04460
04461 if (ok)
04462 {
04463 NodeBlendPath* pNodeBlendPath = GetLastInsertedNodeBlendPath();
04464 ERROR2IF(pNodeBlendPath == NULL, FALSE, "No NodeBlendPath");
04465
04466 pNodeBlendPath->InkPath.IsFilled = Flag;
04467 }
04468
04469 return ok;
04470 }
04471
04472
04473
04474
04475
04476
04477
04478
04479
04480
04481
04482
04483
04484
04485
04486
04487
04488
04489
04490
04491
04492
04493
04494
04495 BOOL BlendRecordHandler::HandleBlenderExtraRecord(CXaraFileRecord* pRecord)
04496 {
04497 ERROR2IF(pRecord == NULL,FALSE,"pCXaraFileRecord is NULL");
04498 ERROR2IF(pRecord->GetTag() != TAG_BLENDERADDITIONAL,FALSE,"I don't handle this tag type");
04499
04500 INT32 Flag;
04501 INT32 Index;
04502 INT32 ObjIndexStart;
04503 INT32 ObjIndexEnd;
04504 BYTE BitField;
04505
04506 BOOL ok = pRecord->ReadINT32(&Flag);
04507 if (ok) ok = pRecord->ReadINT32(&Index);
04508 if (ok) ok = pRecord->ReadINT32(&ObjIndexStart);
04509 if (ok) ok = pRecord->ReadINT32(&ObjIndexEnd);
04510 if (ok)
04511 {
04512
04513
04514 if (!pRecord->ReadBYTEnoError(&BitField))
04515 BitField = 0;
04516 }
04517
04518 if (ok)
04519 {
04520 NodeBlender* pBlender = GetLastInsertedNodeBlender();
04521 ERROR2IF(pBlender == NULL, FALSE, "No NodeBlender");
04522
04523 pBlender->SetBlendedOnCurve(Flag);
04524 pBlender->SetNodeBlendPathIndex(Index);
04525 pBlender->SetObjIndexStart(ObjIndexStart);
04526 pBlender->SetObjIndexEnd(ObjIndexEnd);
04527 pBlender->SetReversed((BitField & 1) == 1);
04528
04529 NodeBlend* pNodeBlend = pBlender->GetNodeBlend();
04530 ERROR2IF(pNodeBlend == NULL, FALSE, "Parent is not NodeBlend");
04531
04532 INT32 CurrentNodeBlendPaths = (INT32)pNodeBlend->GetNumNodeBlendPaths();
04533 if (Index > CurrentNodeBlendPaths)
04534 pNodeBlend->SetNumNodeBlendPaths(Index+1);
04535
04536 }
04537 return ok;
04538 }
04539
04540
04541
04542
04543
04544
04545
04546
04547
04548
04549
04550
04551
04552
04553
04554
04555
04556
04557
04558
04559
04560 BOOL BlendRecordHandler::HandleBlendProfileRecord(CXaraFileRecord* pCXaraFileRecord)
04561 {
04562 ERROR2IF(pCXaraFileRecord == NULL,FALSE,"pCXaraFileRecord is NULL");
04563 ERROR2IF(pCXaraFileRecord->GetTag() != TAG_BLENDPROFILES,FALSE,"I don't handle this tag type");
04564
04565 double ObjBias = 0.0;
04566 double ObjGain = 0.0;
04567 double AttrBias = 0.0;
04568 double AttrGain = 0.0;
04569 double PosBias = 0.0;
04570 double PosGain = 0.0;
04571
04572 BOOL ok = pCXaraFileRecord->ReadDOUBLE(&ObjBias);
04573 if (ok) ok = pCXaraFileRecord->ReadDOUBLE(&ObjGain);
04574 if (ok) ok = pCXaraFileRecord->ReadDOUBLE(&AttrBias);
04575 if (ok) ok = pCXaraFileRecord->ReadDOUBLE(&AttrGain);
04576 if (ok) ok = pCXaraFileRecord->ReadDOUBLE(&PosBias);
04577 if (ok) ok = pCXaraFileRecord->ReadDOUBLE(&PosGain);
04578
04579 m_LastObjectProfile.SetBiasGain(ObjBias, ObjGain);
04580 m_LastAttrProfile.SetBiasGain(AttrBias, AttrGain);
04581 m_LastPositionProfile.SetBiasGain(PosBias, PosGain);
04582
04583 m_bLoadedProfiles = TRUE;
04584
04585 return ok;
04586 }
04587
04588
04589
04590
04591
04592
04593
04594
04595
04596
04597
04598
04599
04600
04601
04602
04603
04604
04605 #ifdef XAR_TREE_DIALOG
04606 void BlendRecordHandler::GetRecordDescriptionText(CXaraFileRecord* pRecord,StringBase* pStr)
04607 {
04608 if (pStr == NULL || pRecord == NULL)
04609 return;
04610
04611 TCHAR s[256];
04612
04613
04614 CamelotRecordHandler::GetRecordDescriptionText(pRecord,pStr);
04615
04616 switch (pRecord->GetTag())
04617 {
04618 case TAG_BLEND:
04619 {
04620 UINT16 NumSteps = 0;
04621 BYTE Flags = 0;
04622
04623 pRecord->ReadUINT16(&NumSteps);
04624 pRecord->ReadBYTE(&Flags);
04625
04626 camSprintf(s,_T("NumSteps\t= %hu\r\n"),NumSteps);
04627 (*pStr) += s;
04628 camSprintf(s,_T("Flags\t\t= %d\r\n"),INT32(Flags));
04629 (*pStr) += s;
04630 (*pStr) += _T("\r\n");
04631
04632 camSprintf(s,_T("One to One\t= %d\r\n"),Flags & TAG_BLEND_FLAG_ONETOONE);
04633 (*pStr) += s;
04634 camSprintf(s,_T("Antialiased\t= %d\r\n"),Flags & TAG_BLEND_FLAG_ANTIALIAS);
04635 (*pStr) += s;
04636 camSprintf(s,_T("Tangential\t= %d\r\n"),Flags & TAG_BLEND_FLAG_TANGENTIAL);
04637 (*pStr) += s;
04638
04639 BYTE ColEffect = (Flags & TAG_BLEND_COLEFFECT_MASK) >> TAG_BLEND_COLEFFECT_SHIFT;
04640 camSprintf(s,_T("Colour Effect\t= %d\r\n"),INT32(ColEffect));
04641 (*pStr) += s;
04642 }
04643 break;
04644
04645 case TAG_BLENDER:
04646 {
04647 INT32 PathIndexStart = -1;
04648 INT32 PathIndexEnd = -1;
04649
04650 pRecord->ReadINT32(&PathIndexStart);
04651 pRecord->ReadINT32(&PathIndexEnd);
04652
04653 camSprintf(s,_T("PathIndexStart\t= %d\r\n"),PathIndexStart);
04654 (*pStr) += s;
04655 camSprintf(s,_T("PathIndexEnd\t= %d\r\n"),PathIndexEnd);
04656 (*pStr) += s;
04657
04658 }
04659 break;
04660
04661 case TAG_BLENDER_CURVEPROP:
04662 {
04663 double PropStart = -1.0;
04664 double PropEnd = -1.0;
04665 pRecord->ReadDOUBLE(&PropStart);
04666 pRecord->ReadDOUBLE(&PropEnd);
04667 camSprintf(s,_T("Proportion of path distance start\t= %f\r\n"),PropStart);
04668 (*pStr) += s;
04669 camSprintf(s,_T("Proportion of path distance end\t= %f\r\n"),PropEnd);
04670 (*pStr) += s;
04671 }
04672 break;
04673
04674 case TAG_BLENDER_CURVEANGLES:
04675 {
04676 double AngleStart = -1.0;
04677 double AngleEnd = -1.0;
04678 pRecord->ReadDOUBLE(&AngleStart);
04679 pRecord->ReadDOUBLE(&AngleEnd);
04680 camSprintf(s,_T("Angle start\t= %f\r\n"),AngleStart);
04681 (*pStr) += s;
04682 camSprintf(s,_T("Angle end\t= %f\r\n"),AngleEnd);
04683 (*pStr) += s;
04684 }
04685 break;
04686
04687 case TAG_BLEND_PATH:
04688
04689 DescribePath(pRecord,pStr);
04690 break;
04691 case TAG_BLENDERADDITIONAL:
04692 {
04693 INT32 BlendedOnCurve = FALSE;
04694 pRecord->ReadINT32(&BlendedOnCurve);
04695 camSprintf(s,_T("BlendedOnCurve\t= %f\r\n"),BlendedOnCurve);
04696 (*pStr) += s;
04697 }
04698 break;
04699 case TAG_NODEBLENDPATH_FILLED:
04700 {
04701 INT32 Filled = FALSE;
04702 pRecord->ReadINT32(&Filled);
04703 camSprintf(s,_T("Filled \t= %f\r\n"),Filled);
04704 (*pStr) += s;
04705 }
04706 break;
04707 case TAG_BLENDPROFILES:
04708 double ObjBias = 0.0;
04709 double ObjGain = 0.0;
04710 double AttrBias = 0.0;
04711 double AttrGain = 0.0;
04712 double PosBias = 0.0;
04713 double PosGain = 0.0;
04714 BOOL ok = pRecord->ReadDOUBLE(&ObjBias);
04715 if (ok)
04716 {
04717 camSprintf(s,_T("Object Bias\t= %f\r\n"),ObjBias);
04718 (*pStr) += s;
04719 ok = pRecord->ReadDOUBLE(&ObjGain);
04720 }
04721 if (ok)
04722 {
04723 camSprintf(s,_T("Object Gain\t= %f\r\n"),ObjGain);
04724 (*pStr) += s;
04725 ok = pRecord->ReadDOUBLE(&AttrBias);
04726 }
04727 if (ok)
04728 {
04729 camSprintf(s,_T("Attribute Bias\t= %f\r\n"),AttrBias);
04730 (*pStr) += s;
04731 ok = pRecord->ReadDOUBLE(&AttrGain);
04732 }
04733 if (ok)
04734 {
04735 camSprintf(s,_T("Attribute Gain\t= %f\r\n"),AttrGain);
04736 (*pStr) += s;
04737 ok = pRecord->ReadDOUBLE(&PosBias);
04738 }
04739 if (ok)
04740 {
04741 camSprintf(s,_T("Position Bias\t= %f\r\n"),PosBias);
04742 (*pStr) += s;
04743 ok = pRecord->ReadDOUBLE(&PosGain);
04744 }
04745 if (ok)
04746 {
04747 camSprintf(s,_T("Position Gain\t= %f\r\n"),PosGain);
04748 (*pStr) += s;
04749 }
04750 break;
04751 }
04752 }
04753 #endif