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 #include "camtypes.h"
00105 #include "fuzzclip.h"
00106
00107
00108
00109
00112
00113 struct GRECT {
00114 INT32 lx ;
00115 INT32 ly ;
00116 INT32 hx ;
00117 INT32 hy ;
00118 } ;
00119
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 #define oo 00
00141 #define bl 01
00142 #define br 02
00143 #define tl 03
00144 #define tr 04
00145 #define pp 05
00146 #define ee 06
00147 #define xx 07
00148
00149 static CONST BYTE CaseTable[25][25] = {
00150
00151 {oo,bl,bl,bl,bl, bl,oo,bl,bl,10, bl,bl,xx,xx,xx, bl,bl,xx,xx,xx, bl,11,xx,xx,xx},
00152 {oo,oo,oo,oo,oo, bl,oo,oo,oo,br, bl,bl,xx,xx,xx, bl,bl,xx,xx,xx, bl,11,xx,xx,xx},
00153 {oo,oo,oo,oo,oo, bl,oo,oo,oo,br, bl,xx,xx,xx,br, xx,xx,xx,xx,xx, xx,xx,xx,xx,xx},
00154 {oo,oo,oo,oo,oo, bl,oo,oo,oo,br, xx,xx,xx,br,br, xx,xx,xx,br,br, xx,xx,xx,12,br},
00155 {br,br,br,br,oo, 13,br,br,oo,br, xx,xx,xx,br,br, xx,xx,xx,br,br, xx,xx,xx,12,br},
00156
00157 {oo,bl,bl,bl,bl, oo,oo,bl,bl,10, oo,oo,xx,xx,xx, oo,oo,xx,xx,xx, oo,tl,xx,xx,xx},
00158 {oo,bl,bl,bl,bl, bl,oo,bl,bl,10, bl,bl,pp,pp,xx, bl,bl,pp,pp,xx, bl,11,xx,xx,xx},
00159 {oo,oo,oo,oo,oo, bl,oo,oo,oo,br, xx,pp,pp,pp,xx, xx,pp,pp,pp,xx, xx,xx,xx,xx,xx},
00160 {br,br,br,br,oo, 13,br,br,oo,br, xx,pp,pp,br,br, xx,pp,pp,br,br, xx,xx,xx,12,br},
00161 {br,br,br,br,oo, 13,br,br,oo,oo, xx,xx,xx,oo,oo, xx,xx,xx,oo,oo, xx,xx,xx,tr,oo},
00162
00163 {oo,bl,bl,xx,xx, oo,oo,xx,xx,xx, oo,oo,xx,xx,xx, oo,oo,xx,xx,xx, oo,tl,tl,xx,xx},
00164 {oo,bl,xx,xx,xx, oo,oo,pp,pp,xx, oo,oo,pp,pp,xx, oo,oo,pp,pp,xx, oo,tl,xx,xx,xx},
00165 {xx,xx,xx,xx,xx, xx,ee,ee,ee,xx, xx,ee,ee,ee,xx, xx,ee,ee,ee,xx, xx,xx,xx,xx,xx},
00166 {xx,xx,xx,br,oo, xx,pp,pp,oo,oo, xx,pp,pp,oo,oo, xx,pp,pp,oo,oo, xx,xx,xx,tr,oo},
00167 {xx,xx,br,br,oo, xx,xx,xx,oo,oo, xx,xx,xx,oo,oo, xx,xx,xx,oo,oo, xx,xx,tr,tr,oo},
00168
00169 {oo,bl,xx,xx,xx, oo,oo,xx,xx,xx, oo,oo,xx,xx,xx, oo,oo,tl,tl,14, oo,tl,tl,tl,tl},
00170 {tl,15,xx,xx,xx, tl,tl,pp,pp,xx, tl,tl,pp,pp,xx, tl,oo,tl,tl,14, oo,tl,tl,tl,tl},
00171 {xx,xx,xx,xx,xx, xx,pp,pp,pp,xx, xx,pp,pp,pp,xx, tl,oo,oo,oo,tr, oo,oo,oo,oo,oo},
00172 {xx,xx,xx,16,tr, xx,pp,pp,tr,tr, xx,pp,pp,tr,tr, 17,tr,tr,oo,tr, tr,tr,tr,tr,oo},
00173 {xx,xx,xx,br,oo, xx,xx,xx,oo,oo, xx,xx,xx,oo,oo, 17,tr,tr,oo,oo, tr,tr,tr,tr,oo},
00174
00175 {tl,15,xx,xx,xx, tl,tl,xx,xx,xx, tl,tl,xx,xx,xx, tl,oo,tl,tl,14, oo,tl,tl,tl,tl},
00176 {tl,15,xx,xx,xx, tl,tl,xx,xx,xx, tl,tl,xx,xx,xx, tl,oo,oo,oo,tr, oo,oo,oo,oo,oo},
00177 {xx,xx,xx,xx,xx, xx,xx,xx,xx,xx, tl,xx,xx,xx,tr, tl,oo,oo,oo,tr, oo,oo,oo,oo,oo},
00178 {xx,xx,xx,16,tr, xx,xx,xx,tr,tr, xx,xx,xx,tr,tr, tl,oo,oo,oo,tr, oo,oo,oo,oo,oo},
00179 {xx,xx,xx,16,tr, xx,xx,xx,tr,tr, xx,xx,xx,tr,tr, 17,tr,tr,oo,tr, tr,tr,tr,tr,oo}
00180 } ;
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 static CONST DWORD Region[25] = {
00192 0x003,0x001,0x001,0x001,0x005,
00193 0x002,0x030,0x110,0x050,0x004,
00194 0x002,0x220,0x300,0x240,0x004,
00195 0x002,0x0a0,0x180,0x0c0,0x004,
00196 0x00a,0x008,0x008,0x008,0x00c
00197 } ;
00198
00199 static INT32 LastSector ;
00200
00201 static GRECT *IRect ;
00202 static GRECT *ORect ;
00203
00204 static POINT LastPoint ;
00205
00206 static PPOINT OPoints ;
00207 static PBYTE OTypes ;
00208 static size_t OMaxLength ;
00209 static size_t OLength ;
00210 static BOOL OFirstPoint ;
00211
00212 static UINT32 Index ;
00213 static UINT32 LastIndex ;
00214 static BOOL SameLine ;
00215
00217
00218 inline BOOL IsMove( CONST BYTE Type )
00219 {
00220 return (Type & PT_MOVETO)==PT_MOVETO ;
00221 }
00222
00223 inline BOOL IsntMove( CONST BYTE Type )
00224 {
00225 return (Type & PT_MOVETO)!=PT_MOVETO ;
00226 }
00227
00228 inline BOOL IsLine( CONST BYTE Type )
00229 {
00230 return (Type & PT_MOVETO)==PT_LINETO ;
00231 }
00232
00233 inline BOOL IsCurve( CONST BYTE Type )
00234 {
00235 return (Type & PT_MOVETO)==PT_BEZIERTO ;
00236 }
00237
00238 inline BOOL IsntCurve( CONST BYTE Type )
00239 {
00240 return (Type & PT_MOVETO)!=PT_BEZIERTO ;
00241 }
00242
00244
00245
00246
00247
00248 void GenLine( INT32 X, INT32 Y, BOOL Merge=TRUE )
00249 {
00250 if ( OFirstPoint )
00251 {
00252 OFirstPoint = FALSE ;
00253 if ( ++OLength > OMaxLength )
00254 throw 1 ;
00255 *OTypes++ = PT_MOVETO ;
00256 OPoints->x = X ;
00257 OPoints->y = Y ;
00258 OPoints++ ;
00259 SameLine = FALSE ;
00260 LastIndex = Merge?Index:INT32_MAX ;
00261 }
00262 else if ( Merge && SameLine && LastIndex==Index )
00263 {
00264 (OPoints-1)->x = X ;
00265 (OPoints-1)->y = Y ;
00266 }
00267 else if ( (OPoints-1)->x != X ||
00268 (OPoints-1)->y != Y )
00269 {
00270 if ( ++OLength > OMaxLength )
00271 throw 1 ;
00272 *OTypes++ = PT_LINETO ;
00273 OPoints->x = X ;
00274 OPoints->y = Y ;
00275 OPoints++ ;
00276 SameLine = Merge && (LastIndex==Index) ;
00277 LastIndex = Merge?Index:INT32_MAX ;
00278 }
00279 }
00280
00281
00282 void GenCurve( POINT &P1, POINT &P2, POINT &P3 )
00283 {
00284 if ( (OLength+=3) > OMaxLength )
00285 throw 1 ;
00286 *OTypes++ = PT_BEZIERTO ; *OPoints++ = P1 ;
00287 *OTypes++ = PT_BEZIERTO ; *OPoints++ = P2 ;
00288 *OTypes++ = PT_BEZIERTO ; *OPoints++ = P3 ;
00289 SameLine = FALSE ;
00290 LastIndex = INT32_MAX ;
00291 }
00292
00293
00294 inline void GenLine( POINT &P, BOOL F=TRUE ) { GenLine( P.x,P.y,F ) ; } ;
00295
00296
00297 inline void GenLineToBelowLeft () { GenLine( IRect->lx,IRect->ly,FALSE ) ; } ;
00298 inline void GenLineToBelowRight() { GenLine( IRect->hx,IRect->ly,FALSE ) ; } ;
00299 inline void GenLineToAboveLeft () { GenLine( IRect->lx,IRect->hy,FALSE ) ; } ;
00300 inline void GenLineToAboveRight() { GenLine( IRect->hx,IRect->hy,FALSE ) ; } ;
00301
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 INT32 GetSector( POINT &P )
00325 {
00326 INT32 Sector = 12 ;
00327 if ( P.x < IRect->lx )
00328 if ( P.x < ORect->lx )
00329 Sector -= 2 ;
00330 else
00331 Sector-- ;
00332 else if ( P.x > IRect->hx )
00333 if ( P.x > ORect->hx )
00334 Sector += 2 ;
00335 else
00336 Sector++ ;
00337 if ( P.y < IRect->ly )
00338 if ( P.y < ORect->ly )
00339 Sector -= 2*5 ;
00340 else
00341 Sector -= 5 ;
00342 else if ( P.y > IRect->hy )
00343 if ( P.y > ORect->hy )
00344 Sector += 2*5 ;
00345 else
00346 Sector += 5 ;
00347 return Sector ;
00348 }
00349
00351
00352 void ClipLine( POINT &Start, POINT &End )
00353 {
00354 INT32 ThisSector = GetSector( End ) ;
00355 switch ( CaseTable[(INT32)LastSector][(INT32)ThisSector] )
00356 {
00357 case 01 : GenLineToBelowLeft() ; break ;
00358 case 02 : GenLineToBelowRight() ; break ;
00359 case 03 : GenLineToAboveLeft() ; break ;
00360 case 04 : GenLineToAboveRight() ; break ;
00361 case 05 : GenLine(Start) ;
00362 GenLine(End) ; break ;
00363 case 06 : if ( OFirstPoint )
00364 GenLine(Start) ;
00365 GenLine(End) ; break ;
00366 case 07 :
00367 POINT Middle ;
00368 Middle.x = (Start.x+End.x) >> 1 ;
00369 Middle.y = (Start.y+End.y) >> 1 ;
00370 ClipLine( Start,Middle ) ;
00371 ClipLine( Middle,End ) ;
00372 return ;
00373 case 10 : GenLineToBelowLeft() ; GenLineToBelowRight() ; break ;
00374 case 11 : GenLineToBelowLeft() ; GenLineToAboveLeft() ; break ;
00375 case 12 : GenLineToBelowRight() ; GenLineToAboveRight() ; break ;
00376 case 13 : GenLineToBelowRight() ; GenLineToBelowLeft() ; break ;
00377 case 14 : GenLineToAboveLeft() ; GenLineToAboveRight() ; break ;
00378 case 15 : GenLineToAboveLeft() ; GenLineToBelowLeft() ; break ;
00379 case 16 : GenLineToAboveRight() ; GenLineToBelowRight() ; break ;
00380 case 17 : GenLineToAboveRight() ; GenLineToAboveLeft() ; break ;
00381 }
00382 LastSector = ThisSector ;
00383 }
00384
00386
00387 void SplitCurve( POINT &P0, POINT &P1, POINT &P2, POINT &P3 ) ;
00388
00389
00390 void ClipCurve( POINT &C0, POINT &C1, POINT &C2, POINT &C3 )
00391 {
00392 INT32 C1Sector = GetSector( C1 ) ;
00393 INT32 C2Sector = GetSector( C2 ) ;
00394 INT32 ThisSector = GetSector( C3 ) ;
00395
00396
00397
00398 INT32 RegionUnion = Region[LastSector] & Region[C1Sector] & Region[C2Sector] & Region[ThisSector];
00399 if ( ( RegionUnion & 0x0ff ) ||
00400 ( (RegionUnion & 0x300) && (LastSector!=ThisSector || LastSector==12) ) ||
00401 ( (C1Sector==LastSector || C1Sector==ThisSector) && (C2Sector==LastSector || C2Sector==ThisSector) ) )
00402 {
00403 switch ( CaseTable[(INT32)LastSector][(INT32)ThisSector] )
00404 {
00405 case 01 : GenLineToBelowLeft() ; break ;
00406 case 02 : GenLineToBelowRight() ; break ;
00407 case 03 : GenLineToAboveLeft() ; break ;
00408 case 04 : GenLineToAboveRight() ; break ;
00409 case 05 : GenLine(C0,FALSE) ;
00410 GenCurve(C1,C2,C3) ; break ;
00411 case 06 : if ( OFirstPoint )
00412 GenLine(C0,FALSE) ;
00413 GenCurve(C1,C2,C3) ; break ;
00414 case 07 : SplitCurve(C0,C1,C2,C3) ; return ;
00415 case 10 : GenLineToBelowLeft() ; GenLineToBelowRight() ; break ;
00416 case 11 : GenLineToBelowLeft() ; GenLineToAboveLeft() ; break ;
00417 case 12 : GenLineToBelowRight() ; GenLineToAboveRight() ; break ;
00418 case 13 : GenLineToBelowRight() ; GenLineToBelowLeft() ; break ;
00419 case 14 : GenLineToAboveLeft() ; GenLineToAboveRight() ; break ;
00420 case 15 : GenLineToAboveLeft() ; GenLineToBelowLeft() ; break ;
00421 case 16 : GenLineToAboveRight() ; GenLineToBelowRight() ; break ;
00422 case 17 : GenLineToAboveRight() ; GenLineToAboveLeft() ; break ;
00423 }
00424 LastSector = ThisSector ;
00425 }
00426 else
00427 SplitCurve(C0,C1,C2,C3) ;
00428 }
00429
00430
00431 void SplitCurve( POINT &P0, POINT &P1, POINT &P2, POINT &P3 )
00432 {
00433 POINT L1, L2, M, R1, R2 ;
00434 L1.x = (P0.x + P1.x)/2;
00435 L1.y = (P0.y + P1.y)/2;
00436 L2.x = (P0.x + 2*P1.x + P2.x)/4;
00437 L2.y = (P0.y + 2*P1.y + P2.y)/4;
00438 M.x = (P0.x + 3*P1.x + 3*P2.x + P3.x)/8;
00439 M.y = (P0.y + 3*P1.y + 3*P2.y + P3.y)/8;
00440 R1.x = (P1.x + 2*P2.x + P3.x)/4;
00441 R1.y = (P1.y + 2*P2.y + P3.y)/4;
00442 R2.x = (P2.x + P3.x)/2;
00443 R2.y = (P2.y + P3.y)/2;
00444 ClipCurve( P0,L1,L2, M ) ;
00445 ClipCurve( M,R1,R2,P3 ) ;
00446 }
00447
00449
00450 size_t FuzzyClip(
00451 PPOINT IPoints,
00452 PBYTE ITypes,
00453 size_t ILength,
00454 BOOL IsClosed,
00455 RECT *InnerRect,
00456 RECT *OuterRect,
00457 PPOINT pOPoints,
00458 PBYTE pOTypes,
00459 size_t pOMaxLength
00460 )
00461 {
00462 IRect = (GRECT*) InnerRect ;
00463 ORect = (GRECT*) OuterRect ;
00464 OPoints = pOPoints ;
00465 OTypes = pOTypes ;
00466 OMaxLength = pOMaxLength ;
00467 OLength = 0 ;
00468
00469 if ( ILength <= 0 )
00470 return 0 ;
00471
00472 try {
00473
00474 Index = 0 ;
00475 while ( Index<ILength )
00476 {
00477 OFirstPoint = TRUE ;
00478 POINT StartPoint = IPoints[Index++] ;
00479 LastSector = GetSector( StartPoint ) ;
00480 LastPoint = StartPoint ;
00481 while ( Index<ILength && (IsLine(ITypes[Index]) || IsCurve(ITypes[Index])) )
00482 {
00483 if ( IsLine(ITypes[Index]) )
00484 {
00485 ClipLine( LastPoint,IPoints[Index] ) ;
00486 LastPoint = IPoints[Index++] ;
00487 }
00488 else
00489 {
00490 ClipCurve( LastPoint,IPoints[Index],IPoints[Index+1],IPoints[Index+2] ) ;
00491 LastPoint = IPoints[Index+2] ;
00492 Index += 3 ;
00493 }
00494 }
00495 if ( IsClosed || (ITypes[Index-1] & PT_CLOSEFIGURE) )
00496 {
00497 ClipLine( LastPoint,StartPoint ) ;
00498 if ( !OFirstPoint )
00499 *(OTypes-1) |= PT_CLOSEFIGURE ;
00500 }
00501 if ( !OFirstPoint && IsMove(*(OTypes-1)) )
00502 {
00503 OTypes-- ;
00504 OPoints-- ;
00505 OLength-- ;
00506 }
00507 }
00508
00509 } catch ( INT32 ) {
00510 OLength = (size_t)-1 ;
00511 }
00512
00513 return OLength ;
00514 }
00515