00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 #include "camtypes.h"
00104 #include "tracectl.h"
00105 #include "tracergn.h"
00106
00107
00108
00109
00110
00111 #include "bitmpinf.h"
00112 #include "bfxalu.h"
00113 #include "bfxpixop.h"
00114 #include "nodepath.h"
00115 #include "lineattr.h"
00116
00117
00118 #include "oilprog.h"
00119
00120
00121 #include "fitcurve.h"
00122 #include "pathproc.h"
00123 #include "progress.h"
00124
00125 #include "keypress.h"
00126
00127
00128
00129 DECLARE_SOURCE("$Revision: 1282 $");
00130
00131
00132
00133 CC_IMPLEMENT_DYNCREATE(TraceControl, BitmapEffectBase)
00134
00135
00136
00137 #define new CAM_DEBUG_NEW
00138
00139 #define TRACEUSESTATS 0
00140
00141 const INT32 MARKED_PIXEL = 0xFFFFFFFF;
00142 const INT32 CLEAR_PIXEL = 0xFF808080;
00143 const INT32 REGION_PIXEL = 0xFF000000;
00144 const INT32 BIT_SCANCOLOUR = 0x80000000;
00145 const INT32 BIT_THRESHOLD = 0x40000000;
00146 const INT32 BIT_CACHES_THRESHOLD = 0x01000000;
00147 const INT32 BIT_CACHEV_THRESHOLD = 0x02000000;
00148 const INT32 BIT_CACHES_COLOURTHRESHOLD = 0x04000000;
00149 const INT32 BIT_CACHEV_COLOURTHRESHOLD = 0x08000000;
00150 const INT32 BIT_CACHES_POSITIVE = 0x10000000;
00151 const INT32 BIT_CACHEV_POSITIVE = 0x20000000;
00152
00153 #ifdef _DEBUG
00154 #define SetDebugBitmap(n,b) { if (DebugSwitch[n]) { if (!pDebug[n]) pDebug[n]=ALU->NewBitmap(pUndithered,0,0,32); \
00155 DebugInvalid[n]=TRUE;\
00156 if (pDebug[n]) { ALU->SetA(pDebug[n]); if (b) {ALU->SetB(b); ALU->ByteCopyBA();} \
00157 else ALU->ZeroA(); } } }
00158 #else
00159 #define SetDebugBitmap(n,b) { if (FALSE); }
00160 #endif
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 TraceControl::TraceControl() : BitmapEffectBase()
00173 {
00174 pOriginal = NULL;
00175 pProposed = NULL;
00176 pUndithered = NULL;
00177 pCurrentPath = NULL;
00178 pFill = NULL;
00179 pTraceRegion = NULL;
00180 pStats = NULL;
00181 pErrorRegionList = NULL;
00182 pThresholdPixelOp = NULL;
00183 pColourThresholdPixelOp = NULL;
00184 pPositivePixelOp = NULL;
00185
00186 pTree=NULL;
00187 pJoinNode=NULL;
00188
00189 #ifdef _DEBUG
00190 for (INT32 i=0; i<NUM_TRACECTL_DEBUG_BITMAPS; i++) {pDebug[i]=NULL;DebugSwitch[i]=FALSE;DebugInvalid[i]=TRUE;}
00191 #endif
00192
00193 MaximumInitialAreaErrorThreshold = 0.12;
00194 InitialAreaErrorThreshold = MaximumInitialAreaErrorThreshold;
00195 MinimumInitialAreaErrorThreshold = 0.06;
00196 InitialAreaErrorRatio = 0.5;
00197
00198 GradFillError = 1.0;
00199 NewGradFillError = 0.0;
00200 MinGradFillError = 2.0/256.0;
00201 GradFillErrorRatio = 0.8;
00202
00203 MinPixelError=0.45;
00204 MaxPixelError=2.0;
00205 PixelError=MaxPixelError;
00206 PixelErrorRatio=0.5;
00207 QuantColours=30;
00208
00209 Blur=64.0;
00210 Smooth=0.0;
00211 Log2BPP=5;
00212 Method = TRACEMETHOD_TRUECOL;
00213
00214 MinimumArea = 10;
00215
00216 FoundRegion = FALSE;
00217 InitialX = 0 ;
00218 InitialY = 0;
00219
00220 ScanPointX = 0;
00221 ScanPointY = 0;
00222
00223 XSize = 0;
00224 YSize = 0;
00225
00226 HavePath = FALSE;
00227
00228 TotalPasses=0;
00229 NumPasses=0;
00230 NumPaths=0;
00231 NumCusps=0;
00232 NumPoints=0;
00233 ProgressDone=FALSE;
00234
00235 InitBitmap();
00236
00237 FirstShape = TRUE;
00238 ShapeFreePass = FALSE;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 TraceControl::~TraceControl()
00254 {
00255 InitBitmap();
00256 RemoveTree();
00257 if (pTraceRegion) delete pTraceRegion;
00258 if (pCurrentPath) delete pCurrentPath;
00259 if (pFill) delete pFill;
00260 if (pStats) delete pStats;
00261 if (pErrorRegionList) delete pErrorRegionList;
00262 if (pThresholdPixelOp) delete pThresholdPixelOp;
00263 if (pColourThresholdPixelOp) delete pColourThresholdPixelOp;
00264 if (pPositivePixelOp) delete pPositivePixelOp;
00265
00266
00267 #ifdef _DEBUG
00268 for (INT32 i=0; i<NUM_TRACECTL_DEBUG_BITMAPS; i++) if (pDebug[i]) delete pDebug[i];
00269 #endif
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 BOOL TraceControl::GetParams(
00303 TraceMethod * pMethod,
00304 INT32 * pMinimumArea,
00305 double * pMaximumInitialAreaErrorThreshold,
00306 double * pMinimumInitialAreaErrorThreshold,
00307 double * pInitialAreaErrorRatio,
00308 double * pMinGradFillError,
00309 double * pGradFillErrorRatio,
00310 double * pMinPixelError,
00311 double * pMaxPixelError,
00312 double * pPixelErrorRatio,
00313 double * pQuantColours,
00314 double * pBlur,
00315 double * pSmooth
00316 )
00317 {
00318 if (pMethod) *pMethod =Method;
00319 if (pMinimumArea) *pMinimumArea =MinimumArea;
00320 if (pMaximumInitialAreaErrorThreshold) *pMaximumInitialAreaErrorThreshold =MaximumInitialAreaErrorThreshold;
00321 if (pMinimumInitialAreaErrorThreshold) *pMinimumInitialAreaErrorThreshold =MinimumInitialAreaErrorThreshold;
00322 if (pInitialAreaErrorRatio) *pInitialAreaErrorRatio =InitialAreaErrorRatio;
00323 if (pMinGradFillError) *pMinGradFillError =MinGradFillError;
00324 if (pGradFillErrorRatio) *pGradFillErrorRatio =GradFillErrorRatio;
00325 if (pMinPixelError) *pMinPixelError =MinPixelError;
00326 if (pMaxPixelError) *pMaxPixelError =MaxPixelError;
00327 if (pPixelErrorRatio) *pPixelErrorRatio =PixelErrorRatio;
00328 if (pQuantColours) *pQuantColours =QuantColours;
00329 if (pBlur) *pBlur =Blur;
00330 if (pSmooth) *pSmooth =Smooth;
00331 return TRUE;
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367 BOOL TraceControl::SetParams(
00368 TraceMethod * pMethod,
00369 INT32 * pMinimumArea,
00370 double * pMaximumInitialAreaErrorThreshold,
00371 double * pMinimumInitialAreaErrorThreshold,
00372 double * pInitialAreaErrorRatio,
00373 double * pMinGradFillError,
00374 double * pGradFillErrorRatio,
00375 double * pMinPixelError,
00376 double * pMaxPixelError,
00377 double * pPixelErrorRatio,
00378 double * pQuantColours,
00379 double * pBlur,
00380 double * pSmooth
00381 )
00382 {
00383 ERROR2IF((!pTraceRegion), FALSE, "SetParams() called without prior call to InitBitmaps()");
00384 if (pMethod) Method =*pMethod;
00385 if (pMinimumArea) MinimumArea =*pMinimumArea;
00386 if (pMaximumInitialAreaErrorThreshold) MaximumInitialAreaErrorThreshold =*pMaximumInitialAreaErrorThreshold;
00387 if (pMinimumInitialAreaErrorThreshold) MinimumInitialAreaErrorThreshold =*pMinimumInitialAreaErrorThreshold;
00388 if (pInitialAreaErrorRatio) InitialAreaErrorRatio =*pInitialAreaErrorRatio;
00389 if (pMinGradFillError) MinGradFillError =*pMinGradFillError;
00390 if (pGradFillErrorRatio) GradFillErrorRatio =*pGradFillErrorRatio;
00391 if (pMinPixelError) MinPixelError =*pMinPixelError;
00392 if (pMaxPixelError) MaxPixelError =*pMaxPixelError;
00393 if (pPixelErrorRatio) PixelErrorRatio =*pPixelErrorRatio;
00394 if (pQuantColours) QuantColours =*pQuantColours;
00395 if (pBlur) Blur =*pBlur;
00396 if (pSmooth) Smooth =*pSmooth;
00397 return TRUE;
00398 }
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 BOOL TraceControl::InitBitmap( KernelBitmap * theOriginal)
00424 {
00425 #ifdef _DEBUG
00426 for (INT32 i=0; i<NUM_TRACECTL_DEBUG_BITMAPS; i++) if (pDebug[i]) {delete pDebug[i];pDebug[i]=NULL;DebugInvalid[i]=TRUE;}
00427 #endif
00428
00429 if (pErrorRegionList)
00430 {
00431
00432 delete pErrorRegionList;
00433 pErrorRegionList = NULL;
00434 }
00435
00436 if (pThresholdPixelOp) delete pThresholdPixelOp;
00437 if (pColourThresholdPixelOp) delete pColourThresholdPixelOp;
00438 if (pPositivePixelOp) delete pPositivePixelOp;
00439 pThresholdPixelOp = NULL;
00440 pColourThresholdPixelOp = NULL;
00441 pPositivePixelOp = NULL;
00442
00443 XSize = 0;
00444 YSize = 0;
00445
00446 if (!pTraceRegion) if ((pTraceRegion = new TraceRegion) == NULL) return FALSE;
00447 if (!pFill) if ((pFill = new LinearFillAttribute) == NULL) return FALSE;
00448
00449 if (!theOriginal)
00450 {
00451
00452 if (pProposed) delete pProposed;
00453 if (pUndithered) delete pUndithered;
00454
00455 pProposed = NULL;
00456 pUndithered = NULL;
00457
00458
00459 pOriginal = NULL;
00460 return TRUE;
00461 }
00462
00463 if (pProposed) delete pProposed;
00464 if (pUndithered) delete pUndithered;
00465
00466 if (!RemoveTree(TRUE)) return FALSE;
00467 ProgressDone=0;
00468
00469 pProposed = NULL;
00470 pUndithered = NULL;
00471
00472
00473 if (Method == TRACEMETHOD_TRUECOL)
00474 {
00475 if ((pThresholdPixelOp = new BfxThresholdPixelOp) ==NULL) return FALSE;
00476 if ((pColourThresholdPixelOp = new BfxColourThresholdPixelOp) ==NULL) return FALSE;
00477 if ((pPositivePixelOp = new BfxColourThresholdPixelOp) ==NULL) return FALSE;
00478 }
00479 else
00480 {
00481 if ((pThresholdPixelOp = new BfxThresholdPixelOpPseudo) ==NULL) return FALSE;
00482 if ((pColourThresholdPixelOp = new BfxColourThresholdPixelOpPseudo) ==NULL) return FALSE;
00483 if ((pPositivePixelOp = new BfxColourThresholdPixelOpPseudo) ==NULL) return FALSE;
00484 }
00485
00486
00487
00488 pOriginal = theOriginal;
00489
00490 FirstShape = TRUE;
00491
00492 return TRUE;
00493 }
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 BOOL TraceControl::RemoveTree(BOOL DeleteIt)
00517 {
00518 if (!DeleteIt) {pTree = NULL; pJoinNode=NULL; return TRUE;}
00519
00520 if (pTree)
00521 {
00522 Node * pFirstChild = pTree->FindFirstChild();
00523 if (pFirstChild) pTree->DeleteChildren(pFirstChild);
00524 delete pTree;
00525 pTree = NULL;
00526 pJoinNode = NULL;
00527 }
00528 return TRUE;
00529 }
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 BOOL TraceControl::GetBitmaps( KernelBitmap * * theOriginal,
00558 KernelBitmap * * theProposed, KernelBitmap * * theUndithered)
00559 {
00560
00561 if (theOriginal) *theOriginal = pOriginal;
00562 if (theProposed) *theProposed = pProposed;
00563 if (theUndithered) *theUndithered = pUndithered;
00564 return TRUE;
00565 }
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590 BOOL TraceControl::Trace(BOOL * Done)
00591 {
00592
00593
00594 ERROR2IF(!Done, FALSE, "Don't call TraceControl::Trace with a NULL Done ptr");
00595 *Done = FALSE;
00596
00597 ERROR2IF((!pOriginal), FALSE, "Don't call TraceControl::Trace without calling InitBitmaps() first");
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 if (FirstShape)
00612 {
00613 if (!RemoveTree(TRUE)) return FALSE;
00614
00615 if ((pTree = new NodeGroup) ==NULL ) return FALSE;
00616 if ((pJoinNode = new AttrStrokeColour(pTree, FIRSTCHILD)) == NULL) return FALSE;
00617 DocColour TheColour(COLOUR_NONE);
00618 ((AttrStrokeColour *)pJoinNode)->SetStartColour(&TheColour);
00619 NodePath * pRect;
00620 AttrFillGeometry * pRectCol;
00621 if (!(((pRect = new NodePath(pJoinNode, NEXT))!=NULL) && pRect->SetUpPath(32, 32))) return FALSE;
00622 if (!(((pRectCol = new AttrFlatColourFill(pRect, FIRSTCHILD))!=NULL))) return FALSE;
00623 pJoinNode=pRect;
00624
00625 TRACEUSER( "Alex", _T("> Removing dither\n"));
00626 if (pProposed) delete pProposed;
00627 if (pUndithered) delete pUndithered;
00628
00629 pProposed = NULL;
00630 pUndithered = NULL;
00631
00632 ERROR2IF(!ALU, FALSE, "OK, where's the ALU gone?");
00633
00634 if (!ALU->SetB(pOriginal)) return FALSE;
00635 INT32 NumColours = (INT32)(17.5+(255.0-17.0)*QuantColours);
00636 if (Method==TRACEMETHOD_GREYSCALE) NumColours = (INT32)(2.5+(255.0-2.0)*QuantColours);
00637 if (!ALU->RemoveDither(&pUndithered, (INT32)(Blur*2.55+0.5), NumColours, Method)) return FALSE;
00638 ERROR2IF(!pUndithered, FALSE, "How come remove dither failed to generate a KB without generating an error");
00639
00640 EndSlowJob();
00641 String_64 ProcessMessage(_R(IDS_TRACEDLG_TRACING));
00642 BeginSlowJob(100, FALSE, &ProcessMessage);
00643
00644
00645 if ((pProposed = ALU->NewBitmap(pUndithered,0,0)) == NULL)
00646 {
00647 delete pUndithered;
00648 pUndithered = NULL;
00649 return FALSE;
00650 }
00651
00652 ALU->SetA(pProposed);
00653 ALU->ZeroA(0xFF);
00654
00655 if (!ALU->GetSize(pUndithered, &XSize, &YSize)) return FALSE;
00656
00657 if (!(
00658 pThresholdPixelOp->SetBitmap(pUndithered, BIT_CACHEV_THRESHOLD, BIT_CACHES_THRESHOLD, FALSE) &&
00659 pColourThresholdPixelOp->SetBitmap(pUndithered, BIT_CACHEV_COLOURTHRESHOLD, BIT_CACHES_COLOURTHRESHOLD, FALSE) &&
00660 pPositivePixelOp->SetBitmap(pUndithered, BIT_CACHEV_POSITIVE, BIT_CACHES_POSITIVE, FALSE) &&
00661
00662 TRUE)) return FALSE;
00663
00664 TRACEUSER( "Alex", _T("> First shape, here we go\n"));
00665 FirstShape = FALSE;
00666 ShapeFreePass = FALSE;
00667 InitialAreaErrorThreshold = MaximumInitialAreaErrorThreshold;
00668 GradFillError = 1.0;
00669 NewGradFillError = 0.0;
00670 if (!(
00671 pThresholdPixelOp->ClearEntireCache() &&
00672 pColourThresholdPixelOp->ClearEntireCache() &&
00673 pPositivePixelOp->ClearEntireCache() &&
00674 TRUE)) return FALSE;
00675
00676
00677 if (!pPositivePixelOp->SetAuxilliaryBitmaps(NULL, pProposed, pUndithered, 0, 0))
00678 return FALSE;
00679
00680
00681 #ifdef _DEBUG
00682 for (INT32 i=0; i<NUM_TRACECTL_DEBUG_BITMAPS; i++) if (pDebug[i]) {delete pDebug[i];pDebug[i]=NULL;DebugInvalid[i]=TRUE;}
00683 #endif
00684 SetDebugBitmap(0, pUndithered);
00685
00686 TotalPasses=0;
00687 NumPasses=0;
00688 NumPaths=0;
00689 NumCusps=0;
00690 NumPoints=0;
00691 ProgressDone=0;
00692
00693 double iaet=InitialAreaErrorThreshold;
00694 while (TRUE)
00695 {
00696
00697
00698 if (iaet<=MinimumInitialAreaErrorThreshold)
00699 iaet=MinimumInitialAreaErrorThreshold;
00700 TotalPasses++;
00701
00702 if (iaet-1E-10<=MinimumInitialAreaErrorThreshold)
00703 break;
00704 iaet *= InitialAreaErrorRatio;
00705 }
00706
00707
00708
00709 pRect->InkPath.FindStartOfPath();
00710
00711
00712 pRect->InkPath.InsertMoveTo(DocCoord(0,0));
00713 pRect->InkPath.InsertLineTo(DocCoord(0,YSize<<8));
00714 pRect->InkPath.InsertLineTo(DocCoord(XSize<<8,YSize<<8));
00715 pRect->InkPath.InsertLineTo(DocCoord(XSize<<8,0));
00716 pRect->InkPath.InsertLineTo(DocCoord(0,0));
00717
00718
00719 pRect->InkPath.CloseSubPath();
00720 pRect->InkPath.IsFilled = TRUE;
00721
00722
00723 GFStartC = GFEndC = (DWORD)(pPositivePixelOp->ReadOriginalPixel(0, 0)) &0x00FFFFFF;
00724 INT32 R = 0;
00725 INT32 G = 0;
00726 INT32 B = 0;
00727 pPositivePixelOp->TranslateToRGB(GFStartC, pUndithered, &R, &G, &B);
00728 DocColour RectColour( R, G, B );
00729 GFStartX = 0;
00730 GFStartY = 0;
00731 GFEndX = XSize;
00732 GFEndY = YSize;
00733 pRectCol->SetStartColour(&RectColour);
00734 return PlotGradFill(TRUE, FALSE);
00735
00736 }
00737
00738
00739 HavePath = FALSE;
00740
00741
00742
00743 while (TRUE)
00744 {
00745 ERROR1IF(KeyPress::IsEscapePressed(), FALSE, _R(IDS_ABORT));
00746
00747
00748
00749
00750
00751
00752 if (!MarkInitialArea()) return FALSE;
00753
00754 if (!FoundRegion)
00755 {
00756
00757
00758 *Done = TRUE;
00759 return TRUE;
00760 }
00761
00762
00763
00764
00765
00766
00767
00768 INT32 Passes = 0;
00769 BOOL UseColourThresholdPixelOp = TRUE;
00770 do
00771 {
00772
00773
00774
00775 PixelError = MaxPixelError;
00776 BOOL RegionTraceable = FALSE;
00777 while ((PixelError>=MinPixelError) && !RegionTraceable)
00778 {
00779 if (!(
00780 pTraceRegion->SetParams(&PixelError) &&
00781 TracePath(UseColourThresholdPixelOp?pColourThresholdPixelOp:pPositivePixelOp) &&
00782
00783 CalculateStatistics() &&
00784 TRUE)) return FALSE;
00785 if (PixelError>MinPixelError)
00786 {
00787 PixelError *= PixelErrorRatio;
00788 if (PixelError<MinPixelError) PixelError=MinPixelError;
00789 } else PixelError=0.0;
00790 RegionTraceable = (!pStats) || (pStats->N > 2);
00791
00792
00793 }
00794
00795 UseColourThresholdPixelOp = FALSE;
00796
00797 if (RegionTraceable)
00798 {
00799 HavePath = TRUE;
00800
00801
00802
00803 if (!(
00804 FormGradFill() &&
00805
00806 TRUE)) return FALSE;
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816 INT32 theErrorThreshold = (INT32)(0.5+3.0*DoubleSquare(InitialAreaErrorThreshold * 255.0));
00817 if (!pPositivePixelOp->ClearCachedArea()) return FALSE;
00818
00819 if (!pPositivePixelOp->SetAuxilliaryBitmaps(NULL, pProposed, pUndithered, theErrorThreshold,
00820 GFStartC ))
00821 return FALSE;
00822
00823
00824 FoundRegion = pPositivePixelOp->IsInRegion(InitialX, InitialY);
00825 INT32 xadj;
00826 INT32 yadj;
00827 if (!FoundRegion) for (yadj=-1; (yadj<=1) && !FoundRegion; yadj++)
00828 for (xadj=-1; (xadj<=1) && !FoundRegion; xadj++)
00829 if (pPositivePixelOp->IsInRegion(InitialX+xadj, InitialY+yadj))
00830 {
00831 FoundRegion=TRUE;
00832 InitialX+=xadj;
00833 InitialY+=yadj;
00834 }
00835
00836
00837 if (FoundRegion) if (!CheckMinimumArea(pPositivePixelOp)) return FALSE;
00838
00839 RegionArea = MinimumArea + 1;
00840
00841
00842 if (FoundRegion)
00843 {
00844
00845
00846
00847
00848 if (TRUE
00849 || (Passes>=1) || ((Passes != 0) && !(FALSE )))
00850 {
00851
00852 if (!PlotGradFill(TRUE, TRUE)) return FALSE;
00853 if ((Smooth>3.0) && pCurrentPath)
00854 {
00855
00856
00857 INT32 orignumcoords = pCurrentPath->InkPath.GetNumCoords();
00858
00859
00860 Path QuantPath;
00861 INT32 startpoints=((orignumcoords>24)?orignumcoords:24)*5;
00862 QuantPath.Initialise(startpoints,(startpoints>2400)?2400:startpoints);
00863
00864
00865
00866
00867 double coordsmooth = Smooth*10.24;
00868
00869 ProcessFlags QuantFlags(TRUE,FALSE,TRUE);
00870 pCurrentPath->InkPath.CreateFlatPath(QuantFlags, coordsmooth, &QuantPath);
00871
00872
00873
00874
00875 CurveFitObject Smoothed(&QuantPath, coordsmooth*coordsmooth);
00876
00877 if (Smoothed.Initialise(&QuantPath,QuantPath.GetNumCoords()))
00878 {
00879 Smoothed.FitCurve();
00880 QuantPath.CloseSubPath();
00881 QuantPath.IsFilled=TRUE;
00882
00883
00884
00885
00886 if (QuantPath.GetNumCoords()<orignumcoords)
00887 if (!pCurrentPath->InkPath.CloneFrom(QuantPath)) return FALSE;
00888
00889 }
00890 }
00891
00892 ShapeFreePass=FALSE;
00893
00894 GradFillError = NewGradFillError;
00895
00896 if (pCurrentPath) NumPoints+=pCurrentPath->InkPath.GetNumCoords()/3;
00897 NumPaths++;
00898
00899
00900 INT32 R = 0;
00901 INT32 G = 0;
00902 INT32 B = 0;
00903 pPositivePixelOp->TranslateToRGB(GFStartC, pUndithered, &R, &G, &B);
00904 DocColour TheColour( R, G, B );
00905
00906 AttrFillGeometry * pFillGeometry = new AttrFlatColourFill;
00907 if (!pFillGeometry) return FALSE;
00908
00909 pFillGeometry->SetStartColour(&TheColour);
00910 pFillGeometry->AttachNode(pCurrentPath, FIRSTCHILD);
00911
00912
00913 if (pJoinNode)
00914 {
00915 pCurrentPath->AttachNode(pJoinNode, NEXT);
00916 }
00917 else
00918 {
00919 pCurrentPath->AttachNode(pTree, FIRSTCHILD);
00920 }
00921
00922 pJoinNode = pCurrentPath;
00923 pCurrentPath = NULL;
00924
00925 return TRUE;
00926 }
00927
00928
00929 }
00930 }
00931 else
00932 {
00933 FoundRegion = FALSE;
00934
00935 }
00936
00937 Passes++;
00938 } while (FoundRegion);
00939 TRACEUSER( "Alex", _T("< Rejecting malformed error region\n"));
00940 HavePath = FALSE;
00941 }
00942
00943
00944
00945 ERROR3("OK, How come a while(TRUE) terminated? Has someone inserted a break or what?");
00946 return FALSE;
00947 }
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985 BOOL TraceControl::GetProgress(INT32 * pPercent,
00986 INT32 * pNumPaths,
00987 INT32 * pNumCusps,
00988 INT32 * pNumPoints,
00989 BOOL * pProgressDone)
00990 {
00991 if (pProgressDone) *pProgressDone = ProgressDone && pOriginal;
00992 if (pPercent)
00993 {
00994 INT32 percent=ProgressDone?100:(INT32)(1.0+100.0*(
00995 ((double)ScanPointY/(double)(YSize?YSize:1)+(double)NumPasses)/(double)(TotalPasses?TotalPasses:1) ));
00996 if ((percent<0 ) || (!pOriginal) || (!ProgressDone && ScanPointX==0 && ScanPointY==0 && NumPasses==0)) percent=0;
00997 if (percent>100) percent=100;
00998 *pPercent=percent;
00999 }
01000 if (pNumPaths) *pNumPaths=NumPaths;
01001 if (pNumCusps) *pNumCusps=NumCusps;
01002 if (pNumPoints) *pNumPoints=NumPoints;
01003 return TRUE;
01004 }
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028 BOOL TraceControl::CheckMinimumArea(BfxPixelOp * pBfxPixelOp)
01029 {
01030 return pBfxPixelOp->CheckMinimumArea(MinimumArea, InitialX, InitialY, &FoundRegion);
01031 }
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052 BOOL TraceControl::SetPath(NodePath * pNodePath)
01053 {
01054 pCurrentPath = pNodePath;
01055 if (!pCurrentPath) HavePath = FALSE;
01056 return TRUE;
01057 }
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075 Node * TraceControl::GetPaths()
01076 {
01077 return pTree;
01078 }
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108 BOOL TraceControl::MarkInitialArea()
01109 {
01110 ERROR3IF (HavePath, "MarkInitialArea() called when a path was set up. Wierd...");
01111 ERROR3IF ((!pUndithered) || (!pProposed), "MarkInitialArea() missing some bitmaps");
01112
01113 BOOL FirstCall = FALSE;
01114
01115 if (!pErrorRegionList)
01116 {
01117 if ((pErrorRegionList = new BfxErrorRegionList) == NULL) return FALSE;
01118 if (!pErrorRegionList->Init(1000))
01119 {
01120 delete pErrorRegionList;
01121 pErrorRegionList = NULL;
01122 return FALSE;
01123 }
01124 FirstCall = TRUE;
01125 }
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137 do
01138 {
01139
01140 pErrorRegionList->Next();
01141 while (!pErrorRegionList->GetCurrent(&InitialX,&InitialY,&RegionArea))
01142 {
01143
01144 pErrorRegionList->ResetRead();
01145
01146 if (TRUE || ShapeFreePass || !pErrorRegionList->GetCurrent(&InitialX,&InitialY,&RegionArea))
01147 {
01148
01149
01150
01151
01152
01153 INT32 theErrorThreshold = (INT32)(0.5+3.0*DoubleSquare(InitialAreaErrorThreshold * 255.0));
01154
01155
01156
01157 BOOL FoundScanPoint=FALSE;
01158
01159 do
01160 {
01161
01162 if (!FirstCall)
01163 {
01164 theErrorThreshold = (INT32)(0.5+3.0*DoubleSquare(InitialAreaErrorThreshold * 255.0));
01165 if (!(ALU->SetB(pProposed) && ALU->SetT(pUndithered))) return FALSE;
01166 if (!(ALU->ScanThreshold(theErrorThreshold, &ScanPointX, &ScanPointY, NULL, &FoundScanPoint, TRUE))) return FALSE;
01167 }
01168
01169
01170 if (FirstCall || !FoundScanPoint)
01171 {
01172
01173 ScanPointX=0;
01174 ScanPointY=0;
01175
01176
01177 if (!FirstCall)
01178 {
01179 NumPasses++;
01180 if (InitialAreaErrorThreshold-1E-10<=MinimumInitialAreaErrorThreshold)
01181 {
01182 FoundRegion = FALSE;
01183 ProgressDone=TRUE;
01184 return TRUE;
01185 }
01186 InitialAreaErrorThreshold *= InitialAreaErrorRatio;
01187 }
01188
01189
01190 FirstCall=FALSE;
01191
01192
01193 if (InitialAreaErrorThreshold<=MinimumInitialAreaErrorThreshold)
01194 InitialAreaErrorThreshold=MinimumInitialAreaErrorThreshold;
01195 TRACEUSER( "Alex", _T("> Reducing InitialAreaErrorThreshold to %f\n"),InitialAreaErrorThreshold);
01196
01197 }
01198 } while (!FoundScanPoint);
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211 ScanPointColour =pPositivePixelOp->ReadOriginalPixel(ScanPointX, ScanPointY) & 0x00FFFFFF;
01212
01213
01214
01215
01216
01217
01218
01219 if (!pColourThresholdPixelOp->ClearCachedArea()) return FALSE;
01220 if (!pColourThresholdPixelOp->SetAuxilliaryBitmaps(NULL, pProposed, pUndithered, theErrorThreshold, ScanPointColour))
01221 return FALSE;
01222
01223
01224 InitialX=ScanPointX; InitialY=ScanPointY;
01225
01226 ScanPointX++;
01227 if (ScanPointX>=XSize) {ScanPointX=0;ScanPointY++;}
01228
01229
01230 if (!CheckMinimumArea(pColourThresholdPixelOp)) return FALSE;
01231 RegionArea = MinimumArea + 1;
01232
01233 if (!pColourThresholdPixelOp->IsInRegion(InitialX, InitialY))
01234 {
01235 FoundRegion=FALSE;
01236
01237 }
01238
01239 if (!pErrorRegionList->Empty()) return FALSE;
01240 if ((FoundRegion) && (RegionArea>=MinimumArea)) if (!(pErrorRegionList->Insert(InitialX, InitialY, RegionArea))) return FALSE;
01241 if (!(pErrorRegionList->Sort() && pErrorRegionList->ResetRead())) return FALSE;
01242
01243 }
01244
01245 ShapeFreePass = TRUE;
01246 }
01247
01248
01249 FoundRegion = TRUE;
01250
01251 } while
01252 (!( (RegionArea>MinimumArea) &&
01253 (pColourThresholdPixelOp->IsInRegion(InitialX, InitialY)) &&
01254 (
01255 pColourThresholdPixelOp->IsInRegion(InitialX-1, InitialY ) ||
01256 pColourThresholdPixelOp->IsInRegion(InitialX+1, InitialY ) ||
01257 pColourThresholdPixelOp->IsInRegion(InitialX, InitialY-1) ||
01258 pColourThresholdPixelOp->IsInRegion(InitialX-1, InitialY-1) ||
01259 pColourThresholdPixelOp->IsInRegion(InitialX-1, InitialY-1) ||
01260 pColourThresholdPixelOp->IsInRegion(InitialX, InitialY+1) ||
01261 pColourThresholdPixelOp->IsInRegion(InitialX-1, InitialY+1) ||
01262 pColourThresholdPixelOp->IsInRegion(InitialX-1, InitialY+1) )
01263 ));
01264
01265 return (pErrorRegionList->MarkUsed());
01266 }
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288 BOOL TraceControl::TracePath(BfxPixelOp * pBfxPixelOp)
01289 {
01290 if (!pCurrentPath)
01291 if (!(((pCurrentPath = new NodePath)!=NULL) && pCurrentPath->SetUpPath(32, 32))) return FALSE;
01292 ERROR3IF ((!pUndithered) || (!pProposed) || (!pBfxPixelOp), "TracePath() missing some bitmaps");
01293
01294 return( pTraceRegion->UseBitmap(pUndithered) &&
01295 pTraceRegion->UsePath(&(pCurrentPath->InkPath)) &&
01296 pTraceRegion->Trace(InitialX, InitialY, pBfxPixelOp) &&
01297 TRUE );
01298 }
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318 BOOL TraceControl::CalculateStatistics()
01319 {
01320 #if TRACEUSESTATS
01321 if (!pStats) if ((pStats = new KernelStatistics) == NULL) return FALSE;
01322
01323 ERROR3IF ((!pUndithered) || (!pProposed), "CalculateStatistics() missing some bitmaps");
01324 ERROR2IF ((!pCurrentPath), FALSE, "CalculateStatistics() called without path to grad fill");
01325
01326 if (!(ALU->SetA(pUndithered))) return FALSE;
01327
01328
01329
01330 return (ALU->GetStatistics(&(pCurrentPath->InkPath), pStats));
01331 #else
01332 return TRUE;
01333 #endif
01334 }
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355 BOOL TraceControl::FormGradFill()
01356 {
01357 GFStartX = 0;
01358 GFStartY = 0;
01359 GFEndX = XSize;
01360 GFEndY = YSize;
01361
01362 #if TRACEUSESTATS
01363 ERROR3IF((!pStats), "How come we got here without a statistics block then?!");
01364 INT32 R = (INT32)(pStats->R * 255.0);
01365 INT32 G = (INT32)(pStats->G * 255.0);
01366 INT32 B = (INT32)(pStats->B * 255.0);
01367 #if 0
01368 UINT32 pval = (UINT32)(pStats->Pixel);
01369 R = (pval) & 0xFF;
01370 G = (pval>>8) & 0xFF;
01371 B = (pval>>16) & 0xFF;
01372 #endif
01373
01374 if (R<0) R=0;
01375 if (G<0) G=0;
01376 if (B<0) B=0;
01377 if (R>255) R=255;
01378 if (G>255) G=255;
01379 if (B>255) B=255;
01380
01381 GFStartC = GFEndC = (DWORD)(R | (G<<8) | (B<<16));
01382
01383
01384
01385 return TRUE;
01386
01387 #else
01388
01389 GFStartC = GFEndC = (DWORD)(pPositivePixelOp->ReadOriginalPixel(InitialX, InitialY)) &0x00FFFFFF;
01390 return TRUE;
01391
01392 #endif
01393 }
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414 BOOL TraceControl::PlotGradFill(BOOL ToProposed, BOOL UsePath)
01415 {
01416 ERROR3IF ((!pUndithered) || (!pProposed) || (!ToProposed && !pUndithered), "PlotGradFill() missing some bitmaps");
01417 if (UsePath) ERROR2IF ((!pCurrentPath), FALSE, "PlotGradFill() called without path to grad fill");
01418
01419 if (ToProposed)
01420 {
01421 if (!(ALU->SetA(pProposed))) return FALSE;
01422 }
01423 else
01424 {
01425 if (!(ALU->SetA(pUndithered) && ALU->SetB(pProposed) && ALU->ByteCopyBA())) return FALSE;
01426 }
01427
01428 return (ALU->GradFillPath(UsePath?&(pCurrentPath->InkPath):NULL, GFStartC, GFEndC,
01429 GFStartX, GFStartY, GFEndX, GFEndY, FALSE, TRUE));
01430 }
01431
01432
01433