00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 #include "camtypes.h"
00114
00115 #include "opgrad.h"
00116 #include "filltool.h"
00117
00118
00119
00120 #include "lineattr.h"
00121
00122
00123
00124
00125
00126 #include "blobs.h"
00127
00128 #include "toollist.h"
00129
00130 #include "bitmpinf.h"
00131 #include "progress.h"
00132 #include "ndoptmz.h"
00133 #include "csrstack.h"
00134
00135 #include "objchge.h"
00136 #include "keypress.h"
00137 #include "nodeblnd.h"
00138 #include "fillramp.h"
00139
00140
00141 #include "nodecont.h"
00142
00143 #ifndef STANDALONE
00144 CC_IMPLEMENT_DYNCREATE( OpCreateFill, Operation )
00145 CC_IMPLEMENT_DYNCREATE( OpEditFill, OpApplyAttribToSelected )
00146 CC_IMPLEMENT_DYNCREATE( RestoreFillRampAction, Action)
00147 #endif
00148
00149
00150
00151
00152
00153
00154
00155 #define new CAM_DEBUG_NEW
00156
00157
00158 BOOL OpEditFill::InteractiveDragUpdate = TRUE;
00159 BOOL OpEditFill::ContinuousEOR = TRUE;
00160 UINT32 OpEditFill::IdleFillDelay = 200;
00161
00162 BOOL OpEditFill::CreateFill = FALSE;
00163
00164 static BOOL EditFinished = FALSE;
00165
00166
00167
00168 static NodeRenderableInk* pParentOfFill = NULL;
00169 static AttrFillGeometry* pTheFill = NULL;
00170
00171 #ifndef STANDALONE
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 OpEditFill::OpEditFill()
00184 {
00185
00186 AlwaysFail = TRUE;
00187 ApplyAtEnd = TRUE;
00188 ForceAspectLock = FALSE;
00189 CreateFill = FALSE;
00190 IsRequired = TRUE;
00191 ShouldApplyNewFill = FALSE;
00192 CheckForCompound = TRUE;
00193 CallAllowOp = FALSE;
00194
00195 InvalidateAll = TRUE;
00196 InvalidateCompound = FALSE;
00197
00198 DragIsIdle = FALSE;
00199 DoneIdleRedraw = FALSE;
00200
00201 ShowDragBlobs = TRUE;
00202 DontDrawBlobs = FALSE;
00203
00204 EditFinished = FALSE;
00205
00206 AspectRatio = 1;
00207 }
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 void OpEditFill::DoCreate(DocCoord &Start, Spread* pSpread, AttrFillGeometry* pGrad)
00223 {
00224 ERROR3IF(pGrad == NULL, "Fill pointer is NULL in OpEditFill::DoCreate()");
00225
00226 if (pGrad == NULL)
00227 {
00228
00229 FailAndExecute();
00230 End();
00231 return;
00232 }
00233
00234
00235 m_pAttr = (NodeAttribute *)pGrad;
00236
00237 AlwaysFail = FALSE;
00238
00239
00240 ApplyAtEnd = FALSE;
00241 ForceAspectLock = TRUE;
00242 CreateFill = TRUE;
00243
00244
00245
00246 UndoAttribStrID = pGrad->GetAttrNameID();
00247 AttrFillGeometry::HitList.DeleteAll();
00248
00249 SelRange* pSel = GetApplication()->FindSelection();
00250 if (pSel && pSel->Count() > 0)
00251 {
00252
00253 ObjChangeFlags cFlags;
00254 cFlags.Attribute = TRUE;
00255 ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
00256 ObjChange.SetRetainCachedData(TRUE);
00257 if (!pSel->AllowOp(&ObjChange))
00258 {
00259 delete pGrad;
00260 FailAndExecute();
00261 End();
00262 return;
00263 }
00264 }
00265
00266 AttrFillGeometry* pFillToEdit = pGrad;
00267
00268
00269 if (AttributeManager::CanBeAppliedToSelection(pGrad, &AttrGroups))
00270 {
00271
00272 IsRequired = TRUE;
00273
00274
00275
00276 ShouldApplyNewFill = TRUE;
00277
00278
00279 DocRect SelBounds = pSel->GetBlobBoundingRect();
00280 RenderInitSelectionBlobs(pSel, SelBounds, pSpread);
00281 }
00282 else
00283 {
00284
00285
00286
00287 IsRequired = FALSE;
00288 AttributeManager::pLastNodeAppliedTo = NULL;
00289 }
00290
00291
00292 DocView::SnapSelected(pSpread, &Start);
00293
00294
00295 pFillToEdit->SetStartPoint(&Start);
00296 pFillToEdit->SetEndPoint(&Start);
00297 pFillToEdit->SetEndPoint2(&Start);
00298
00299
00300 DoDrag(Start, pSpread, pFillToEdit, FILLCONTROL_ENDPOINT);
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 void OpEditFill::DoDrag(DocCoord &Start, Spread* pSpread, AttrFillGeometry* pGrad, FillControl ControlHit)
00331 {
00332 ERROR3IF(ControlHit > NUMCONTROLPOINTS &&
00333 !ISA_RAMPINDEX(ControlHit), "Invalid control point in OpEditFill::DoDrag()");
00334 ERROR3IF(pGrad == NULL, "Fill pointer is NULL in OpEditFill::DoDrag()");
00335
00336 if (pGrad == NULL)
00337 {
00338
00339 FailAndExecute();
00340 End();
00341 return;
00342 }
00343
00344
00345 StartSpread = pSpread;
00346 DragControl = ControlHit;
00347
00348
00349 CCRuntimeClass* ObjectType = pGrad->GetRuntimeClass();
00350 FillClone = (AttrFillGeometry*)ObjectType->CreateObject();
00351 *FillClone = *pGrad;
00352
00353
00354 ObjectType = pGrad->GetRuntimeClass();
00355 GradFill = (AttrFillGeometry*)ObjectType->CreateObject();
00356 *GradFill = *pGrad;
00357
00358 pParentOfFill = (NodeRenderableInk*) pGrad->FindParent ();
00359 pTheFill = pGrad;
00360
00361 if (CreateFill)
00362 delete pGrad;
00363
00364 AspectRatio = FindAspectRatio();
00365
00366 AnchorPos = Start;
00367 LastMousePosition = Start;
00368
00369 DontDrawBlobs = FALSE;
00370 DragIsIdle = FALSE;
00371 DoneIdleRedraw = FALSE;
00372
00373
00374 ShowDragBlobs = !DocView::SolidDragging;
00375
00376 if (!IsRequired)
00377 ShowDragBlobs = TRUE;
00378
00379 AttrFillGeometry::DraggedFill = NULL;
00380 AttrFillGeometry::EditedFill = GradFill;
00381
00382
00383 StartDrag(DRAGTYPE_AUTOSCROLL, NULL, NULL, TRUE, TRUE);
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 void OpEditFill::DragPointerMove(DocCoord PointerPos, ClickModifiers ClickMods, Spread* pSpread, BOOL bSolidDrag)
00403 {
00404 if (ISA_RAMPINDEX(DragControl) && !bSolidDrag)
00405 {
00406 GradFill->DisableRampRedraw();
00407 }
00408
00409 if (EditFinished)
00410 return;
00411
00412 if (ForceAspectLock)
00413 ClickMods.Adjust = TRUE;
00414
00415 DragIsIdle = FALSE;
00416 DoneIdleRedraw = FALSE;
00417
00418
00419 DocView::SnapSelected(pSpread, &PointerPos);
00420
00421 if (AttrFillGeometry::DraggedFill == NULL)
00422 {
00423 double APixel = (DocView::GetSelected()->GetScaledPixelWidth()).MakeDouble();
00424
00425
00426 if (PointerPos.Distance(AnchorPos) <= APixel*2)
00427 {
00428 if (!(ISA_RAMPINDEX(DragControl)))
00429 {
00430 return;
00431 }
00432 }
00433
00434
00435 if (!CreateFill)
00436 {
00437
00438
00439
00440 ListItem* pAttrPtr = AttrFillGeometry::HitList.GetHead();
00441 AttrFillGeometry* pGrad = (AttrFillGeometry*)((NodeAttributePtrItem*)pAttrPtr)->NodeAttribPtr;
00442
00443 if (pGrad != NULL)
00444 {
00445 Node* pParent = pGrad->FindParent();
00446
00447 if (pParent != NULL)
00448 {
00449
00450 ObjChangeFlags cFlags;
00451 cFlags.Attribute = TRUE;
00452 ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
00453 ObjChange.SetRetainCachedData(TRUE);
00454
00455 if (!pParent->AllowOp(&ObjChange))
00456 {
00457
00458
00459 EndDrag();
00460 delete FillClone;
00461 delete GradFill;
00462
00463 FailAndExecute();
00464 End();
00465 return;
00466 }
00467 }
00468 }
00469 }
00470
00471 AttrFillGeometry::EditedFill = GradFill;
00472
00473 AttrFillGeometry::LastRenderedStartBlob = DocCoord(0,0);
00474 AttrFillGeometry::LastRenderedEndBlob = DocCoord(0,0);
00475 AttrFillGeometry::LastRenderedEnd2Blob = DocCoord(0,0);
00476 AttrFillGeometry::LastRenderedEnd3Blob = DocCoord(0,0);
00477
00478
00479 RenderInitBlobs(GradFill->GetBlobBoundingRect(), StartSpread, bSolidDrag);
00480
00481 GradFill->SetBlobState(DragControl, TRUE);
00482
00483
00484 AttrFillGeometry::DraggedFill = GradFill;
00485
00486 LastDragRect = GradFill->GetBlobBoundingRect();
00487 DontDrawBlobs = !ShowDragBlobs;
00488
00489
00490 RenderDragBlobs(LastDragRect, StartSpread, bSolidDrag);
00491
00492
00493 String_256 DragText;
00494 GetStatusLineText(&DragText, pSpread, PointerPos, ClickMods);
00495 GetApplication()->UpdateStatusBarText(&DragText);
00496 }
00497
00498
00499 if (PointerPos != LastMousePosition)
00500 {
00501
00502 RenderDragBlobs(LastDragRect, StartSpread, bSolidDrag);
00503
00504
00505 if (pSpread != StartSpread)
00506 PointerPos = MakeRelativeToSpread(StartSpread, pSpread, PointerPos);
00507
00508
00509 GradFill->OnControlDrag(PointerPos, DragControl, ClickMods);
00510
00511 LastMousePosition = PointerPos;
00512
00513
00514
00515 if (ForceAspectLock)
00516 GradFill->SetAspectRatio(AspectRatio);
00517
00518 LastDragRect = GradFill->GetBlobBoundingRect();
00519 DontDrawBlobs = !ShowDragBlobs;
00520
00521
00522 RenderDragBlobs(LastDragRect, StartSpread, bSolidDrag);
00523
00524 if (DontDrawBlobs)
00525 RedrawFills(ClickMods);
00526 }
00527
00528 if (ISA_RAMPINDEX(DragControl))
00529 {
00530 GradFill->EnableRampRedraw ();
00531 }
00532 }
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544 double OpEditFill::FindAspectRatio()
00545 {
00546
00547 if (!GradFill->IsABitmapFill())
00548 return 1;
00549
00550 SelRange* pSel = GetApplication()->FindSelection();
00551
00552 NodeAttribute* pCommonAttr;
00553 SelRange::CommonAttribResult Result;
00554
00555
00556 Result = pSel->FindCommonAttribute(GradFill->GetAttributeType(), &pCommonAttr);
00557
00558 KernelBitmap* Bmp = NULL;
00559
00560 if (Result == SelRange::ATTR_COMMON)
00561 {
00562
00563
00564 AttrFillGeometry* pFill = (AttrFillGeometry*)pCommonAttr;
00565
00566 if (pFill->IsABitmapFill())
00567 Bmp = pFill->GetBitmap();
00568
00569 GradFill->AttachBitmap(Bmp);
00570 }
00571 else
00572 {
00573
00574 Bmp = GradFill->GetBitmap();
00575 }
00576
00577 if (Bmp == NULL)
00578 return 1;
00579
00580 BitmapInfo Info;
00581
00582 if (Bmp->ActualBitmap &&
00583 Bmp->ActualBitmap->GetInfo( &Info ))
00584 {
00585 INT32 BitmapWidth = Info.RecommendedWidth;
00586 INT32 BitmapHeight = Info.RecommendedHeight;
00587
00588
00589 return double(BitmapHeight)/double(BitmapWidth);
00590 }
00591
00592
00593 return 1;
00594 }
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606 void OpEditFill::RedrawFills(ClickModifiers& ClickMods)
00607 {
00608 if (ClickMods.Alternative1)
00609 return;
00610
00611
00612
00613 Operation::SetQuickRender(TRUE);
00614
00615 if (ShouldApplyNewFill)
00616 {
00617
00618
00619 ApplyNewFill();
00620 }
00621
00622 if (CheckForCompound)
00623 {
00624
00625
00626 CheckForCompoundRedraw();
00627 }
00628
00629 if (!AttrFillGeometry::HitList.IsEmpty())
00630 {
00631 DocView* pSelView = DocView::GetSelected();
00632
00633
00634 ListItem* pAttrPtr = AttrFillGeometry::HitList.GetHead();
00635
00636 DocRect SelBounds = GetApplication()->FindSelection()->GetBoundingRect();
00637
00638 while (pAttrPtr != NULL)
00639 {
00640 AttrFillGeometry* pAttr = (AttrFillGeometry*)((NodeAttributePtrItem*)pAttrPtr)->NodeAttribPtr;
00641 ERROR3IF(pAttr->IsADefaultAttr(), "Default attr in hit list");
00642
00643 if (pAttr != GradFill)
00644 {
00645 if (ISA_RAMPINDEX(DragControl))
00646 {
00647 AttrFillGeometry* CurrentFill = AttrFillGeometry::DraggedFill;
00648
00649 AttrFillGeometry::DraggedFill = pAttr;
00650 DocRect Current = pAttr->GetBlobBoundingRect ();
00651 SelBounds = SelBounds.Union (Current);
00652
00653 AttrFillGeometry::DraggedFill = CurrentFill;
00654 }
00655
00656
00657 pAttr->SetStartPoint(GradFill->GetStartPoint());
00658 pAttr->SetEndPoint(GradFill->GetEndPoint());
00659 pAttr->SetEndPoint2(GradFill->GetEndPoint2());
00660 pAttr->SetColourRamp(GradFill->GetColourRamp());
00661
00662
00663 pAttr->RecalcFractal();
00664 }
00665
00666 if (!InvalidateAll)
00667 {
00668
00669 NodeRenderableInk* pParent = (NodeRenderableInk*)pAttr->FindParent();
00670 ERROR3IF(pParent==NULL, "Can't find parent of edited attribute");
00671 if (pParent && pAttr->IsEffectAttribute())
00672 {
00673
00674
00675
00676 pParent->ReleaseCached(TRUE, FALSE, FALSE, TRUE);
00677 }
00678 else
00679 pParent->ReleaseCached();
00680 pSelView->ForceRedraw(StartSpread, pParent->GetBoundingRect(), FALSE, pAttr);
00681 GetApplication ()->ServiceRendering ();
00682 }
00683
00684 pAttrPtr = AttrFillGeometry::HitList.GetNext(pAttrPtr);
00685 }
00686
00687 if (InvalidateAll)
00688 {
00689
00690
00691 if (InvalidateCompound)
00692 {
00693 pAttrPtr = AttrFillGeometry::HitList.GetHead();
00694 AttrFillGeometry* pGrad = (AttrFillGeometry*)((NodeAttributePtrItem*)pAttrPtr)->NodeAttribPtr;
00695
00696 if (CallAllowOp && !pGrad->IsEffectAttribute())
00697 {
00698
00699
00700
00701 ObjChangeFlags cFlags;
00702 cFlags.Attribute = TRUE;
00703
00704 ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL, this);
00705
00706 pGrad->AllowOp(&ObjChange);
00707
00708 ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL, this);
00709 UpdateAllChangedNodes(&ObjChange);
00710 }
00711
00712 if (ISA_RAMPINDEX (DragControl))
00713 {
00714 GradFill->DisableBoundsRedraw();
00715 }
00716
00717 NodeRenderableInk* pParent = (NodeRenderableInk*)pCompound;
00718 ERROR3IF(pParent==NULL, "Can't find parent of edited attribute");
00719 if (pParent && pGrad->IsEffectAttribute())
00720 {
00721
00722
00723
00724 pParent->ReleaseCached(TRUE, FALSE, FALSE, TRUE);
00725 }
00726 else
00727 pParent->ReleaseCached();
00728 pSelView->ForceRedraw(StartSpread, pParent->GetBoundingRect(), FALSE, pGrad);
00729 GetApplication ()->ServiceRendering();
00730
00731 if (ISA_RAMPINDEX (DragControl))
00732 {
00733 GradFill->EnableBoundsRedraw();
00734 }
00735 }
00736 else
00737 {
00738 if (ISA_RAMPINDEX (DragControl))
00739 {
00740 GradFill->DisableBoundsRedraw();
00741 }
00742
00743
00744
00745
00746
00747
00748 ListItem* pAttrPtr = AttrFillGeometry::HitList.GetHead();
00749 Node* pBackMost = NULL;
00750 while (pAttrPtr != NULL)
00751 {
00752 AttrFillGeometry* pAttr = (AttrFillGeometry*)((NodeAttributePtrItem*)pAttrPtr)->NodeAttribPtr;
00753
00754
00755 NodeRenderableInk* pParent = (NodeRenderableInk*)pAttr->FindParent();
00756 ERROR3IF(pParent==NULL, "Can't find parent of edited attribute");
00757 if (pParent && pAttr->IsEffectAttribute())
00758 {
00759
00760
00761
00762 pParent->ReleaseCached(TRUE, FALSE, FALSE, TRUE);
00763 }
00764 else
00765 pParent->ReleaseCached();
00766
00767
00768 if (pBackMost==NULL || pAttr->IsUnder(pBackMost))
00769 pBackMost = pAttr;
00770
00771 pAttrPtr = AttrFillGeometry::HitList.GetNext(pAttrPtr);
00772 }
00773
00774 pSelView->ForceRedraw(StartSpread, SelBounds, FALSE, pBackMost);
00775
00776 GetApplication()->ServiceRendering();
00777
00778 if (ISA_RAMPINDEX (DragControl))
00779 {
00780 GradFill->EnableBoundsRedraw();
00781 }
00782 }
00783 }
00784 }
00785
00786
00787 Operation::SetQuickRender(FALSE);
00788 }
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801 void OpEditFill::CheckForCompoundRedraw()
00802 {
00803 CheckForCompound = FALSE;
00804
00805 pFillsDoc = StartSpread->FindOwnerDoc();
00806
00807 if (AttrFillGeometry::HitList.GetCount() == GetApplication()->FindSelection()->Count() ||
00808 AttrFillGeometry::HitList.GetCount() > 10)
00809 {
00810
00811
00812
00813 InvalidateAll = TRUE;
00814 }
00815 else
00816 {
00817
00818 InvalidateAll = FALSE;
00819 }
00820
00821 InvalidateCompound = FALSE;
00822
00823 if (AttrFillGeometry::HitList.GetCount() == 1)
00824 {
00825
00826
00827
00828
00829
00830 ListItem* pAttrPtr = AttrFillGeometry::HitList.GetHead();
00831 AttrFillGeometry* pGrad = (AttrFillGeometry*)((NodeAttributePtrItem*)pAttrPtr)->NodeAttribPtr;
00832
00833 Node* pParent = pGrad->FindParent();
00834 if (pParent == NULL)
00835 {
00836 InvalidateAll = TRUE;
00837 return;
00838 }
00839
00840 if (pParent->IsCompound())
00841 {
00842
00843 InvalidateAll = TRUE;
00844 InvalidateCompound = TRUE;
00845 pCompound = pParent;
00846 }
00847
00848
00849
00850 while (pParent != NULL && !pParent->IsLayer())
00851 {
00852 if (pParent->IS_KIND_OF(NodeBlend) || pParent->ShouldITransformWithChildren())
00853 {
00854
00855
00856 InvalidateAll = TRUE;
00857 InvalidateCompound = TRUE;
00858 pCompound = pParent;
00859
00860
00861 CallAllowOp = TRUE;
00862
00863
00864
00865 }
00866
00867 pParent = pParent->FindParent();
00868 }
00869 }
00870 }
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888 void OpEditFill::DragPointerIdle(DocCoord PointerPos, ClickModifiers ClickMods, Spread* pSpread, BOOL bSolidDrag)
00889 {
00890 if (!DragIsIdle)
00891 {
00892
00893 DragIsIdle = TRUE;
00894 DoneIdleRedraw = FALSE;
00895 Time.Sample();
00896 }
00897 else
00898 {
00899
00900 if (Time.Elapsed(IdleFillDelay))
00901 {
00902 if (DontDrawBlobs)
00903 {
00904
00905
00906
00907 DontDrawBlobs = FALSE;
00908 DragIsIdle = FALSE;
00909 RenderDragBlobs(LastDragRect, StartSpread, bSolidDrag);
00910 }
00911 else
00912 {
00913
00914
00915 if (InteractiveDragUpdate && !DoneIdleRedraw)
00916 {
00917 RedrawFills(ClickMods);
00918 DoneIdleRedraw = TRUE;
00919 }
00920 }
00921 }
00922 }
00923 }
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936 BOOL OpEditFill::DragKeyPress(KeyPress* pKeyPress, BOOL bSolidDrag)
00937 {
00938 if (pKeyPress->GetVirtKey() == CAMKEY(TAB) &&
00939 pKeyPress->IsPress() &&
00940 !pKeyPress->IsRepeat())
00941 {
00942
00943 ContinuousEOR = !ContinuousEOR;
00944 ShowDragBlobs = ContinuousEOR;
00945
00946 String_256 DragText;
00947 ClickModifiers ClickMods;
00948
00949
00950 GetStatusLineText(&DragText, StartSpread, LastMousePosition, ClickMods);
00951 GetApplication()->UpdateStatusBarText(&DragText);
00952
00953 return TRUE;
00954 }
00955 return FALSE;
00956 }
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974 void OpEditFill::DragModeChanged(BOOL bSolidDrag)
00975 {
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991 }
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014 void OpEditFill::DragFinished(DocCoord PointerPos, ClickModifiers ClickMods, Spread*, BOOL Success, BOOL bSolidDrag)
01015 {
01016 EditFinished = TRUE;
01017
01018 double APixel;
01019
01020
01021 BOOL IsOk = FALSE;
01022
01023
01024 if (!DontDrawBlobs && AttrFillGeometry::DraggedFill != NULL)
01025 {
01026 if (!(ISA_RAMPINDEX(DragControl)))
01027 {
01028 RenderDragBlobs(GradFill->GetBlobBoundingRect(), StartSpread, bSolidDrag);
01029 }
01030 else
01031 {
01032 if (ISA_RAMPINDEX (DragControl))
01033 {
01034 GradFill->DisableBoundsRedraw ();
01035 }
01036 RenderDragBlobs(GradFill->GetBlobBoundingRect(), StartSpread, bSolidDrag);
01037 if (ISA_RAMPINDEX (DragControl))
01038 {
01039 GradFill->EnableBoundsRedraw ();
01040 }
01041 }
01042 }
01043
01044 DontDrawBlobs = FALSE;
01045 BOOL HaveFailed = FALSE;
01046
01047 Document* pDoc = Document::GetSelected();
01048
01049
01050 if (ISA_RAMPINDEX(DragControl))
01051 {
01052 if (Success)
01053 {
01054 if (GradFill->GetColourRamp())
01055 {
01056 GradFill->GetColourRamp()->SortRamp();
01057 }
01058 }
01059 }
01060
01061
01062 if (!EndDrag())
01063 {
01064 delete FillClone;
01065 delete GradFill;
01066 goto EndOperation;
01067 }
01068
01069 if (*GradFill->GetStartPoint() == *GradFill->GetEndPoint())
01070 Success = FALSE;
01071
01072 APixel = (DocView::GetSelected()->GetScaledPixelWidth()).MakeDouble();
01073
01074
01075 if (PointerPos.Distance(AnchorPos) <= APixel*2)
01076 Success = FALSE;
01077
01078
01079 if (!Success || (PointerPos == AnchorPos))
01080 {
01081 if (AttrFillGeometry::DraggedFill)
01082 {
01083
01084
01085
01086 AttrFillGeometry::DraggedFill = NULL;
01087 AttrFillGeometry::EditedFill = NULL;
01088
01089
01090
01091 if (!(*GradFill == *FillClone))
01092 {
01093 *GradFill = *FillClone;
01094
01095 ListItem* pAttrPtr = AttrFillGeometry::HitList.GetHead();
01096 while (pAttrPtr != NULL)
01097 {
01098 AttrFillGeometry* pAttr = (AttrFillGeometry*)((NodeAttributePtrItem*)pAttrPtr)->NodeAttribPtr;
01099 ERROR3IF(pAttr->IsADefaultAttr(), "Default attr in hit list");
01100
01101 pAttr->SetStartPoint(FillClone->GetStartPoint());
01102 pAttr->SetEndPoint(FillClone->GetEndPoint());
01103 pAttr->SetEndPoint2(FillClone->GetEndPoint2());
01104
01105 NodeRenderableInk* pParent = (NodeRenderableInk*)pAttr->FindParent();
01106 ERROR3IF(pParent==NULL, "Can't find parent of edited attribute");
01107 if (pParent && pAttr->IsEffectAttribute())
01108 {
01109
01110
01111
01112 pParent->ReleaseCached(TRUE, FALSE, FALSE, TRUE);
01113 }
01114 else
01115 pParent->ReleaseCached();
01116
01117 pAttrPtr = AttrFillGeometry::HitList.GetNext(pAttrPtr);
01118 }
01119
01120
01121 DocRect SelBounds = GetApplication()->FindSelection()->GetBlobBoundingRect();
01122
01123 DocView::GetSelected()->ForceRedraw(StartSpread, SelBounds);
01124 }
01125
01126 }
01127 else
01128 {
01129
01130 if (ClickMods.Adjust && ClickMods.Constrain)
01131 {
01132
01133 SelectAllBlobs();
01134 }
01135
01136
01137 BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::COLOURATTCHANGED));
01138 }
01139
01140 AttrFillGeometry::LastRenderedMesh = NULL;
01141 AttrFillGeometry::HitList.DeleteAll();
01142
01143 delete FillClone;
01144 delete GradFill;
01145 goto EndOperation;
01146 }
01147
01148
01149 AttrFillGeometry::DraggedFill = NULL;
01150
01151 if (IsRequired)
01152 RenderFinalBlobs(GetDragBlobRect(), StartSpread, bSolidDrag);
01153
01154 if (AlwaysFail)
01155 {
01156
01157
01158
01159 FailAndExecute();
01160 HaveFailed = TRUE;
01161 }
01162
01163
01164 if (Success && (!GetDragBlobRect().IsEmpty()))
01165 {
01166 AttrFillGeometry::EditedFill = NULL;
01167 AttrFillGeometry::DraggedFill = NULL;
01168
01169 if (ApplyAtEnd)
01170 {
01171
01172 ApplyEditedFill();
01173
01174 delete FillClone;
01175 delete GradFill;
01176 }
01177 else
01178 {
01179 if (ShouldApplyNewFill)
01180 {
01181 ApplyNewFill();
01182 }
01183
01184 BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::COLOURATTCHANGED));
01185 BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::NONCOLOURATTCHANGED));
01186
01187 SelRange *Selection = Camelot.FindSelection();
01188 DocRect Bounds;
01189 if (Selection != NULL && Selection->Count()>0)
01190 Bounds = Selection->GetBoundingRect();
01191 else
01192 Bounds = GetDragBlobRect();
01193
01194 GradFill->SetBoundingRect(Bounds);
01195
01196
01197 if (!AttrFillGeometry::HitList.IsEmpty())
01198 {
01199 ListItem* pAttrPtr = AttrFillGeometry::HitList.GetHead();
01200
01201 while (pAttrPtr != NULL)
01202 {
01203 AttrFillGeometry* pAttr = (AttrFillGeometry*)((NodeAttributePtrItem*)pAttrPtr)->NodeAttribPtr;
01204 ERROR3IF(pAttr->IsADefaultAttr(), "Default attr in hit list");
01205
01206
01207 pAttr->SetStartPoint(GradFill->GetStartPoint());
01208 pAttr->SetEndPoint(GradFill->GetEndPoint());
01209 pAttr->SetEndPoint2(GradFill->GetEndPoint2());
01210
01211
01212 pAttr->SetBoundingRect(Bounds);
01213
01214
01215
01216
01217
01218 if (bSolidDrag)
01219 {
01220 Node* pParent = pAttr->FindParent();
01221 if (pParent && pParent->IsBounded())
01222 {
01223 ((NodeRenderableBounded*)pParent)->ReleaseCached(TRUE, FALSE, !pAttr->IsEffectAttribute(), TRUE);
01224 DoInvalidateNodeRegion((NodeRenderableBounded*)pParent, FALSE, TRUE, FALSE, FALSE);
01225
01226 }
01227 }
01228
01229 pAttrPtr = AttrFillGeometry::HitList.GetNext(pAttrPtr);
01230 }
01231 }
01232 AttributeManager& AttrMgr = pDoc->GetAttributeMgr();
01233
01234 if (AttrMgr.WeShouldMakeAttrCurrent(IsRequired,GradFill,&AttrGroups))
01235 {
01236 AttributeManager::UpdateCurrentAttr(GradFill, TRUE, &AttrGroups);
01237 }
01238
01239 delete FillClone;
01240 delete GradFill;
01241 }
01242
01243 IsOk = TRUE;
01244 }
01245
01246 EndOperation:
01247
01248
01249 AttrFillGeometry::EditedFill = NULL;
01250 AttrFillGeometry::DraggedFill = NULL;
01251 AttrFillGeometry::HitList.DeleteAll();
01252 CreateFill = FALSE;
01253
01254
01255 AttrGroups.DeleteAll();
01256
01257
01258 if (!IsOk && !HaveFailed)
01259 {
01260 FailAndExecute();
01261 }
01262
01263
01264 End();
01265 }
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278 BOOL OpEditFill::ApplyNewFill()
01279 {
01280 ShouldApplyNewFill = FALSE;
01281
01282 SelRange* pSel = GetApplication()->FindSelection();
01283 Range SelRng(*pSel);
01284
01285 BOOL bShowProgress = TRUE;
01286 #ifndef EXCLUDE_FROM_XARALX
01287 if (GetKeyState(CAMKEY(LBUTTON)) & 0x80)
01288 bShowProgress = FALSE;
01289 #endif
01290
01291
01292 if (bShowProgress)
01293 BeginSlowJob(-1, FALSE);
01294
01295 ObjChangeFlags cFlags;
01296 cFlags.Attribute = TRUE;
01297 ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,this);
01298 ObjChange.SetRetainCachedData(TRUE);
01299
01300 if (!pSel->AllowOp(&ObjChange))
01301 {
01302 if (bShowProgress)
01303 EndSlowJob();
01304 return FALSE;
01305 }
01306
01307 DoStartSelOp(FALSE,FALSE, TRUE,TRUE);
01308
01309
01310
01311
01312
01313 AttrTypeSet AttrTypes;
01314 AttrTypes.AddToSet((GradFill->GetAttributeType()));
01315
01316
01317 if (!DoInvalidateRegions(&SelRng,
01318 GradFill,
01319 TRUE,
01320 NULL,
01321 FALSE))
01322 {
01323 if (bShowProgress)
01324 EndSlowJob();
01325 return FALSE;
01326 }
01327
01328 if (!DoLocaliseForAttrChange(&SelRng, &AttrTypes))
01329 {
01330 if (bShowProgress)
01331 EndSlowJob();
01332 return FALSE;
01333 }
01334
01335
01336
01337
01338
01339 ApplyToSelection(GradFill, TRUE);
01340
01341
01342
01343 if (!DoFactorOutAfterAttrChange(&SelRng,
01344 &AttrTypes))
01345 {
01346 if (bShowProgress)
01347 EndSlowJob();
01348 return FALSE;
01349 }
01350
01351
01352 if (!DoInvalidateRegions(&SelRng,
01353 GradFill,
01354 TRUE,
01355 NULL,
01356 FALSE))
01357 {
01358 if (bShowProgress)
01359 EndSlowJob();
01360 return FALSE;
01361 }
01362
01363 AttrTypes.DeleteAll();
01364
01365 if (Document::GetSelected())
01366 Document::GetSelected()->SetModified(TRUE);
01367
01368 ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,this);
01369 ObjChange.SetRetainCachedData(TRUE);
01370 if (!UpdateChangedNodes(&ObjChange))
01371 {
01372 if (bShowProgress)
01373 EndSlowJob();
01374 return FALSE;
01375 }
01376
01377
01378 AttrFillGeometry* pFill = AttrFillGeometry::FindFirstSelectedAttr(GradFill->GetAttributeType());
01379
01380
01381
01382 while (pFill)
01383 {
01384 BOOL InList = FALSE;
01385
01386
01387
01388
01389
01390
01391 if (!AttrFillGeometry::HitList.IsEmpty())
01392 {
01393 ListItem* pItem = AttrFillGeometry::HitList.GetHead();
01394
01395 while (pItem)
01396 {
01397 NodeAttributePtrItem* NodePtr = (NodeAttributePtrItem*)pItem;
01398
01399 if (NodePtr->NodeAttribPtr == pFill)
01400 {
01401
01402 InList = TRUE;
01403 break;
01404 }
01405
01406 pItem = AttrFillGeometry::HitList.GetNext(pItem);
01407 }
01408 }
01409
01410 if (!InList)
01411 {
01412
01413 ListItem* pAttr = new NodeAttributePtrItem;
01414 if (pAttr == NULL)
01415 {
01416 if (bShowProgress)
01417 EndSlowJob();
01418 return FALSE;
01419 }
01420
01421 ERROR3IF(pFill->IsADefaultAttr(), "Default attr in hit list");
01422 ((NodeAttributePtrItem*)pAttr)->NodeAttribPtr = pFill;
01423
01424 AttrFillGeometry::HitList.AddTail(pAttr);
01425 }
01426
01427 pFill = AttrFillGeometry::FindNextSelectedAttr(GradFill->GetAttributeType());
01428 }
01429
01430 if (bShowProgress)
01431 EndSlowJob();
01432
01433 return TRUE;
01434 }
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447 BOOL OpEditFill::ApplyEditedFill()
01448 {
01449
01450 ListItem* pAttrPtr = AttrFillGeometry::HitList.GetHead();
01451 while (pAttrPtr != NULL)
01452 {
01453 AttrFillGeometry* pAttr = (AttrFillGeometry*)((NodeAttributePtrItem*)pAttrPtr)->NodeAttribPtr;
01454
01455 if (pAttr != GradFill)
01456 {
01457 pAttr->SetStartPoint(FillClone->GetStartPoint());
01458 pAttr->SetEndPoint(FillClone->GetEndPoint());
01459 pAttr->SetEndPoint2(FillClone->GetEndPoint2());
01460 pAttr->SetColourRamp(FillClone->GetColourRamp());
01461 }
01462
01463 pAttrPtr = AttrFillGeometry::HitList.GetNext(pAttrPtr);
01464 }
01465
01466 SelRange *Selection = Camelot.FindSelection();
01467
01468 DocRect Bounds;
01469 if (Selection != NULL && Selection->Count()>0)
01470 Bounds = Selection->GetBoundingRect();
01471 else
01472 Bounds = GetDragBlobRect();
01473
01474
01475 GradFill->SetBoundingRect(Bounds);
01476
01477 BeginSlowJob(-1, FALSE);
01478 AttributeManager::SendMessages = FALSE;
01479
01480
01481 AttributeManager::ReplaceAttributes(GradFill, &AttrFillGeometry::HitList);
01482 AttrFillGeometry::HitList.DeleteAll();
01483
01484
01485
01486 AttributeManager::SendMessages = TRUE;
01487 EndSlowJob();
01488
01489 return TRUE;
01490 }
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502 void OpEditFill::SelectAllBlobs()
01503 {
01504
01505 AttrFillGeometry::LastRenderedStartBlob = DocCoord(0,0);
01506 AttrFillGeometry::LastRenderedEndBlob = DocCoord(0,0);
01507 AttrFillGeometry::LastRenderedEnd2Blob = DocCoord(0,0);
01508
01509
01510 AttrFillGeometry* pSelAttr = AttrFillGeometry::FindFirstSelectedAttr(FillClone->GetAttributeType());
01511 while (pSelAttr != NULL)
01512 {
01513 if (pSelAttr)
01514 {
01515 pSelAttr->SelectBlob(DragControl);
01516 pSelAttr->DeselectAllBut(DragControl);
01517 }
01518
01519
01520 pSelAttr = AttrFillGeometry::FindNextSelectedAttr(FillClone->GetAttributeType());
01521 }
01522 }
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536 DocRect OpEditFill::GetDragBlobRect()
01537 {
01538 return GradFill->GetBlobBoundingRect();
01539 }
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554 void OpEditFill::RenderDragBlobs(DocRect Rect, Spread* pSpread, BOOL bSolidDrag)
01555 {
01556 if (DontDrawBlobs)
01557 return;
01558
01559
01560
01561 if (pSpread != StartSpread)
01562 {
01563 Rect.lo = MakeRelativeToSpread(StartSpread, pSpread, Rect.lo);
01564 Rect.hi = MakeRelativeToSpread(StartSpread, pSpread, Rect.hi);
01565 }
01566
01567 AttrFillGeometry::EditedFill = NULL;
01568
01569 RenderRegion* pRegion = DocView::RenderOnTop(&Rect, StartSpread, UnclippedEOR);
01570 while (pRegion)
01571 {
01572 GradFill->RenderFillBlobs(pRegion);
01573
01574
01575 pRegion = DocView::GetNextOnTop(&Rect);
01576 }
01577
01578 AttrFillGeometry::EditedFill = GradFill;
01579
01580
01581 AttrFillGeometry::LastRenderedMesh = NULL;
01582 }
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597 void OpEditFill::RenderSelectionFillBlobs(SelRange* pSel, DocRect Rect, Spread* pSpread)
01598 {
01599
01600 RenderRegion* pRegion = DocView::RenderOnTop(&Rect, pSpread, UnclippedEOR);
01601 while (pRegion)
01602 {
01603 Node* pNode = pSel->FindFirst();
01604
01605 while (pNode)
01606 {
01607 ((NodeRenderable*)pNode)->RenderAppliedFillBlobs(pRegion);
01608 pNode = pSel->FindNext(pNode);
01609 }
01610
01611
01612 pRegion = DocView::GetNextOnTop(&Rect);
01613 }
01614
01615 AttrFillGeometry::LastRenderedMesh = NULL;
01616 }
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631 void OpEditFill::RenderInitSelectionBlobs(SelRange* pSel, DocRect Rect, Spread* pSpread)
01632 {
01633
01634
01635
01636 RenderRegionList* pRegionList = GetApplication()->GetRegionList();
01637
01638 if (!pRegionList->IsEmpty())
01639 {
01640 RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();
01641
01642 while (pRegion)
01643 {
01644
01645 if (pRegion->GetRenderSpread() == pSpread &&
01646 (pRegion->IsInkRenderStarted || pRegion->NeedsOSPaper))
01647 {
01648
01649 DocRect ClipRect = pRegion->GetRegionRect();
01650
01651 if (ClipRect.IsIntersectedWith(Rect))
01652 {
01653 ClipRect = ClipRect.Intersection(Rect);
01654 RenderSelectionFillBlobs(pSel, ClipRect, pSpread);
01655 }
01656 }
01657
01658
01659 pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
01660 }
01661 }
01662
01663
01664 RenderSelectionFillBlobs(pSel, Rect, pSpread);
01665 }
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680 void OpEditFill::RenderFinalBlobs(DocRect Rect, Spread* pSpread, BOOL bSolidDrag)
01681 {
01682
01683 RenderDragBlobs(Rect, pSpread, bSolidDrag);
01684
01685
01686
01687
01688 RenderRegionList* pRegionList = GetApplication()->GetRegionList();
01689
01690 if (!pRegionList->IsEmpty())
01691 {
01692 RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();
01693
01694 while (pRegion)
01695 {
01696
01697 if (pRegion->GetRenderSpread() == pSpread &&
01698 (pRegion->IsInkRenderStarted || pRegion->NeedsOSPaper))
01699 {
01700
01701 DocRect ClipRect = pRegion->GetRegionRect();
01702
01703 if (ClipRect.IsIntersectedWith(Rect))
01704 {
01705 ClipRect = ClipRect.Intersection(Rect);
01706 RenderDragBlobs(ClipRect, pSpread, bSolidDrag);
01707 }
01708 }
01709
01710
01711 pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
01712 }
01713 }
01714 }
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729 void OpEditFill::RenderInitBlobs(DocRect Rect, Spread* pSpread, BOOL bSolidDrag)
01730 {
01731
01732
01733
01734 RenderRegionList* pRegionList = GetApplication()->GetRegionList();
01735
01736 if (!pRegionList->IsEmpty())
01737 {
01738 RenderRegion* pRegion = (RenderRegion*)pRegionList->GetHead();
01739
01740 while (pRegion)
01741 {
01742
01743 if (pRegion->GetRenderSpread() == pSpread &&
01744 (pRegion->IsInkRenderStarted || pRegion->NeedsOSPaper))
01745 {
01746
01747 DocRect ClipRect = pRegion->GetRegionRect();
01748
01749 if (ClipRect.IsIntersectedWith(Rect))
01750 {
01751 ClipRect = ClipRect.Intersection(Rect);
01752 RenderDragBlobs(ClipRect, pSpread, bSolidDrag);
01753 }
01754 }
01755
01756
01757 pRegion = (RenderRegion*)pRegionList->GetNext(pRegion);
01758 }
01759 }
01760
01761
01762 RenderDragBlobs(Rect, pSpread, bSolidDrag);
01763 }
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780 BOOL OpEditFill::GetStatusLineText(String_256* pText, Spread* pSpread,
01781 DocCoord DocPos, ClickModifiers ClickMods)
01782 {
01783 if (GradFill == NULL)
01784 {
01785 *pText="";
01786 return TRUE;
01787 }
01788
01789 pText->Load(_R(IDS_K_OPGRAD_EDITING));
01790
01791 String_256 FillName;
01792 if (FillName.Load(GradFill->GetAttrNameID()))
01793 {
01794
01795 *pText += FillName;
01796
01797 if (ContinuousEOR)
01798 {
01799 *pText += String_256(_R(IDS_K_OPGRAD_IMMEDIATE));
01800 }
01801 else
01802 {
01803 if (InteractiveDragUpdate)
01804 {
01805 *pText += String_256(_R(IDS_K_OPGRAD_BACKGROUND));
01806 }
01807 else
01808 {
01809 *pText += String_256(_R(IDS_K_OPGRAD_NOUPDATE));
01810 }
01811 }
01812
01813 return TRUE;
01814 }
01815
01816 return FALSE;
01817 }
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830 BOOL OpEditFill::Init()
01831 {
01832 return (RegisterOpDescriptor( 0,
01833 _R(IDS_EDITFILLOP),
01834 CC_RUNTIME_CLASS(OpEditFill),
01835 OPTOKEN_EDITFILL,
01836 OpEditFill::GetState,
01837 0,
01838 0,
01839 0 ));
01840 }
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854 OpState OpEditFill::GetState(String_256* Description, OpDescriptor*)
01855 {
01856 OpState Blobby;
01857
01858 return Blobby;
01859 }
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
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
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02142
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02320
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506 OpCreateFill::OpCreateFill()
02507 {
02508 GradFill = NULL;
02509 }
02510
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524 void OpCreateFill::DoDrag( AttrFillGeometry* Fill, Spread* pSpread, DocCoord Anchor)
02525 {
02526 DocView::SnapSelected(pSpread, &Anchor);
02527
02528
02529 StartSpread = pSpread;
02530 StartPoint = Anchor;
02531
02532
02533 LastMousePosition = Anchor;
02534
02535 GradFill = Fill;
02536
02537 GradFill->SetStartPoint(&Anchor);
02538 GradFill->SetEndPoint(&Anchor);
02539
02540 if (GradFill->GetEndPoint2() != NULL)
02541 GradFill->SetEndPoint2(&Anchor);
02542
02543
02544 BlobStyle MyBlobs;
02545 MyBlobs.Fill = TRUE;
02546 (Camelot.GetBlobManager())->RemoveInterest(MyBlobs);
02547
02548 AttrFillGeometry::DraggedFill = GradFill;
02549
02550
02551
02552 StartDrag(DRAGTYPE_AUTOSCROLL, NULL, NULL, TRUE, TRUE);
02553 }
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569 void OpCreateFill::DragPointerMove(DocCoord PointerPos, ClickModifiers ClickMods, Spread* pSpread, BOOL bSolidDrag)
02570 {
02571
02572 DocView::SnapSelected(pSpread, &PointerPos);
02573
02574
02575 if (ClickMods.Constrain)
02576 DocView::ConstrainToAngle(StartPoint, PI/4, &PointerPos);
02577
02578
02579 if (PointerPos != LastMousePosition)
02580 {
02581
02582 DocRect BoundingRect = GetDragBlobRect();
02583 RenderDragBlobs(BoundingRect, StartSpread, bSolidDrag);
02584
02585
02586 if (pSpread != StartSpread)
02587 PointerPos = MakeRelativeToSpread(StartSpread, pSpread, PointerPos);
02588
02589
02590 LastMousePosition = PointerPos;
02591
02592 DocCoord Start = StartPoint;
02593 DocCoord End = PointerPos;
02594 DocCoord End2 = MakeLineAtAngle(StartPoint, PointerPos);
02595
02596
02597
02598 if (GradFill->GetBitmap() != NULL)
02599 {
02600 BitmapInfo Info;
02601 KernelBitmap* Bmp = GradFill->GetBitmap();
02602
02603 AttrFillGeometry* Attr = AttrFillGeometry::FindFirstSelectedAttr(GradFill->GetAttributeType());
02604
02605 while (Attr != NULL)
02606 {
02607 if (Attr->GetBitmap() != NULL)
02608 {
02609 Bmp = Attr->GetBitmap();
02610 break;
02611 }
02612
02613 Attr = AttrFillGeometry::FindNextSelectedAttr(GradFill->GetAttributeType());
02614 }
02615
02616
02617 if (Bmp && Bmp->ActualBitmap)
02618 {
02619 if (Bmp->ActualBitmap->GetInfo( &Info ))
02620 {
02621 INT32 BitmapWidth = Info.RecommendedWidth;
02622 INT32 BitmapHeight = Info.RecommendedHeight;
02623
02624
02625 double Ratio = double(BitmapHeight)/double(BitmapWidth);
02626
02627 End2 = MakeLineAtAngle(Start, End, 90, INT32(Start.Distance(End) * Ratio));
02628 }
02629 }
02630 }
02631
02632 if (GradFill->IsKindOf(CC_RUNTIME_CLASS(AttrBitmapFill)))
02633 {
02634
02635
02636 GetBitmapRealPoints(Start, End, End2,
02637 &Start, &End, &End2);
02638 }
02639
02640
02641 GradFill->SetStartPoint(&Start);
02642 GradFill->SetEndPoint(&End);
02643 if (GradFill->GetEndPoint2() != NULL)
02644 GradFill->SetEndPoint2(&End2);
02645
02646 BoundingRect = GetDragBlobRect();
02647
02648
02649 RenderDragBlobs(BoundingRect, StartSpread, bSolidDrag);
02650 }
02651 }
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668
02669 void OpCreateFill::DragFinished(DocCoord PointerPos, ClickModifiers, Spread* pSpread, BOOL Success, BOOL bSolidDrag)
02670 {
02671
02672 BeginSlowJob();
02673
02674 DocRect DragRect;
02675
02676
02677 DocRect BoundingRect = GetDragBlobRect();
02678 RenderDragBlobs(BoundingRect, StartSpread, bSolidDrag);
02679
02680
02681 FIXED16 ScaledPixelWidth,
02682 ScaledPixelHeight;
02683 GetWorkingView()->GetScaledPixelSize(&ScaledPixelWidth, &ScaledPixelHeight);
02684
02685 INT32 PixWidth = ScaledPixelWidth.MakeLong();
02686 INT32 PixHeight = ScaledPixelHeight.MakeLong();
02687
02688
02689 BOOL IsOk = FALSE;
02690
02691
02692 if (!EndDrag())
02693 goto EndOperation;
02694
02695 if (PointerPos == StartPoint)
02696 goto EndOperation;
02697
02698 if (*GradFill->GetStartPoint() == *GradFill->GetEndPoint())
02699 goto EndOperation;
02700
02701 DragRect.IncludePoint(StartPoint);
02702 DragRect.IncludePoint(PointerPos);
02703
02704 if (DragRect.Width() < PixWidth*2 && DragRect.Height() < PixHeight*2)
02705 {
02706 TRACEUSER( "Will", _T("Drag rect too small\n"));
02707 goto EndOperation;
02708 }
02709
02710
02711 if (Success && (!DragRect.IsEmpty()))
02712 {
02713 if (GradFill != NULL)
02714 {
02715 CCRuntimeClass* CurrentAttribGroup =
02716 Tool::GetCurrent()->Parent->m_ToolInfo.CurrentAttributeGroup;
02717
02718 Document* CurrentDoc = Document::GetSelected();
02719
02720 AttrFillGeometry* CurrentAttr = (AttrFillGeometry*)(CurrentDoc->GetAttributeMgr()
02721 .GetCurrentAttribute(CurrentAttribGroup, GradFill->GetAttributeType()));
02722
02723
02724 if (CurrentAttr != NULL)
02725 {
02726 BOOL Locked = ((FillGeometryAttribute*)GradFill->GetAttributeValue())->IsAspectLocked();
02727
02728
02729 *((FillGeometryAttribute*)GradFill->GetAttributeValue()) =
02730 *((FillGeometryAttribute*)CurrentAttr->GetAttributeValue());
02731
02732 ((FillGeometryAttribute*)GradFill->GetAttributeValue())->SetAspectLock(Locked);
02733
02734 DocCoord Start = StartPoint;
02735 DocCoord End = LastMousePosition;
02736 DocCoord End2 = MakeLineAtAngle(StartPoint, LastMousePosition);
02737
02738
02739
02740 if (GradFill->GetBitmap() != NULL)
02741 {
02742 BitmapInfo Info;
02743 KernelBitmap* Bmp = GradFill->GetBitmap();
02744
02745 AttrFillGeometry* Attr = AttrFillGeometry::FindFirstSelectedAttr(GradFill->GetAttributeType());
02746
02747 while (Attr != NULL)
02748 {
02749 if (Attr->GetBitmap() != NULL)
02750 {
02751 Bmp = Attr->GetBitmap();
02752 break;
02753 }
02754
02755 Attr = AttrFillGeometry::FindNextSelectedAttr(GradFill->GetAttributeType());
02756 }
02757
02758
02759 if (Bmp && Bmp->ActualBitmap)
02760 {
02761 if (Bmp->ActualBitmap->GetInfo( &Info ))
02762 {
02763 INT32 BitmapWidth = Info.RecommendedWidth;
02764 INT32 BitmapHeight = Info.RecommendedHeight;
02765
02766
02767 double Ratio = double(BitmapHeight)/double(BitmapWidth);
02768
02769 End2 = MakeLineAtAngle(Start, End, 90, INT32(Start.Distance(End) * Ratio));
02770 }
02771 }
02772 }
02773
02774 if (GradFill->IsKindOf(CC_RUNTIME_CLASS(AttrBitmapFill)))
02775 {
02776
02777
02778 GetBitmapRealPoints(Start, End, End2,
02779 &Start, &End, &End2);
02780 }
02781
02782
02783 GradFill->SetStartPoint(&Start);
02784 GradFill->SetEndPoint(&End);
02785
02786 if (GradFill->GetEndPoint2() != NULL)
02787 GradFill->SetEndPoint2(&End2);
02788 }
02789 else
02790 {
02791
02792 *GradFill->GetStartColour() = DocColour(COLOUR_WHITE);
02793 *GradFill->GetEndColour() = DocColour(COLOUR_BLACK);
02794 }
02795
02796 if (GradFill->GetAttributeType() == CC_RUNTIME_CLASS(AttrTranspFillGeometry))
02797 {
02798 UINT32 Start = 0;
02799 UINT32 End = 255;
02800
02801 GradFill->SetStartTransp(&Start);
02802 GradFill->SetEndTransp(&End);
02803 }
02804
02805 SelRange *Selection = Camelot.FindSelection();
02806 DocRect Bounds;
02807 if (Selection != NULL && Selection->Count()>0)
02808 Bounds = Selection->GetBoundingRect();
02809 else
02810 Bounds = GetDragBlobRect();
02811
02812
02813 GradFill->SetBoundingRect(Bounds);
02814
02815 GradFill->SelectBlob(FILLCONTROL_ENDPOINT);
02816
02817
02818 AttributeManager::SendMessages = FALSE;
02819 AttributeManager::AttributeSelected(GradFill);
02820 AttributeManager::SendMessages = TRUE;
02821
02822 IsOk = TRUE;
02823 }
02824 }
02825
02826 EndOperation:
02827
02828 if (!IsOk)
02829 {
02830 delete GradFill;
02831 FailAndExecute();
02832 }
02833
02834 AttrFillGeometry::DraggedFill = NULL;
02835
02836
02837 BlobStyle MyBlobs;
02838 MyBlobs.Fill = TRUE;
02839 (Camelot.GetBlobManager())->AddInterest(MyBlobs);
02840
02841 AttrFillGeometry::SelectionCount = AttrFillGeometry::CountSelectionControlPoints();
02842
02843 BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::COLOURATTCHANGED));
02844
02845 BROADCAST_TO_ALL(SelChangingMsg(SelChangingMsg::NONCOLOURATTCHANGED));
02846
02847
02848 End();
02849 }
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863 void OpCreateFill::RenderDragBlobs(DocRect Rect, Spread* pSpread, BOOL bSolidDrag)
02864 {
02865
02866
02867 if (pSpread != StartSpread)
02868 {
02869 Rect.lo = MakeRelativeToSpread(StartSpread, pSpread, Rect.lo);
02870 Rect.hi = MakeRelativeToSpread(StartSpread, pSpread, Rect.hi);
02871 }
02872
02873 RenderRegion* pRegion = DocView::RenderOnTop(&Rect, StartSpread, UnclippedEOR);
02874 while (pRegion)
02875 {
02876 GradFill->RenderFillBlobs(pRegion);
02877
02878
02879 pRegion = DocView::GetNextOnTop(&Rect);
02880 }
02881
02882
02883 AttrFillGeometry::LastRenderedMesh = NULL;
02884 }
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898 DocRect OpCreateFill::GetDragBlobRect()
02899 {
02900 return GradFill->GetBlobBoundingRect();
02901 }
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913
02914 BOOL OpCreateFill::Init()
02915 {
02916 return (RegisterOpDescriptor( 0,
02917 _R(IDS_CREATEFILLOP),
02918 CC_RUNTIME_CLASS(OpCreateFill),
02919 OPTOKEN_GRADFILL,
02920 OpCreateFill::GetState,
02921 0,
02922 0,
02923 0 ));
02924 }
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937 OpState OpCreateFill::GetState(String_256* Description, OpDescriptor*)
02938 {
02939 OpState Blobby;
02940
02941 return Blobby;
02942 }
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952
02953
02954
02955
02956
02957
02958
02959 BOOL OpCreateFill::GetStatusLineText(String_256* pText, Spread* pSpread,
02960 DocCoord DocPos, ClickModifiers ClickMods)
02961 {
02962 if (GradFill == NULL)
02963 {
02964 *pText="";
02965 return TRUE;
02966 }
02967
02968 pText->Load(_R(IDS_K_OPGRAD_CREATENEW));
02969
02970 String_256 FillName;
02971 if (FillName.Load(GradFill->GetAttrNameID()))
02972 {
02973
02974 *pText += FillName;
02975
02976 return TRUE;
02977 }
02978
02979 return FALSE;
02980 }
02981
02982
02983 #endif // STANDALONE
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010 void MakeMeshArrow(Path* ArrowPath, DocCoord &Start, DocCoord &End, DocCoord* LineEnd)
03011 {
03012 #if !defined(EXCLUDE_FROM_RALPH)
03013
03014 const INT32 dx = Start.x - End.x;
03015 const INT32 dy = Start.y - End.y;
03016
03017 if ( (dy==0) && (dx==0) )
03018 {
03019 ArrowPath->InsertMoveTo(End);
03020 ArrowPath->InsertLineTo(End);
03021 ArrowPath->TryToClose();
03022
03023 *LineEnd = End;
03024 return;
03025 }
03026
03027 double ArrowAngle;
03028
03029 if ( (dx>=0) && (dy>=0) )
03030 ArrowAngle = PI - atan2( (double)dx, (double)dy );
03031 else if ( (dx<0) && (dy>=0) )
03032 ArrowAngle = -PI + atan2( (double)-dx, (double)dy );
03033 else if ( (dx<0) && (dy<0) )
03034 ArrowAngle = -atan2( (double)-dx, (double)-dy );
03035 else if ( (dx>=0) && (dy<0) )
03036 ArrowAngle = atan2( (double)dx, (double)-dy );
03037 else
03038 {
03039 TRACE( _T("invalid angle on arrowhead\n"));
03040 return;
03041 }
03042
03043 ANGLE RotateAngle = 360 * (ArrowAngle / (2*PI));
03044
03045 Matrix ArrowMatrix = Matrix(RotateAngle);
03046 ArrowMatrix *= Matrix(End);
03047
03048 const UINT32 PointCount = 4;
03049 Coord ArrowPts[PointCount];
03050
03051 INT32 BlobSize = (Camelot.GetBlobManager())->GetBlobSize();
03052
03053 INT32 ArrowWidth = (BlobSize * 3)/2;
03054 INT32 ArrowHeight = (BlobSize * 3)/2;
03055
03056 ArrowPts[0] = Coord( 0, 0);
03057 ArrowPts[1] = Coord( -ArrowWidth/2, -ArrowHeight);
03058 ArrowPts[2] = Coord( ArrowWidth/2, -ArrowHeight);
03059 ArrowPts[3] = Coord( 0, -ArrowHeight);
03060
03061 ArrowMatrix.transform(ArrowPts, PointCount);
03062
03063 ArrowPath->InsertMoveTo(DocCoord(ArrowPts[0].x, ArrowPts[0].y));
03064 ArrowPath->InsertLineTo(DocCoord(ArrowPts[1].x, ArrowPts[1].y));
03065 ArrowPath->InsertLineTo(DocCoord(ArrowPts[2].x, ArrowPts[2].y));
03066 ArrowPath->InsertLineTo(DocCoord(ArrowPts[0].x, ArrowPts[0].y));
03067 ArrowPath->TryToClose();
03068
03069 *LineEnd = DocCoord(ArrowPts[3].x, ArrowPts[3].y);
03070 #endif
03071 }
03072
03073
03074
03075
03076
03077
03078
03079
03080
03081
03082
03083
03084
03085
03086 void MakeMeshDottedLine(Path* ArrowPath, DocCoord &Start, DocCoord &End)
03087 {
03088 #if !defined(EXCLUDE_FROM_RALPH)
03089 ArrowPath->InsertMoveTo(Start);
03090 ArrowPath->InsertLineTo(End);
03091 #endif
03092 }
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102
03103
03104
03105
03106 void MakeMeshSemiCircle(Path* EllipsePath, DocCoord Start, DocCoord End, DocCoord ArrowPoint)
03107 {
03108 #if !defined(EXCLUDE_FROM_RALPH)
03109 End = MakeLineAtAngle(Start, End, 180);
03110 DocCoord End2 = MakeLineAtAngle(Start, End);
03111
03112 ANGLE LineAngle = CalcLineAngle(Start, End);
03113 Matrix Rotate = Matrix(-LineAngle);
03114
03115 End.translate(-Start.x, -Start.y);
03116 End2.translate(-Start.x, -Start.y);
03117
03118 Rotate.transform(&End);
03119 Rotate.transform(&End2);
03120
03121 End.translate(Start.x, Start.y);
03122 End2.translate(Start.x, Start.y);
03123
03124 DocCoord Parallel[4];
03125
03126 INT32 dx = End2.x - Start.x;
03127 INT32 dy = Start.y - End.y;
03128
03129
03130 Parallel[0] = DocCoord(Start.x - dx, Start.y - dy);
03131 Parallel[1] = DocCoord(Start.x + dx, Start.y - dy);
03132 Parallel[2] = DocCoord(Start.x + dx, Start.y + dy);
03133 Parallel[3] = DocCoord(Start.x - dx, Start.y + dy);
03134
03135
03136 DocCoord NewCoords[12];
03137
03138
03139 CalcMeshEllipseEdge(Parallel[0], Parallel[1], &NewCoords[11], &NewCoords[0], &NewCoords[1]);
03140 CalcMeshEllipseEdge(Parallel[1], Parallel[2], &NewCoords[2], &NewCoords[3], &NewCoords[4]);
03141 CalcMeshEllipseEdge(Parallel[2], Parallel[3], &NewCoords[5], &NewCoords[6], &NewCoords[7]);
03142 CalcMeshEllipseEdge(Parallel[3], Parallel[0], &NewCoords[8], &NewCoords[9], &NewCoords[10]);
03143
03144 Matrix Rotate2 = Matrix(LineAngle);
03145
03146 for (INT32 i=0; i<12; i++)
03147 {
03148 NewCoords[i].translate(-Start.x, -Start.y);
03149 Rotate2.transform(&NewCoords[i]);
03150 NewCoords[i].translate(Start.x, Start.y);
03151 }
03152
03153
03154 EllipsePath->ClearPath();
03155 EllipsePath->FindStartOfPath();
03156
03157
03158
03159
03160
03161
03162 EllipsePath->InsertMoveTo(ArrowPoint);
03163 EllipsePath->InsertCurveTo(NewCoords[7], NewCoords[8], NewCoords[9]);
03164 EllipsePath->InsertCurveTo(NewCoords[10], NewCoords[11], NewCoords[0]);
03165
03166
03167
03168 #endif
03169 }
03170
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183 DocRect GetMeshSemiCircleBounds(DocCoord Start, DocCoord End, DocCoord EndPoint)
03184 {
03185 #if !defined(EXCLUDE_FROM_RALPH)
03186 DocCoord End2 = MakeLineAtAngle(Start, End);
03187
03188 ANGLE LineAngle = CalcLineAngle(Start, End);
03189 Matrix Rotate = Matrix(-LineAngle);
03190
03191 End.translate(-Start.x, -Start.y);
03192 End2.translate(-Start.x, -Start.y);
03193
03194 Rotate.transform(&End);
03195 Rotate.transform(&End2);
03196
03197 End.translate(Start.x, Start.y);
03198 End2.translate(Start.x, Start.y);
03199
03200 DocCoord Parallel[4];
03201
03202 INT32 dx = End2.x - Start.x;
03203 INT32 dy = Start.y - End.y;
03204
03205
03206 Parallel[0] = DocCoord(Start.x - dx, Start.y - dy);
03207 Parallel[1] = DocCoord(Start.x + dx, Start.y - dy);
03208 Parallel[2] = DocCoord(Start.x + dx, Start.y + dy);
03209 Parallel[3] = DocCoord(Start.x - dx, Start.y + dy);
03210
03211
03212 DocCoord NewCoords[12];
03213
03214
03215 CalcMeshEllipseEdge(Parallel[0], Parallel[1], &NewCoords[11], &NewCoords[0], &NewCoords[1]);
03216 CalcMeshEllipseEdge(Parallel[1], Parallel[2], &NewCoords[2], &NewCoords[3], &NewCoords[4]);
03217 CalcMeshEllipseEdge(Parallel[2], Parallel[3], &NewCoords[5], &NewCoords[6], &NewCoords[7]);
03218 CalcMeshEllipseEdge(Parallel[3], Parallel[0], &NewCoords[8], &NewCoords[9], &NewCoords[10]);
03219
03220 Matrix Rotate2 = Matrix(LineAngle);
03221
03222 for (INT32 i=0; i<12; i++)
03223 {
03224 NewCoords[i].translate(-Start.x, -Start.y);
03225 Rotate2.transform(&NewCoords[i]);
03226 NewCoords[i].translate(Start.x, Start.y);
03227 }
03228
03229 DocRect Bounds = DocRect(EndPoint, EndPoint);
03230 Bounds.IncludePoint(NewCoords[6]);
03231 Bounds.IncludePoint(NewCoords[7]);
03232 Bounds.IncludePoint(NewCoords[8]);
03233 Bounds.IncludePoint(NewCoords[9]);
03234 Bounds.IncludePoint(NewCoords[10]);
03235 Bounds.IncludePoint(NewCoords[11]);
03236
03237 return Bounds;
03238 #else
03239 return DocRect(0,0,0,0);
03240 #endif
03241 }
03242
03243
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253
03254
03255 void MakeMeshEllipse(Path* EllipsePath, DocCoord Start, DocCoord End, DocCoord End2)
03256 {
03257 #if !defined(EXCLUDE_FROM_RALPH)
03258 if (End2 == DocCoord(0,0))
03259 {
03260 End2 = MakeLineAtAngle(Start, End);
03261 }
03262
03263 ANGLE LineAngle = CalcLineAngle(Start, End);
03264 Matrix Rotate = Matrix(-LineAngle);
03265
03266 End.translate(-Start.x, -Start.y);
03267 End2.translate(-Start.x, -Start.y);
03268
03269 Rotate.transform(&End);
03270 Rotate.transform(&End2);
03271
03272 End.translate(Start.x, Start.y);
03273 End2.translate(Start.x, Start.y);
03274
03275 DocCoord Parallel[4];
03276
03277 INT32 dx = End2.x - Start.x;
03278 INT32 dy = Start.y - End.y;
03279
03280
03281 Parallel[0] = DocCoord(Start.x - dx, Start.y - dy);
03282 Parallel[1] = DocCoord(Start.x + dx, Start.y - dy);
03283 Parallel[2] = DocCoord(Start.x + dx, Start.y + dy);
03284 Parallel[3] = DocCoord(Start.x - dx, Start.y + dy);
03285
03286
03287 DocCoord NewCoords[12];
03288
03289
03290 CalcMeshEllipseEdge(Parallel[0], Parallel[1], &NewCoords[11], &NewCoords[0], &NewCoords[1]);
03291 CalcMeshEllipseEdge(Parallel[1], Parallel[2], &NewCoords[2], &NewCoords[3], &NewCoords[4]);
03292 CalcMeshEllipseEdge(Parallel[2], Parallel[3], &NewCoords[5], &NewCoords[6], &NewCoords[7]);
03293 CalcMeshEllipseEdge(Parallel[3], Parallel[0], &NewCoords[8], &NewCoords[9], &NewCoords[10]);
03294
03295 Matrix Rotate2 = Matrix(LineAngle);
03296
03297 for (INT32 i=0; i<12; i++)
03298 {
03299 NewCoords[i].translate(-Start.x, -Start.y);
03300 Rotate2.transform(&NewCoords[i]);
03301 NewCoords[i].translate(Start.x, Start.y);
03302 }
03303
03304
03305 EllipsePath->ClearPath();
03306 EllipsePath->FindStartOfPath();
03307
03308
03309 EllipsePath->InsertMoveTo(NewCoords[0]);
03310 EllipsePath->InsertCurveTo(NewCoords[1], NewCoords[2], NewCoords[3]);
03311 EllipsePath->InsertCurveTo(NewCoords[4], NewCoords[5], NewCoords[6]);
03312 EllipsePath->InsertCurveTo(NewCoords[7], NewCoords[8], NewCoords[9]);
03313 EllipsePath->InsertCurveTo(NewCoords[10], NewCoords[11], NewCoords[0]);
03314
03315
03316 EllipsePath->CloseSubPath();
03317 #endif
03318 }
03319
03320
03321
03322
03323
03324
03325
03326
03327
03328
03329
03330
03331
03332
03333 void CalcMeshEllipseEdge(const DocCoord& P0, const DocCoord& P1, DocCoord* NewCoordA,
03334 DocCoord* NewCoordB, DocCoord* NewCoordC)
03335 {
03336 #if !defined(EXCLUDE_FROM_RALPH)
03337
03338
03339 INT32 dx = P1.x - P0.x;
03340 INT32 dy = P1.y - P0.y;
03341
03342
03343
03344
03345
03346
03347
03348
03349 double ControlDist = 1.0 / (2 * 2.2336);
03350
03351
03352 NewCoordA->x = (INT32) (P0.x + (dx * ControlDist));
03353 NewCoordA->y = (INT32) (P0.y + (dy * ControlDist));
03354
03355
03356 NewCoordB->x = (INT32) (P0.x + (dx / 2));
03357 NewCoordB->y = (INT32) (P0.y + (dy / 2));
03358
03359
03360 NewCoordC->x = (INT32) (P1.x - dx * ControlDist);
03361 NewCoordC->y = (INT32) (P1.y - dy * ControlDist);
03362 #endif
03363 }
03364
03365
03366
03367
03368
03369
03370
03371
03372
03373
03374
03375
03376
03377 DocRect GetMeshEllipseBounds(DocCoord Start, DocCoord End, DocCoord End2)
03378 {
03379 #if !defined(EXCLUDE_FROM_RALPH)
03380 if (End2 == DocCoord(0,0))
03381 {
03382 End2 = MakeLineAtAngle(Start, End);
03383 }
03384
03385 ANGLE LineAngle = CalcLineAngle(Start, End);
03386 Matrix Rotate = Matrix(-LineAngle);
03387
03388 End.translate(-Start.x, -Start.y);
03389 End2.translate(-Start.x, -Start.y);
03390
03391 Rotate.transform(&End);
03392 Rotate.transform(&End2);
03393
03394 End.translate(Start.x, Start.y);
03395 End2.translate(Start.x, Start.y);
03396
03397 DocCoord Parallel[4];
03398
03399 INT32 dx = End2.x - Start.x;
03400 INT32 dy = Start.y - End.y;
03401
03402
03403 Parallel[0] = DocCoord(Start.x - dx, Start.y - dy);
03404 Parallel[1] = DocCoord(Start.x + dx, Start.y - dy);
03405 Parallel[2] = DocCoord(Start.x + dx, Start.y + dy);
03406 Parallel[3] = DocCoord(Start.x - dx, Start.y + dy);
03407
03408 Matrix Rotate2 = Matrix(LineAngle);
03409
03410 for (INT32 i=0; i<4; i++)
03411 {
03412 Parallel[i].translate(-Start.x, -Start.y);
03413 Rotate2.transform(&Parallel[i]);
03414 Parallel[i].translate(Start.x, Start.y);
03415 }
03416
03417 DocRect Bounds = DocRect(Parallel[0], Parallel[0]);
03418 Bounds.IncludePoint(Parallel[1]);
03419 Bounds.IncludePoint(Parallel[2]);
03420 Bounds.IncludePoint(Parallel[3]);
03421
03422 return Bounds;
03423 #else
03424 return DocRect(0,0,0,0);
03425 #endif
03426 }
03427
03428
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438
03439
03440
03441 void MakePerpendicularMeshLines(DocCoord Start, DocCoord End,
03442 DocRect Bounds, DocCoord* PointArray)
03443 {
03444 #if !defined(EXCLUDE_FROM_RALPH)
03445 INT32 Infinity = max(Bounds.Width(), Bounds.Height());
03446
03447 PointArray[0] = MakeLineAtAngle(Start, End, 90, Infinity);
03448 PointArray[1] = MakeLineAtAngle(Start, End, -90, Infinity);
03449 PointArray[2] = MakeLineAtAngle(End, Start, 90, Infinity);
03450 PointArray[3] = MakeLineAtAngle(End, Start, -90, Infinity);
03451 #endif
03452 }
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467 DocCoord MakeLineAtAngle(DocCoord Start, DocCoord End, ANGLE Offset, INT32 Length)
03468 {
03469 const INT32 dx = End.x - Start.x;
03470 const INT32 dy = End.y - Start.y;
03471
03472 if ( (dy==0) && (dx==0) )
03473 {
03474 return End;
03475 }
03476
03477 DocCoord End2;
03478
03479 if (Length == 0 && Offset == ANGLE(90))
03480 {
03481 End2.x = Start.x - (End.y - Start.y);
03482 End2.y = Start.y + (End.x - Start.x);
03483
03484 return End2;
03485 }
03486 else if (Length == 0 && Offset == ANGLE(-90))
03487 {
03488 End2.x = Start.x + (End.y - Start.y);
03489 End2.y = Start.y - (End.x - Start.x);
03490
03491 return End2;
03492 }
03493 else if (Length == 0 && (Offset == ANGLE(180) || Offset == ANGLE(-180)))
03494 {
03495 End2.x = Start.x - (End.x - Start.x);
03496 End2.y = Start.y - (End.y - Start.y);
03497
03498 return End2;
03499 }
03500
03501 double LineAngle=0;
03502
03503 if ( (dx>=0) && (dy>=0) )
03504 LineAngle = PI - atan2( (double)dx, (double)dy );
03505 else if ( (dx<0) && (dy>=0) )
03506 LineAngle = -PI + atan2( (double)-dx, (double)dy );
03507 else if ( (dx<0) && (dy<0) )
03508 LineAngle = -atan2( (double)-dx, (double)-dy );
03509 else if ( (dx>=0) && (dy<0) )
03510 LineAngle = atan2( (double)dx, (double)-dy );
03511
03512 ANGLE RotateAngle = 360 * (LineAngle / (2*PI));
03513
03514 double Length1 = Length;
03515 double Length2 = Start.Distance(End);
03516
03517 if ( INT32(Length2) == 0)
03518 return End;
03519
03520 if ( INT32(Length1) == 0)
03521 Length1 = Length2;
03522
03523 FIXED16 LineScale = FIXED16(Length1/Length2);
03524
03525 Matrix Rotate1 = Matrix(-RotateAngle);
03526 Matrix Rotate2 = Matrix(RotateAngle + Offset);
03527 Matrix Scale = Matrix(LineScale, LineScale);
03528
03529 End2 = End;
03530
03531 End2.translate(-Start.x, -Start.y);
03532 Rotate1.transform(&End2);
03533 Scale.transform(&End2);
03534 Rotate2.transform(&End2);
03535 End2.translate(Start.x, Start.y);
03536
03537 return End2;
03538 }
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552 ANGLE CalcLineAngle(DocCoord Start, DocCoord End)
03553 {
03554 const INT32 dx = End.x - Start.x;
03555 const INT32 dy = End.y - Start.y;
03556
03557 if ( (dy==0) && (dx==0) )
03558 {
03559 return 0;
03560 }
03561
03562 double LineAngle=0;
03563
03564 if ( (dx>=0) && (dy>=0) )
03565 LineAngle = PI - atan2( (double)dx, (double)dy );
03566 else if ( (dx<0) && (dy>=0) )
03567 LineAngle = -PI + atan2( (double)-dx, (double)dy );
03568 else if ( (dx<0) && (dy<0) )
03569 LineAngle = -atan2( (double)-dx, (double)-dy );
03570 else if ( (dx>=0) && (dy<0) )
03571 LineAngle = atan2( (double)dx, (double)-dy );
03572
03573 return 360 * (LineAngle / (2*PI));
03574 }
03575
03576
03577
03578
03579
03580
03581
03582
03583
03584
03585
03586
03587
03588 DocCoord CentreOf(DocRect Rect)
03589 {
03590 return DocCoord(Rect.lo.x + (Rect.Width()/2), Rect.lo.y + (Rect.Height()/2));
03591 }
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601
03602
03603
03604
03605 void MakeMeshParallelagram(Path* ParaPath, DocCoord Start, DocCoord End, DocCoord End2)
03606 {
03607 #if !defined(EXCLUDE_FROM_RALPH)
03608 INT32 dx1 = (End2.x - Start.x);
03609 INT32 dy1 = (End2.y - Start.y);
03610
03611 INT32 dx2 = (End.x - Start.x);
03612 INT32 dy2 = (Start.y - End.y);
03613
03614
03615 ParaPath->ClearPath();
03616 ParaPath->FindStartOfPath();
03617
03618 ParaPath->InsertMoveTo(DocCoord(Start.x + dx1 + dx2, Start.y + dy1 - dy2));
03619 ParaPath->InsertLineTo(DocCoord(Start.x - dx1 + dx2, Start.y - dy1 - dy2));
03620 ParaPath->InsertLineTo(DocCoord(Start.x - dx1 - dx2, Start.y - dy1 + dy2));
03621 ParaPath->InsertLineTo(DocCoord(Start.x + dx1 - dx2, Start.y + dy1 + dy2));
03622 ParaPath->InsertLineTo(DocCoord(Start.x + dx1 + dx2, Start.y + dy1 - dy2));
03623 #endif
03624 }
03625
03626
03627
03628
03629
03630
03631
03632
03633
03634
03635
03636
03637
03638
03639
03640 void GetMeshParallelagram(DocCoord Start, DocCoord End, DocCoord End2,
03641 DocCoord* P1, DocCoord* P2, DocCoord* P3, DocCoord* P4)
03642 {
03643 #if !defined(EXCLUDE_FROM_RALPH)
03644 INT32 dx1 = (End2.x - Start.x);
03645 INT32 dy1 = (End2.y - Start.y);
03646
03647 INT32 dx2 = (End.x - Start.x);
03648 INT32 dy2 = (Start.y - End.y);
03649
03650 *P1 = DocCoord(Start.x + dx1 + dx2, Start.y + dy1 - dy2);
03651 *P2 = DocCoord(Start.x - dx1 + dx2, Start.y - dy1 - dy2);
03652 *P3 = DocCoord(Start.x - dx1 - dx2, Start.y - dy1 + dy2);
03653 *P4 = DocCoord(Start.x + dx1 - dx2, Start.y + dy1 + dy2);
03654 #endif
03655 }
03656
03657
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668
03669 DocRect GetParallelagramBounds(DocCoord Start, DocCoord End, DocCoord End2)
03670 {
03671 DocCoord P1(0,0);
03672 DocCoord P2;
03673 DocCoord P3;
03674 DocCoord P4;
03675
03676 GetMeshParallelagram(Start, End, End2, &P1, &P2, &P3, &P4);
03677
03678 DocRect Bounds = DocRect(P1, P1);
03679
03680 Bounds.IncludePoint(P2);
03681 Bounds.IncludePoint(P3);
03682 Bounds.IncludePoint(P4);
03683
03684 return Bounds;
03685 }
03686
03687
03688
03689
03690
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700
03701 void GetBitmapVirtualPoints(DocCoord Start, DocCoord End, DocCoord End2,
03702 DocCoord* P1, DocCoord* P2, DocCoord* P3)
03703 {
03704 #if !defined(EXCLUDE_FROM_RALPH)
03705 double dx1 = (End2.x - Start.x);
03706 double dy1 = (End2.y - Start.y);
03707
03708 double dx2 = (End.x - Start.x);
03709 double dy2 = (Start.y - End.y);
03710
03711 if (P1 != NULL && (Start != DocCoord(0,0)))
03712 *P1 = DocCoord(INT32(double(Start.x) + dx1/2 + dx2/2), INT32(double(Start.y) + dy1/2 - dy2/2));
03713 if (P2 != NULL && (End != DocCoord(0,0)))
03714 *P2 = DocCoord(INT32(double(Start.x) + dx1/2 + dx2), INT32(double(Start.y) + dy1/2 - dy2));
03715 if (P3 != NULL && (End2 != DocCoord(0,0)))
03716 *P3 = DocCoord(INT32(double(Start.x) + dx1 + dx2/2), INT32(double(Start.y) + dy1 - dy2/2));
03717 #endif
03718 }
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731
03732
03733 void GetBitmapRealPoints(DocCoord Start, DocCoord End, DocCoord End2,
03734 DocCoord* P1, DocCoord* P2, DocCoord* P3)
03735 {
03736 #if !defined(EXCLUDE_FROM_RALPH)
03737 INT32 dx1 = (End2 == DocCoord(0,0)) ? 0 : (End2.x - Start.x);
03738 INT32 dy1 = (End2 == DocCoord(0,0)) ? 0 : (End2.y - Start.y);
03739
03740 INT32 dx2 = (End.x - Start.x);
03741 INT32 dy2 = (Start.y - End.y);
03742
03743 if (P1 != NULL && (Start != DocCoord(0,0)))
03744 *P1 = DocCoord(Start.x - dx1 - dx2, Start.y - dy1 + dy2);
03745 if (P2 != NULL && (End != DocCoord(0,0)))
03746 *P2 = DocCoord(Start.x - dx1 + dx2, Start.y - dy1 - dy2);
03747 if (P3 != NULL && (End2 != DocCoord(0,0)))
03748 *P3 = DocCoord(Start.x + dx1 - dx2, Start.y + dy1 + dy2);
03749 #endif
03750 }
03751
03752
03753
03754
03755
03756
03757
03758
03759
03760
03761
03762
03763
03764 void IncludeArrowHead(DocRect* Bounds, DocCoord Start, DocCoord End)
03765 {
03766 #if !defined(EXCLUDE_FROM_RALPH)
03767
03768 const INT32 dx = Start.x - End.x;
03769 const INT32 dy = Start.y - End.y;
03770
03771 if ( (dy==0) && (dx==0) )
03772 {
03773 return;
03774 }
03775
03776 double ArrowAngle;
03777
03778 if ( (dx>=0) && (dy>=0) )
03779 ArrowAngle = PI - atan2( (double)dx, (double)dy );
03780 else if ( (dx<0) && (dy>=0) )
03781 ArrowAngle = -PI + atan2( (double)-dx, (double)dy );
03782 else if ( (dx<0) && (dy<0) )
03783 ArrowAngle = -atan2( (double)-dx, (double)-dy );
03784 else if ( (dx>=0) && (dy<0) )
03785 ArrowAngle = atan2( (double)dx, (double)-dy );
03786 else
03787 {
03788 TRACE( _T("invalid angle on arrowhead\n"));
03789 return;
03790 }
03791
03792 ANGLE RotateAngle = 360 * (ArrowAngle / (2*PI));
03793
03794 Matrix ArrowMatrix = Matrix(RotateAngle);
03795 ArrowMatrix *= Matrix(End);
03796
03797 const UINT32 PointCount = 3;
03798 Coord ArrowPts[PointCount];
03799
03800 INT32 BlobSize = (Camelot.GetBlobManager())->GetBlobSize();
03801
03802 INT32 ArrowWidth = (BlobSize * 3)/2;
03803 INT32 ArrowHeight = (BlobSize * 3)/2;
03804
03805 ArrowPts[0] = Coord( 0, 0);
03806 ArrowPts[1] = Coord( -ArrowWidth/2, -ArrowHeight);
03807 ArrowPts[2] = Coord( ArrowWidth/2, -ArrowHeight);
03808
03809 ArrowMatrix.transform(ArrowPts, PointCount);
03810
03811 Bounds->IncludePoint(DocCoord(ArrowPts[0].x, ArrowPts[0].y));
03812 Bounds->IncludePoint(DocCoord(ArrowPts[1].x, ArrowPts[1].y));
03813 Bounds->IncludePoint(DocCoord(ArrowPts[2].x, ArrowPts[2].y));
03814 #endif
03815 }
03816
03817
03818
03819
03820
03821
03822
03823
03824
03825
03826
03827
03828
03829
03830 BOOL AreLinesPerpendicular(DocCoord* Start, DocCoord* End, DocCoord* End2)
03831 {
03832 INT32 dx1 = (*End).x - (*Start).x;
03833 INT32 dy1 = (*End).y - (*Start).y;
03834
03835 INT32 dx2 = (*End2).x - (*Start).x;
03836 INT32 dy2 = (*End2).y - (*Start).y;
03837
03838 if ( (ABS(dx1 - dy2)) > 5 )
03839 return FALSE;
03840
03841 if ( (ABS(dy1 + dx2)) > 5 )
03842 return FALSE;
03843
03844 return TRUE;
03845 }
03846
03848
03849
03850
03851
03852
03853
03854
03855
03856
03857
03858
03859
03860
03861
03862
03863
03864 RestoreFillRampAction::RestoreFillRampAction()
03865 {
03866 m_pAttr = NULL;
03867 }
03868
03869
03870
03871
03872
03873
03874
03875
03876
03877
03878
03879
03880
03881
03882
03883
03884
03885
03886
03887
03888
03889
03890
03891
03892
03893
03894 ActionCode RestoreFillRampAction::Init( Operation* pOp,
03895 ActionList* pActionList,
03896 AttrFillGeometry* pFill,
03897 RestoreFillRampAction** NewAction)
03898 {
03899 UINT32 ActSize = sizeof(RestoreFillRampAction);
03900
03901 ActionCode Ac = Action::Init(pOp,pActionList,ActSize,
03902 CC_RUNTIME_CLASS(RestoreFillRampAction),
03903 (Action**)NewAction);
03904
03905
03906
03907 DocRect dr;
03908
03909 if (Ac != AC_FAIL)
03910 {
03911 if (pFill->GetColourRamp() != NULL)
03912 {
03913 (*NewAction)->m_LastRamp = *pFill->GetColourRamp();
03914 }
03915
03916 (*NewAction)->m_pAttr = pFill;
03917 }
03918
03919 return Ac;
03920 }
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930
03931
03932
03933
03934
03935
03936
03937
03938 ActionCode RestoreFillRampAction::Execute()
03939 {
03940 ActionCode Act;
03941 RestoreFillRampAction* pAction;
03942
03943 Act = RestoreFillRampAction::Init( pOperation,
03944 pOppositeActLst,
03945 m_pAttr,
03946 &pAction
03947 );
03948
03949 if (Act != AC_FAIL)
03950 {
03951 Document * pDoc = Document::GetCurrent();
03952
03953 if (pDoc)
03954 {
03955
03956
03957
03958
03959
03960
03961
03962
03963
03964 ColourRamp* ColRamp = m_pAttr->GetColourRamp();
03965
03966 if (ColRamp)
03967 {
03968 *m_pAttr->GetColourRamp() = m_LastRamp;
03969 }
03970 else
03971 {
03972
03973
03974 ColRamp = new ColourRamp ();
03975 m_pAttr->SetColourRamp (ColRamp);
03976 *m_pAttr->GetColourRamp() = m_LastRamp;
03977 }
03978 }
03979 }
03980
03981 return Act;
03982 }
03983
03984 RestoreFillRampAction::~RestoreFillRampAction()
03985 {
03986 }
03987