00001 // $Id: bfxpixop.cpp 1282 2006-06-09 09:46:49Z alex $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 // This file implents the bitmap pixel operations 00099 00100 /* 00101 */ 00102 00103 #include "camtypes.h" 00104 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00105 #include "bfxpixop.h" 00106 #include "bfxalu.h" 00107 //#include "bitmap.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00108 #include "oilbitmap.h" 00109 00110 // The asm file defines FASTxxxxxx if there are fast versions of the routeines available 00111 //#include "bfxasm.h" 00112 00113 // This is not compulsory, but you may as well put it in so that the correct version 00114 // of your file can be registered in the .exe 00115 DECLARE_SOURCE("$Revision: 1282 $"); 00116 00117 CC_IMPLEMENT_DYNCREATE(BfxPixelOp, CCObject) 00118 CC_IMPLEMENT_DYNCREATE(BfxPixelOp32, BfxPixelOp) 00119 CC_IMPLEMENT_DYNCREATE(BfxPixelOp24, BfxPixelOp) 00120 CC_IMPLEMENT_DYNCREATE(BfxPixelOpPseudo, BfxPixelOp) 00121 CC_IMPLEMENT_DYNCREATE(BfxThresholdPixelOp, BfxPixelOp32) 00122 CC_IMPLEMENT_DYNCREATE(BfxColourThresholdPixelOp, BfxPixelOp32) 00123 CC_IMPLEMENT_DYNCREATE(BfxPositivePixelOp, BfxPixelOp32) 00124 CC_IMPLEMENT_DYNCREATE(BfxThresholdPixelOpPseudo, BfxPixelOpPseudo) 00125 CC_IMPLEMENT_DYNCREATE(BfxColourThresholdPixelOpPseudo, BfxPixelOpPseudo) 00126 CC_IMPLEMENT_DYNCREATE(BfxPositivePixelOpPseudo, BfxPixelOpPseudo) 00127 CC_IMPLEMENT_DYNCREATE(Octree, CCObject) 00128 00129 // This will get Camelot to display the filename and linenumber of any memory allocations 00130 // that are not released at program exit 00131 #define new CAM_DEBUG_NEW 00132 00133 00134 /******************************************************************************************** 00135 00136 > BfxPixelOp::BfxPixelOp() 00137 00138 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00139 Created: 14/03/95 00140 Inputs: None 00141 Outputs: Constructs object 00142 Returns: Nothing 00143 Purpose: Default constructor for pixel op 00144 Errors: None yet 00145 SeeAlso: - 00146 00147 ********************************************************************************************/ 00148 00149 BfxPixelOp::BfxPixelOp() 00150 { 00151 Base=NULL; 00152 Height=0; 00153 Width=WidthRounded=0; 00154 Size=0; 00155 DefaultValue=FALSE; 00156 Reset(); 00157 pA=NULL; 00158 pB=NULL; 00159 pT=NULL; 00160 Value=0; 00161 BPP=32; 00162 } 00163 00164 /******************************************************************************************** 00165 00166 > BfxPixelOp::~BfxPixelOp() 00167 00168 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00169 Created: 14/03/95 00170 Inputs: None 00171 Outputs: Constructs object 00172 Returns: Nothing 00173 Purpose: Default destructor for pixel op 00174 Errors: Error3 if DeInit hasn't been called. 00175 SeeAlso: - 00176 00177 ********************************************************************************************/ 00178 00179 BfxPixelOp::~BfxPixelOp() 00180 { 00181 } 00182 00183 /******************************************************************************************** 00184 00185 > BOOL BfxPixelOp::Reset() 00186 00187 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00188 Created: 14/03/95 00189 Inputs: None 00190 Outputs: Resets all parameters associated with the cache 00191 Returns: TRUE if succeeded, FALSE & error set if not 00192 Purpose: Resets all parameters associated with the cache 00193 Errors: Error 2 if init hasn't been called or GDraw fails 00194 Error 3 if windows and some other Oil layer are stangely mixed... 00195 Scope: Public 00196 SeeAlso: - 00197 00198 ********************************************************************************************/ 00199 00200 BOOL BfxPixelOp::Reset() 00201 { 00202 return TRUE; 00203 } 00204 00205 00206 00207 /******************************************************************************************** 00208 00209 > BOOL BfxPixelOp::SetBitmap(KernelBitmap * pKB, DWORD theCacheStateMask, DWORD theCacheValueMask, 00210 BOOL theDefaultValue); 00211 00212 00213 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00214 Created: 14/03/95 00215 Inputs: pKB = pointer to the bitmap 00216 theCacheStateMask = bit mask used to show cache information 00217 theCacheValueMask = bit mask used to show cache value information 00218 theDefaultValue = BOOL value associated with pixels outside the bitmap 00219 Outputs: None 00220 Returns: TRUE if succeeded, FALSE & error set if not 00221 Purpose: Class set up to use bitmap passed in 00222 Errors: Error 2 if init hasn't been called or GDraw fails 00223 Error 3 if windows and some other Oil layer are stangely mixed... 00224 Scope: Public 00225 SeeAlso: - 00226 00227 ********************************************************************************************/ 00228 00229 BOOL BfxPixelOp::SetBitmap(KernelBitmap * pKB, DWORD theCacheStateMask, DWORD theCacheValueMask, 00230 BOOL theDefaultValue) 00231 { 00232 Base = NULL; 00233 ERROR2IF( ((!pKB) || (pKB->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap"); 00234 ERROR3IF( (!(pKB->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency"); 00235 00236 BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(pKB->ActualBitmap))->BMInfo->bmiHeader); 00237 00238 ERROR2IF( (BPP && pBMI->biBitCount != BPP), FALSE, "BfxPixelOp called with incorrect BPP"); 00239 00240 Base = (DWORD *)(void *)(((CWxBitmap *)(pKB->ActualBitmap))->BMBytes); 00241 Width = pBMI->biWidth; 00242 INT32 Bits = pBMI->biBitCount; 00243 switch (Bits) 00244 { 00245 case 1 : WidthRounded = (Width+31) &~31; break; 00246 case 2 : WidthRounded = (Width+15) &~15; break; 00247 case 4 : WidthRounded = (Width+7) &~7; break; 00248 case 8 : WidthRounded = (Width+3) &~3; break; 00249 case 16: WidthRounded = (Width+1) &~1; break; 00250 case 32: 00251 default: 00252 WidthRounded = Width; break; 00253 } 00254 00255 Height = pBMI->biHeight; 00256 Size = (pBMI->biSizeImage)>>2; 00257 00258 return TRUE; 00259 } 00260 00261 /******************************************************************************************** 00262 00263 > BOOL BfxPixelOp::IsPixelReallyInRegion(INT32 x, INT32 y) 00264 00265 00266 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00267 Created: 14/03/95 00268 Inputs: x,y = coordinates of pixel 00269 Outputs: None 00270 Returns: Whether pixel is in the region or not. 00271 Purpose: To be overriden by derived classes 00272 Errors: Always errors. The base class should never be called 00273 Scope: Public 00274 SeeAlso: BfxPixelOp::IsInRegion() 00275 00276 Outisiders should used the cached version BfxPixelOp::IsInRegion() 00277 00278 ********************************************************************************************/ 00279 00280 BOOL BfxPixelOp::IsPixelReallyInRegion(INT32 x, INT32 y) 00281 { 00282 ERROR3("How come base class BfxPixelOp::IsPixelReallyInRegion has got called?"); 00283 return DefaultValue; 00284 } 00285 00286 /******************************************************************************************** 00287 00288 > BOOL BfxPixelOp::IsInRegion(INT32 x, INT32 y) 00289 00290 00291 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00292 Created: 14/03/95 00293 Inputs: x,y = coordinates of pixel 00294 Outputs: None 00295 Returns: Whether pixel is in the region or not (uses caching) 00296 Purpose: To be overriden by derived classes 00297 Errors: Always errors. The base class should never be called 00298 Scope: Public 00299 SeeAlso: BfxPixelOp::IsPixelReallyInRegion() 00300 00301 NB This function is inline 00302 00303 ********************************************************************************************/ 00304 00305 /******************************************************************************************** 00306 00307 > BOOL BfxPixelOp::SetAuxilliaryBitmaps(KernelBitmap * pProposed, KernelBitmap * pCurrent, 00308 KernelBitmap * pOriginal, INT32 Threshold, DWORD theColour); 00309 00310 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00311 Created: 14/03/95 00312 Inputs: pProposed = the proposed bitmap (with new proposed grad fill) 00313 pCurrent = the current bitmap (as built up) 00314 pOriginal = the original image (to trace) 00315 Threshold = new threshold 00316 theColour = Colour to look for 00317 Outputs: None 00318 Returns: TRUE on success else FALSE & error set 00319 Purpose: Sets up auxilliary bitmaps for derived classes 00320 Errors: Several 00321 Scope: Public 00322 SeeAlso: BfxPixelOp::IsPixelReallyInRegion() 00323 00324 The bitmaps may be NULL if you don't want to use them 00325 00326 ********************************************************************************************/ 00327 00328 BOOL BfxPixelOp::SetAuxilliaryBitmaps(KernelBitmap * pProposed /*A*/, KernelBitmap * pCurrent /*B*/, 00329 KernelBitmap * pOriginal /*T*/, INT32 Threshold, DWORD theColour) 00330 { 00331 if (pProposed) 00332 { 00333 ERROR2IF( (pProposed->ActualBitmap==NULL) ,FALSE,"BfxPixelOp can't find OIL bitmap"); 00334 ERROR3IF( (!(pProposed->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxPixelOp Oil layer inconsistency"); 00335 00336 BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(pProposed->ActualBitmap))->BMInfo->bmiHeader); 00337 00338 ERROR2IF( ((pBMI->biHeight != Height) || (pBMI->biWidth != Width) || (BPP && pBMI->biBitCount !=BPP)), FALSE, 00339 "Incompatible bitmaps for BfxPixelOp::SetAuxilliaryBitmap"); 00340 pA = (DWORD *)(void *)(((CWxBitmap *)(pProposed->ActualBitmap))->BMBytes); 00341 } 00342 else 00343 { 00344 pA = NULL; 00345 } 00346 00347 if (pOriginal) 00348 { 00349 ERROR2IF( (pOriginal->ActualBitmap==NULL) ,FALSE,"BfxPixelOp can't find OIL bitmap"); 00350 ERROR3IF( (!(pOriginal->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxPixelOp Oil layer inconsistency"); 00351 00352 BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(pOriginal->ActualBitmap))->BMInfo->bmiHeader); 00353 00354 ERROR2IF( ((pBMI->biHeight != Height) || (pBMI->biWidth != Width) || (BPP && pBMI->biBitCount !=BPP)), FALSE, 00355 "Incompatible bitmaps for BfxPixelOp::SetAuxilliaryBitmap"); 00356 pT = (DWORD *)(void *)(((CWxBitmap *)(pOriginal->ActualBitmap))->BMBytes); 00357 } 00358 else 00359 { 00360 pT = NULL; 00361 } 00362 00363 if (pCurrent) 00364 { 00365 ERROR2IF( (pCurrent->ActualBitmap==NULL) ,FALSE,"BfxPixelOp can't find OIL bitmap"); 00366 ERROR3IF( (!(pCurrent->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxPixelOp Oil layer inconsistency"); 00367 00368 BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(pCurrent->ActualBitmap))->BMInfo->bmiHeader); 00369 00370 ERROR2IF( ((pBMI->biHeight != Height) || (pBMI->biWidth != Width) || (BPP && pBMI->biBitCount !=BPP)), FALSE, 00371 "Incompatible bitmaps for BfxPixelOp::SetAuxilliaryBitmap"); 00372 pB = (DWORD *)(void *)(((CWxBitmap *)(pCurrent->ActualBitmap))->BMBytes); 00373 } 00374 else 00375 { 00376 pB = NULL; 00377 } 00378 00379 00380 Value = Threshold; 00381 Colour = theColour; 00382 return TRUE; 00383 } 00384 00385 /******************************************************************************************** 00386 00387 > BfxPixelOp32::BfxPixelOp32() 00388 00389 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00390 Created: 14/03/95 00391 Inputs: None 00392 Outputs: Constructs object 00393 Returns: Nothing 00394 Purpose: Default constructor for pixel op 00395 Errors: None yet 00396 SeeAlso: - 00397 00398 ********************************************************************************************/ 00399 00400 BfxPixelOp32::BfxPixelOp32() : BfxPixelOp() 00401 { 00402 CacheStateMask=0; 00403 CacheValueMask=0; 00404 CacheMarks=0; 00405 BPP=32; 00406 } 00407 00408 /******************************************************************************************** 00409 00410 > BfxPixelOp32::~BfxPixelOp32() 00411 00412 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00413 Created: 14/03/95 00414 Inputs: None 00415 Outputs: Constructs object 00416 Returns: Nothing 00417 Purpose: Default destructor for pixel op 00418 Errors: Error3 if DeInit hasn't been called. 00419 SeeAlso: - 00420 00421 ********************************************************************************************/ 00422 00423 BfxPixelOp32::~BfxPixelOp32() 00424 { 00425 } 00426 00427 /******************************************************************************************** 00428 00429 > BOOL BfxPixelOp32::Reset() 00430 00431 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00432 Created: 14/03/95 00433 Inputs: None 00434 Outputs: Resets all parameters associated with the cache 00435 Returns: TRUE if succeeded, FALSE & error set if not 00436 Purpose: Resets all parameters associated with the cache 00437 Errors: Error 2 if init hasn't been called or GDraw fails 00438 Error 3 if windows and some other Oil layer are stangely mixed... 00439 Scope: Public 00440 SeeAlso: - 00441 00442 ********************************************************************************************/ 00443 00444 BOOL BfxPixelOp32::Reset() 00445 { 00446 MinX=(1<<30); 00447 MinY=(1<<30); 00448 MaxX=0; 00449 MaxY=0; 00450 CacheMarks = 0; 00451 return BfxPixelOp::Reset(); 00452 } 00453 00454 00455 00456 /******************************************************************************************** 00457 00458 > BOOL BfxPixelOp32::SetBitmap(KernelBitmap * pKB, DWORD theCacheStateMask, DWORD theCacheValueMask, 00459 BOOL theDefaultValue); 00460 00461 00462 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00463 Created: 14/03/95 00464 Inputs: pKB = pointer to the bitmap 00465 theCacheStateMask = bit mask used to show cache information 00466 theCacheValueMask = bit mask used to show cache value information 00467 theDefaultValue = BOOL value associated with pixels outside the bitmap 00468 Outputs: None 00469 Returns: TRUE if succeeded, FALSE & error set if not 00470 Purpose: Class set up to use bitmap passed in 00471 Errors: Error 2 if init hasn't been called or GDraw fails 00472 Error 3 if windows and some other Oil layer are stangely mixed... 00473 Scope: Public 00474 SeeAlso: - 00475 00476 ********************************************************************************************/ 00477 00478 BOOL BfxPixelOp32::SetBitmap(KernelBitmap * pKB, DWORD theCacheStateMask, DWORD theCacheValueMask, 00479 BOOL theDefaultValue) 00480 { 00481 Base = NULL; 00482 ERROR2IF( ((!pKB) || (pKB->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap"); 00483 ERROR3IF( (!(pKB->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency"); 00484 00485 BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(pKB->ActualBitmap))->BMInfo->bmiHeader); 00486 00487 ERROR2IF((pBMI->biBitCount !=32), FALSE,"Bad BfxALU A reg"); 00488 00489 if (!BfxPixelOp::SetBitmap(pKB, theCacheStateMask,theCacheValueMask, theDefaultValue)) return FALSE; 00490 00491 CacheStateMask = theCacheStateMask; 00492 CacheValueMask = theCacheValueMask; 00493 DefaultValue = theDefaultValue; 00494 00495 return TRUE; 00496 } 00497 00498 /******************************************************************************************** 00499 00500 > BOOL BfxPixelOp32::ClearEntireCache() 00501 00502 00503 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00504 Created: 14/03/95 00505 Inputs: None 00506 Outputs: None 00507 Returns: TRUE if succeeded, FALSE & error set if not 00508 Purpose: Clears the entire bitmap of caching information 00509 Errors: Error 2 if init hasn't been called or GDraw fails 00510 Error 3 if windows and some other Oil layer are stangely mixed... 00511 Scope: Public 00512 SeeAlso: - 00513 00514 ********************************************************************************************/ 00515 00516 BOOL BfxPixelOp32::ClearEntireCache() 00517 { 00518 MinX=0; 00519 MinY=0; 00520 MaxX=Width-1; 00521 MaxY=Height-1; 00522 return ClearCachedArea(); 00523 } 00524 00525 /******************************************************************************************** 00526 00527 > BOOL BfxPixelOp32::ClearCachedArea() 00528 00529 00530 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00531 Created: 14/03/95 00532 Inputs: None 00533 Outputs: None 00534 Returns: TRUE if succeeded, FALSE & error set if not 00535 Purpose: Clears the caching information from the area in which it's been stored 00536 Errors: Error 2 if init hasn't been called or GDraw fails 00537 Error 3 if windows and some other Oil layer are stangely mixed... 00538 Scope: Public 00539 SeeAlso: - 00540 00541 ********************************************************************************************/ 00542 00543 BOOL BfxPixelOp32::ClearCachedArea() 00544 { 00545 ERROR2IF(!Base,FALSE,"BfxPixelOp32::SetBitmap not called"); 00546 if ((MaxX<MinX) || (MaxY<MinY)) return TRUE; 00547 INT32 x; 00548 INT32 y; 00549 DWORD v=~(CacheValueMask | CacheStateMask); 00550 for (y=MinY; y<=MaxY; y++) for (x=MinX; x<=MaxX; x++) __bfxpixop_xy(x,y)&=v; 00551 Reset(); 00552 return TRUE; 00553 } 00554 00555 /******************************************************************************************** 00556 00557 > BOOL BfxPixelOp32::IsInRegion(INT32 x, INT32 y) 00558 00559 00560 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00561 Created: 14/03/95 00562 Inputs: x,y = coordinates of pixel 00563 Outputs: None 00564 Returns: Whether pixel is in the region or not (uses caching) 00565 Purpose: To be overriden by derived classes 00566 Errors: Always errors. The base class should never be called 00567 Scope: Public 00568 SeeAlso: BfxPixelOp32::IsPixelReallyInRegion() 00569 00570 NB This function is inline 00571 00572 ********************************************************************************************/ 00573 00574 /******************************************************************************************** 00575 00576 > BOOL BfxPixelOp32::GetValueAdjustCache(INT32 x, INT32 y) 00577 00578 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00579 Created: 14/03/95 00580 Inputs: x,y = coordinates of pixel 00581 Outputs: None 00582 Returns: Whether pixel is in the region or not (and alters cache parameters) 00583 Purpose: To be overriden by derived classes 00584 Errors: Always errors. The base class should never be called 00585 Scope: Public 00586 SeeAlso: BfxPixelOp32::IsPixelReallyInRegion() 00587 00588 ********************************************************************************************/ 00589 00590 BOOL BfxPixelOp32::GetValueAdjustCache(INT32 x, INT32 y) 00591 { 00592 if (x<MinX) MinX=x; 00593 if (x>MaxX) MaxX=x; 00594 if (y<MinY) MinY=y; 00595 if (y>MaxY) MaxY=y; 00596 BOOL state; 00597 // The following is disgusting but is time critical. Increment CacheMarks where we find 00598 // a previously undiscovered newly marked pixel 00599 CacheMarks+= (state = /*assign*/ IsPixelReallyInRegion(x,y)); 00600 return state; 00601 } 00602 00603 /******************************************************************************************** 00604 00605 > BOOL BfxPixelOp32::CheckMinimumArea(INT32 MinimumArea, INT32 InitialX, INT32 InitialY, BOOL * FoundRegion) 00606 00607 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00608 Created: 17/1/95 00609 Inputs: MinimumArea = minimum area 00610 Outputs: FoundRegion set as per whether it's found a region 00611 Returns: TRUE on success, FALSE (& error set) on failure 00612 Purpose: Determines whether atleast (MinimumArea) pixels are within the region 00613 Errors: None yet 00614 Scope: Public 00615 SeeAlso: TraceControl::FloodSearch 00616 00617 FoundRegion is set according the the result. The search starts at InitialX/InitialY 00618 00619 This call *must* be done immediately (yes, immediately) after the cache is cleared. If not 00620 you lose all your caching. Har har. 00621 00622 ********************************************************************************************/ 00623 00624 BOOL BfxPixelOp32::CheckMinimumArea(INT32 MinimumArea, INT32 InitialX, INT32 InitialY, BOOL * FoundRegion) 00625 { 00626 if (!ClearCachedArea()) return FALSE; 00627 if (!FloodSearch(InitialX, InitialY, MinimumArea)) return FALSE; 00628 *FoundRegion = (GetCacheMarks() >= MinimumArea); 00629 return TRUE; 00630 } 00631 00632 /******************************************************************************************** 00633 00634 > BOOL BfxPixelOp32::FloodSearch(INT32 x, INT32 y, INT32 MinimumArea) 00635 00636 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00637 Created: 17/1/95 00638 Inputs: x = start x 00639 y = start y 00640 MinimumArea = minimum area 00641 Outputs: None 00642 Returns: TRUE on success, FALSE (& error set) on failure 00643 Purpose: Recursively flood fills an area until >=MinimumArea pixels are found 00644 Errors: None yet 00645 Scope: Public 00646 SeeAlso: BfxPixelOp32::CheckMinimumArea, TraceControl::CheckMinimumArea 00647 00648 ***ONLY TO BE USED FROM CheckMinimumArea *** 00649 00650 ********************************************************************************************/ 00651 00652 BOOL BfxPixelOp32::FloodSearch(INT32 x, INT32 y, INT32 MinimumArea) 00653 { 00654 if (IsCached(x,y) // We've been here before 00655 || GetCacheMarks()>=MinimumArea) // We've got enough 00656 return TRUE; 00657 if (IsInRegion(x,y)) 00658 { 00659 if (!( FloodSearch(x-1, y-1, MinimumArea) && 00660 FloodSearch(x , y-1, MinimumArea) && 00661 FloodSearch(x+1, y-1, MinimumArea) && 00662 FloodSearch(x-1, y , MinimumArea) && 00663 FloodSearch(x+1, y , MinimumArea) && 00664 FloodSearch(x-1, y+1, MinimumArea) && 00665 FloodSearch(x , y+1, MinimumArea) && 00666 FloodSearch(x+1, y+1, MinimumArea) && 00667 TRUE)) return TRUE; 00668 } 00669 return TRUE; 00670 } 00671 00672 00673 /******************************************************************************************** 00674 00675 > BfxPixelOpPseudo::BfxPixelOpPseudo() 00676 00677 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00678 Created: 14/03/95 00679 Inputs: None 00680 Outputs: Constructs object 00681 Returns: Nothing 00682 Purpose: Default constructor for pixel op 00683 Errors: None yet 00684 SeeAlso: - 00685 00686 ********************************************************************************************/ 00687 00688 BfxPixelOpPseudo::BfxPixelOpPseudo() : BfxPixelOp() 00689 { 00690 BPP=8; 00691 } 00692 00693 /******************************************************************************************** 00694 00695 > BfxPixelOpPseudo::~BfxPixelOpPseudo() 00696 00697 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00698 Created: 14/03/95 00699 Inputs: None 00700 Outputs: Constructs object 00701 Returns: Nothing 00702 Purpose: Default destructor for pixel op 00703 Errors: Error3 if DeInit hasn't been called. 00704 SeeAlso: - 00705 00706 ********************************************************************************************/ 00707 00708 BfxPixelOpPseudo::~BfxPixelOpPseudo() 00709 { 00710 } 00711 00712 /******************************************************************************************** 00713 00714 > BOOL BfxPixelOpPseudo::Reset() 00715 00716 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00717 Created: 14/03/95 00718 Inputs: None 00719 Outputs: Resets all parameters associated with the cache 00720 Returns: TRUE if succeeded, FALSE & error set if not 00721 Purpose: Resets all parameters associated with the cache 00722 Errors: Error 2 if init hasn't been called or GDraw fails 00723 Error 3 if windows and some other Oil layer are stangely mixed... 00724 Scope: Public 00725 SeeAlso: - 00726 00727 ********************************************************************************************/ 00728 00729 BOOL BfxPixelOpPseudo::Reset() 00730 { 00731 return BfxPixelOp::Reset(); 00732 } 00733 00734 00735 00736 /******************************************************************************************** 00737 00738 > BOOL BfxPixelOpPseudo::SetBitmap(KernelBitmap * pKB, DWORD theCacheStateMask, DWORD theCacheValueMask, 00739 BOOL theDefaultValue); 00740 00741 00742 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00743 Created: 14/03/95 00744 Inputs: pKB = pointer to the bitmap 00745 theCacheStateMask = bit mask used to show cache information 00746 theCacheValueMask = bit mask used to show cache value information 00747 theDefaultValue = BOOL value associated with pixels outside the bitmap 00748 Outputs: None 00749 Returns: TRUE if succeeded, FALSE & error set if not 00750 Purpose: Class set up to use bitmap passed in 00751 Errors: Error 2 if init hasn't been called or GDraw fails 00752 Error 3 if windows and some other Oil layer are stangely mixed... 00753 Scope: Public 00754 SeeAlso: - 00755 00756 ********************************************************************************************/ 00757 00758 BOOL BfxPixelOpPseudo::SetBitmap(KernelBitmap * pKB, DWORD theCacheStateMask, DWORD theCacheValueMask, 00759 BOOL theDefaultValue) 00760 { 00761 Base = NULL; 00762 ERROR2IF( ((!pKB) || (pKB->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap"); 00763 ERROR3IF( (!(pKB->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency"); 00764 00765 BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(pKB->ActualBitmap))->BMInfo->bmiHeader); 00766 00767 BPP=pBMI->biBitCount; 00768 ERROR2IF(BPP>8, FALSE,"Pseudo colour BMP not pseudo colour"); 00769 switch (BPP) 00770 { 00771 case 1 : Log2BPP=0; break; 00772 case 2 : Log2BPP=1; break; 00773 case 4 : Log2BPP=2; break; 00774 case 8 : Log2BPP=3; break; 00775 default: 00776 ERROR2(FALSE, "Invalid BPP field"); 00777 } 00778 00779 if (!BfxPixelOp::SetBitmap(pKB, theCacheStateMask,theCacheValueMask, theDefaultValue)) return FALSE; 00780 00781 BPPMask = (BPP==32)?0xFFFFFFFF:(1<<BPP)-1; 00782 XShift = 3-Log2BPP; 00783 XMask = (1<<XShift)-1; 00784 Size = (pBMI->biSizeImage<<3)>>Log2BPP; 00785 00786 return TRUE; 00787 } 00788 00789 00790 00791 00792 /******************************************************************************************** 00793 00794 > BOOL BfxPositivePixelOp::IsPixelReallyInRegion(INT32 x, INT32 y) 00795 00796 00797 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00798 Created: 14/03/95 00799 Inputs: x,y = coordinates of pixel 00800 Outputs: None 00801 Returns: Whether pixel is in the region or not. 00802 Purpose: To be overriden by derived classes 00803 Errors: None 00804 Scope: Public 00805 SeeAlso: BfxPixelOp::IsInRegion() 00806 00807 The region calculation is done as ( ((B-T)^2 >= Value ) && ((A-T)^2 < Value)) 00808 where A = pProposed - the proposed image (i.e. new thing with grad fill on) 00809 B = pCurrent - the current built up image 00810 T = pOriginal - the image to be traced 00811 00812 ********************************************************************************************/ 00813 00814 BOOL BfxPositivePixelOp::IsPixelReallyInRegion(INT32 x, INT32 y) 00815 { 00816 INT32 BE; 00817 INT32 AE; 00818 DWORD Pixel = y*Width+x; 00819 00820 AE = ( IntegerSquare( ((INT32)(((AluPix32 *) pA)[Pixel].R)) - ((INT32)(((AluPix32 *) pT)[Pixel].R))) 00821 + IntegerSquare( ((INT32)(((AluPix32 *) pA)[Pixel].G)) - ((INT32)(((AluPix32 *) pT)[Pixel].G))) 00822 + IntegerSquare( ((INT32)(((AluPix32 *) pA)[Pixel].B)) - ((INT32)(((AluPix32 *) pT)[Pixel].B))) ); 00823 00824 BE = (IntegerSquare( ((INT32)(((AluPix32 *) pB)[Pixel].R)) - ((INT32)(((AluPix32 *) pT)[Pixel].R))) 00825 + IntegerSquare( ((INT32)(((AluPix32 *) pB)[Pixel].G)) - ((INT32)(((AluPix32 *) pT)[Pixel].G))) 00826 + IntegerSquare( ((INT32)(((AluPix32 *) pB)[Pixel].B)) - ((INT32)(((AluPix32 *) pT)[Pixel].B))) ); 00827 00828 return ((AE<Value) && (BE>=Value)); 00829 } 00830 00831 /******************************************************************************************** 00832 00833 > BOOL BfxColourThresholdPixelOp::IsPixelReallyInRegion(INT32 x, INT32 y) 00834 00835 00836 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00837 Created: 14/03/95 00838 Inputs: x,y = coordinates of pixel 00839 Outputs: None 00840 Returns: Whether pixel is in the region or not. 00841 Purpose: To be overriden by derived classes 00842 Errors: None 00843 Scope: Public 00844 SeeAlso: BfxPixelOp::IsInRegion() 00845 00846 The region calculation is done as ( ((B-T)^2 >= Value ) && ((Colour-T)^2 < Value)) 00847 where Colour = the colour to measure against 00848 B = pCurrent - the current built up image 00849 T = pOriginal - the image to be traced 00850 00851 ********************************************************************************************/ 00852 00853 BOOL BfxColourThresholdPixelOp::IsPixelReallyInRegion(INT32 x, INT32 y) 00854 { 00855 INT32 BE; 00856 INT32 AE; 00857 DWORD Pixel = y*Width+x; 00858 00859 AluPix32 TheColour; 00860 *(DWORD *)(void *)(&TheColour)=Colour; // Yuck 00861 00862 AE = ( IntegerSquare( ((INT32)(TheColour.R)) - ((INT32)(((AluPix32 *) pT)[Pixel].R))) 00863 + IntegerSquare( ((INT32)(TheColour.G)) - ((INT32)(((AluPix32 *) pT)[Pixel].G))) 00864 + IntegerSquare( ((INT32)(TheColour.B)) - ((INT32)(((AluPix32 *) pT)[Pixel].B))) ); 00865 00866 BE = (IntegerSquare( ((INT32)(((AluPix32 *) pB)[Pixel].R)) - ((INT32)(((AluPix32 *) pT)[Pixel].R))) 00867 + IntegerSquare( ((INT32)(((AluPix32 *) pB)[Pixel].G)) - ((INT32)(((AluPix32 *) pT)[Pixel].G))) 00868 + IntegerSquare( ((INT32)(((AluPix32 *) pB)[Pixel].B)) - ((INT32)(((AluPix32 *) pT)[Pixel].B))) ); 00869 00870 return ((AE<Value) && (BE>=Value)); 00871 } 00872 00873 /******************************************************************************************** 00874 00875 > BOOL BfxThresholdPixelOp::IsPixelReallyInRegion(INT32 x, INT32 y) 00876 00877 00878 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00879 Created: 14/03/95 00880 Inputs: x,y = coordinates of pixel 00881 Outputs: None 00882 Returns: Whether pixel is in the region or not. 00883 Purpose: To be overriden by derived classes 00884 Errors: None 00885 Scope: Public 00886 SeeAlso: BfxPixelOp::IsInRegion() 00887 00888 The region calculation is done as ( (B-T)^2 >= Value ) 00889 where Colour = the colour to measure against 00890 B = pCurrent - the current built up image 00891 T = pOriginal - the image to be traced 00892 00893 ********************************************************************************************/ 00894 00895 BOOL BfxThresholdPixelOp::IsPixelReallyInRegion(INT32 x, INT32 y) 00896 { 00897 DWORD Pixel = y*Width+x; 00898 00899 return ( (IntegerSquare( ((INT32)(((AluPix32 *) pB)[Pixel].R)) - ((INT32)(((AluPix32 *) pT)[Pixel].R))) 00900 + IntegerSquare( ((INT32)(((AluPix32 *) pB)[Pixel].G)) - ((INT32)(((AluPix32 *) pT)[Pixel].G))) 00901 + IntegerSquare( ((INT32)(((AluPix32 *) pB)[Pixel].B)) - ((INT32)(((AluPix32 *) pT)[Pixel].B))) ) >= Value ); 00902 } 00903 00904 00905 /******************************************************************************************** 00906 00907 > BOOL BfxPositivePixelOpPseudo::IsPixelReallyInRegion(INT32 x, INT32 y) 00908 00909 00910 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00911 Created: 14/03/95 00912 Inputs: x,y = coordinates of pixel 00913 Outputs: None 00914 Returns: Whether pixel is in the region or not. 00915 Purpose: To be overriden by derived classes 00916 Errors: None 00917 Scope: Public 00918 SeeAlso: BfxPixelOpPseudo::IsInRegion() 00919 00920 The region calculation is done as ( ((B-T)^2 >= Value ) && ((A-T)^2 < Value)) 00921 where A = pProposed - the proposed image (i.e. new thing with grad fill on) 00922 B = pCurrent - the current built up image 00923 T = pOriginal - the image to be traced 00924 00925 ********************************************************************************************/ 00926 00927 #define __bfx_pseudopixel(i,x,y) BfxPixelOp::ReadPixel((void *)i,x,y) 00928 //((((DWORD *)i)[Pixel]>>shift)&BPPMask) 00929 00930 00931 BOOL BfxPositivePixelOpPseudo::IsPixelReallyInRegion(INT32 x, INT32 y) 00932 { 00933 // DWORD Pixel = (x+y*WidthRounded)>>XShift; 00934 // DWORD shift = x & XMask; 00935 DWORD tval=__bfx_pseudopixel(pT,x,y); 00936 return (__bfx_pseudopixel(pB,x,y) != tval) && (__bfx_pseudopixel(pA,x,y) == tval); 00937 } 00938 00939 /******************************************************************************************** 00940 00941 > BOOL BfxColourThresholdPixelOpPseudo::IsPixelReallyInRegion(INT32 x, INT32 y) 00942 00943 00944 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00945 Created: 14/03/95 00946 Inputs: x,y = coordinates of pixel 00947 Outputs: None 00948 Returns: Whether pixel is in the region or not. 00949 Purpose: To be overriden by derived classes 00950 Errors: None 00951 Scope: Public 00952 SeeAlso: BfxPixelOpPseudo::IsInRegion() 00953 00954 The region calculation is done as ( ((B-T)^2 >= Value ) && ((Colour-T)^2 < Value)) 00955 where Colour = the colour to measure against 00956 B = pCurrent - the current built up image 00957 T = pOriginal - the image to be traced 00958 00959 ********************************************************************************************/ 00960 00961 BOOL BfxColourThresholdPixelOpPseudo::IsPixelReallyInRegion(INT32 x, INT32 y) 00962 { 00963 // DWORD Pixel = (x+y*WidthRounded)>>XShift; 00964 // DWORD shift = x & XMask; 00965 DWORD tval=__bfx_pseudopixel(pT,x,y); 00966 return (__bfx_pseudopixel(pB,x,y) != tval) && (Colour == tval); 00967 } 00968 00969 /******************************************************************************************** 00970 00971 > BOOL BfxThresholdPixelOpPseudo::IsPixelReallyInRegion(INT32 x, INT32 y) 00972 00973 00974 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 00975 Created: 14/03/95 00976 Inputs: x,y = coordinates of pixel 00977 Outputs: None 00978 Returns: Whether pixel is in the region or not. 00979 Purpose: To be overriden by derived classes 00980 Errors: None 00981 Scope: Public 00982 SeeAlso: BfxPixelOpPseudo::IsInRegion() 00983 00984 The region calculation is done as ( (B-T)^2 >= Value ) 00985 where Colour = the colour to measure against 00986 B = pCurrent - the current built up image 00987 T = pOriginal - the image to be traced 00988 00989 ********************************************************************************************/ 00990 00991 BOOL BfxThresholdPixelOpPseudo::IsPixelReallyInRegion(INT32 x, INT32 y) 00992 { 00993 // DWORD Pixel = (x+y*WidthRounded)>>XShift; 00994 // DWORD shift = x & XMask; 00995 return __bfx_pseudopixel(pB,x,y) != __bfx_pseudopixel(pT,x,y); 00996 } 00997 00998 /******************************************************************************************** 00999 01000 > void BfxPixelOpPseudo::TranslateToRGB(DWORD Colour, KernelBitmap * pKB, 01001 INT32 * R, INT32 * G, INT32 * B) 01002 01003 01004 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 01005 Created: 14/03/95 01006 Inputs: Colour = the colour 01007 Outputs: R, G, B = rd, green, blue components 01008 Returns: None 01009 Purpose: To get the R G B values corresponding to a memory entry 01010 Errors: None 01011 Scope: Public 01012 SeeAlso: BfxPixelOpPseudo::IsInRegion() 01013 01014 ********************************************************************************************/ 01015 01016 void BfxPixelOpPseudo::TranslateToRGB(DWORD Colour, KernelBitmap * pKB, 01017 INT32 * R, INT32 * G, INT32 * B) 01018 { 01019 RGBQUAD Col; 01020 01021 if ((!pKB) || (pKB->ActualBitmap==NULL)) 01022 { 01023 ERROR3( "BfxALU can't find OIL bitmap"); 01024 return; 01025 } 01026 ERROR3IF( (!(pKB->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency"); 01027 01028 BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(pKB->ActualBitmap))->BMInfo->bmiHeader); 01029 01030 if ( Colour >= pBMI->biClrUsed ) 01031 { 01032 ERROR3("Too large palette entry"); 01033 *R=*G=*B=0; 01034 return; 01035 } 01036 01037 Col = ((RGBQUAD *)(pBMI+1/*pointer arith*/))[Colour]; 01038 01039 *R = Col.rgbRed; 01040 *G = Col.rgbGreen; 01041 *B = Col.rgbBlue; 01042 return; 01043 }; 01044 01045 /******************************************************************************************** 01046 01047 > BOOL BfxPixelOpPseudo::CheckMinimumArea(INT32 MinimumArea, INT32 InitialX, INT32 InitialY, BOOL * FoundRegion) 01048 01049 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 01050 Created: 17/1/95 01051 Inputs: MinimumArea = minimum area 01052 Outputs: FoundRegion set as per whether it's found a region 01053 Returns: TRUE on success, FALSE (& error set) on failure 01054 Purpose: Determines whether atleast (MinimumArea) pixels are within the region 01055 Errors: None yet 01056 Scope: Public 01057 SeeAlso: BfxPixelOpPseudo::CheckMinimumArea, TraceControl::FloodSearch 01058 01059 FoundRegion is set according the the result. The search starts at InitialX/InitialY 01060 01061 This call *must* be done immediately (yes, immediately) after the cache is cleared. If not 01062 you lose all your caching. Har har. 01063 01064 ********************************************************************************************/ 01065 01066 BOOL BfxPixelOpPseudo::CheckMinimumArea(INT32 MinimumArea, INT32 InitialX, INT32 InitialY, BOOL * FoundRegion) 01067 { 01068 // This is a bodge currently 01069 *FoundRegion = FALSE; 01070 if (IsInRegion(InitialX, InitialY)) 01071 { 01072 if (MinimumArea>BFX_PSEUDOFLOODSIZE-1) MinimumArea=BFX_PSEUDOFLOODSIZE-1; 01073 INT32 FloodArray[BFX_PSEUDOFLOODSIZE][2]; 01074 INT32 FloodTop=0; 01075 01076 if (!FloodSearch(InitialX, InitialY, MinimumArea, FloodArray, &FloodTop)) return FALSE; 01077 *FoundRegion = (FloodTop >= MinimumArea); 01078 01079 for (INT32 n=0; n<FloodTop; n++) WriteOriginalPixel(FloodArray[n][0], FloodArray[n][1], Colour); 01080 } 01081 01082 return TRUE; 01083 } 01084 01085 /******************************************************************************************** 01086 01087 > BOOL BfxPixelOpPseudo::FloodSearch(INT32 x, INT32 y, INT32 MinimumArea, 01088 INT32 FloodArray[BFX_PSEUDOFLOODSIZE][2], INT32 * FloodTop) 01089 01090 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 01091 Created: 17/1/95 01092 Inputs: x = start x 01093 y = start y 01094 MinimumArea = minimum area 01095 Outputs: None 01096 Returns: TRUE on success, FALSE (& error set) on failure 01097 Purpose: Recursively flood fills an area until >=MinimumArea pixels are found 01098 Errors: None yet 01099 Scope: Public 01100 SeeAlso: BfxPixelOpPseudo::CheckMinimumArea, TraceControl::CheckMinimumArea 01101 01102 ***ONLY TO BE USED FROM CheckMinimumArea *** 01103 01104 ********************************************************************************************/ 01105 01106 BOOL BfxPixelOpPseudo::FloodSearch(INT32 x, INT32 y, INT32 MinimumArea, 01107 INT32 FloodArray[BFX_PSEUDOFLOODSIZE][2], INT32 * FloodTop) 01108 { 01109 if (IsInRegion(x,y)) 01110 { 01111 WriteOriginalPixel(x, y, Colour^1); // make it out of the region 01112 FloodArray[*FloodTop][0]=x; 01113 FloodArray[(*FloodTop)++][1]=y; // save coordinate so we can restore value later 01114 if (*FloodTop>=MinimumArea) return TRUE; 01115 if (!FloodSearch(x-1, y-1, MinimumArea, FloodArray, FloodTop)) return FALSE; 01116 if (*FloodTop>=MinimumArea) return TRUE; 01117 if (!FloodSearch(x , y-1, MinimumArea, FloodArray, FloodTop)) return FALSE; 01118 if (*FloodTop>=MinimumArea) return TRUE; 01119 if (!FloodSearch(x+1, y-1, MinimumArea, FloodArray, FloodTop)) return FALSE; 01120 if (*FloodTop>=MinimumArea) return TRUE; 01121 if (!FloodSearch(x-1, y , MinimumArea, FloodArray, FloodTop)) return FALSE; 01122 if (*FloodTop>=MinimumArea) return TRUE; 01123 if (!FloodSearch(x+1, y , MinimumArea, FloodArray, FloodTop)) return FALSE; 01124 if (*FloodTop>=MinimumArea) return TRUE; 01125 if (!FloodSearch(x-1, y+1, MinimumArea, FloodArray, FloodTop)) return FALSE; 01126 if (*FloodTop>=MinimumArea) return TRUE; 01127 if (!FloodSearch(x , y+1, MinimumArea, FloodArray, FloodTop)) return FALSE; 01128 if (*FloodTop>=MinimumArea) return TRUE; 01129 if (!FloodSearch(x+1, y+1, MinimumArea, FloodArray, FloodTop)) return FALSE; 01130 } 01131 return TRUE; 01132 } 01133 01134 01135 /******************************************************************************************** 01136 01137 > Octree::Octree() 01138 01139 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 01140 Created: 19/04/95 01141 Inputs: None 01142 Outputs: Constructs object 01143 Returns: Nothing 01144 Purpose: Default constructor 01145 Errors: None yet 01146 SeeAlso: - 01147 01148 ********************************************************************************************/ 01149 01150 Octree::Octree() 01151 { 01152 MaxLeaves=255; 01153 CurrentLeaves=0; 01154 CurrentIndex=0; 01155 pTopElement=NULL; 01156 for (INT32 d=0; d<=9; d++) for (INT32 c=0; c<=8; c++) ListHead[d][c]=NULL; 01157 } 01158 01159 /******************************************************************************************** 01160 01161 > Octree::~Octree() 01162 01163 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 01164 Created: 19/04/95 01165 Inputs: None 01166 Outputs: Constructs object 01167 Returns: Nothing 01168 Purpose: Default destructor for pixel op 01169 Errors: Error3 if DeInit hasn't been called. 01170 SeeAlso: - 01171 01172 ********************************************************************************************/ 01173 01174 Octree::~Octree() 01175 { 01176 if (pTopElement) 01177 { 01178 delete pTopElement; // which deletes its children. 01179 pTopElement=NULL; 01180 } 01181 } 01182 01183 /******************************************************************************************** 01184 01185 > BOOL Octree::Init(INT32 NumColours) 01186 01187 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 01188 Created: 19/04/95 01189 Inputs: None 01190 Outputs: Resets all parameters associated with the cache 01191 Returns: TRUE if succeeded, FALSE & error set if not 01192 Purpose: Resets all parameters associated with the cache 01193 Errors: Error 2 if init hasn't been called or GDraw fails 01194 Error 3 if windows and some other Oil layer are stangely mixed... 01195 Scope: Public 01196 SeeAlso: - 01197 01198 ********************************************************************************************/ 01199 01200 BOOL Octree::Init(INT32 NumColours) 01201 { 01202 if (pTopElement) 01203 { 01204 delete pTopElement; // which deletes its children. 01205 pTopElement=NULL; 01206 } 01207 MaxLeaves=NumColours; 01208 CurrentLeaves=0; 01209 CurrentIndex=0; 01210 01211 for (INT32 d=0; d<=9; d++) for (INT32 c=0; c<=8; c++) ListHead[d][c]=NULL; 01212 01213 if ((pTopElement=new OctreeElement) == NULL) return FALSE; // error already set 01214 // and it's already in a fairly well set up state 01215 01216 ListHead[0][0]=pTopElement; 01217 01218 return TRUE; 01219 } 01220 01221 01222 /******************************************************************************************** 01223 01224 > OctreeElement * Octree::GetElement(INT32 r, INT32 g, INT32 b) 01225 01226 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 01227 Created: 19/04/95 01228 Inputs: r, g, b values to octree search for 01229 Outputs: None 01230 Returns: pointer to relevant octree element 01231 Purpose: Resets all parameters associated with the cache 01232 Errors: None yet 01233 Scope: Public 01234 SeeAlso: - 01235 01236 ********************************************************************************************/ 01237 01238 OctreeElement * Octree::GetElement(INT32 r, INT32 g, INT32 b) 01239 { 01240 ERROR2IF(!pTopElement, NULL, "Octree not initialised"); 01241 OctreeElement * pEl = pTopElement; 01242 01243 // descend the tree till we reach the minimal cube containing the colour 01244 while(TRUE) 01245 { 01246 INT32 halfwidth=(1<<(8 - pEl->Depth))>>1; 01247 INT32 R=pEl->R+halfwidth; 01248 INT32 G=pEl->G+halfwidth; 01249 INT32 B=pEl->B+halfwidth; 01250 INT32 child=((r>=R)?1:0)+((g>=G)?2:0)+((b>=B)?4:0); 01251 if (!pEl->pChildren[child]) return pEl; 01252 pEl=pEl->pChildren[child]; 01253 } 01254 01255 ERROR3("How did it get here?"); 01256 return NULL; 01257 } 01258 01259 /******************************************************************************************** 01260 01261 > BOOL Octree::Insert(INT32 r, INT32 g, INT32 b) 01262 01263 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 01264 Created: 19/04/95 01265 Inputs: r, g, b values to insert 01266 Outputs: None 01267 Returns: TRUE on success, FALSE on error 01268 Purpose: Resets all parameters associated with the cache 01269 Errors: 2 & 3 01270 Scope: Public 01271 SeeAlso: - 01272 01273 ********************************************************************************************/ 01274 01275 BOOL Octree::Insert(INT32 r, INT32 g, INT32 b) 01276 { 01277 //CheckIntegrity(); 01278 01279 OctreeElement * pEl = GetElement(r, g, b); 01280 if (!pEl) return FALSE; 01281 01282 // Insert any necessary intermediates 01283 while (pEl->Depth !=8) 01284 { 01285 OctreeElement * pNewEl = new OctreeElement; 01286 if (!pNewEl) return FALSE; 01287 pNewEl->Depth=pEl->Depth+1; 01288 INT32 halfwidth=(1<<(8 - pEl->Depth))>>1; 01289 INT32 R=pEl->R+halfwidth; 01290 INT32 G=pEl->G+halfwidth; 01291 INT32 B=pEl->B+halfwidth; 01292 01293 pNewEl->R=(r>=R)?R:(pEl->R); 01294 pNewEl->G=(g>=G)?G:(pEl->G); 01295 pNewEl->B=(b>=B)?B:(pEl->B); 01296 01297 INT32 child=((r>=R)?1:0)+((g>=G)?2:0)+((b>=B)?4:0); 01298 ERROR2IF(pEl->pChildren[child], FALSE, "Blurk! Octree element already has a child"); 01299 pEl->pChildren[child]=pNewEl; 01300 pNewEl->pParent=pEl; 01301 01302 Unlink(pEl); 01303 pEl->NumChildren++; 01304 Link(pEl); 01305 01306 pEl=pNewEl; 01307 Link(pEl); 01308 01309 //CheckIntegrity(); 01310 } 01311 01312 if (!pEl->Pixels) CurrentLeaves++; 01313 pEl->Pixels++; 01314 01315 while (CurrentLeaves>MaxLeaves) 01316 { 01317 pEl=NULL; 01318 01319 // Seatch deepest in the tree first ... 01320 for (INT32 d=8; (d>=0) && !pEl; d--) 01321 { 01322 // ... for an element with no children ... 01323 OctreeElement * plEl=ListHead[d][0]; 01324 while (plEl && !pEl) 01325 { 01326 // ... which has a parent ... 01327 pEl=plEl->pParent; 01328 // ... whose children have no children themselves 01329 for (INT32 c=0; (c<8) && pEl; c++) if (pEl->pChildren[c] && pEl->pChildren[c]->NumChildren) pEl=NULL; 01330 plEl=plEl->pListNext; 01331 } 01332 } 01333 01334 if (pEl) 01335 { 01336 Unlink(pEl); 01337 if (!pEl->Pixels) CurrentLeaves++; 01338 for (INT32 c=0; c<8; c++) if (pEl->pChildren[c]) 01339 { 01340 pEl->Pixels+=pEl->pChildren[c]->Pixels; 01341 01342 Unlink (pEl->pChildren[c]); 01343 pEl->NumChildren--; 01344 ERROR3IF(pEl->pChildren[c]->NumChildren, "OK, why have I been given an octree element with children?"); 01345 delete pEl->pChildren[c]; 01346 pEl->pChildren[c]=NULL; 01347 CurrentLeaves--; 01348 } 01349 Link(pEl); 01350 //CheckIntegrity(); 01351 } else 01352 { 01353 ERROR3("Can't find a candidate for combining octree"); 01354 break; 01355 } 01356 } 01357 01358 return TRUE; 01359 } 01360 01361 /******************************************************************************************** 01362 01363 > void Octree::CheckIntegrity() 01364 01365 01366 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 01367 Created: 19/04/95 01368 Inputs: None 01369 Outputs: None 01370 Returns: None 01371 Purpose: Unlinks elt from lists 01372 Errors: 2 & 3 01373 Scope: 01374 SeeAlso: - 01375 01376 Checks the octrees integrity 01377 01378 ********************************************************************************************/ 01379 01380 void Octree::CheckIntegrity() 01381 { 01382 #ifdef _DEBUG // avoid unused variable warnings 01383 for (INT32 d=0; d<=8; d++) for (INT32 c=0; c<=8; c++) 01384 { 01385 OctreeElement *pCheck = ListHead[d][c]; 01386 OctreeElement *pChild = NULL; 01387 while (pCheck) 01388 { 01389 if (pCheck->pListPrev) ERROR3IF(pCheck->pListPrev->pListNext!=pCheck, "Bad prev ptr"); 01390 if (pCheck->pListNext) ERROR3IF(pCheck->pListNext->pListPrev!=pCheck, "Bad next ptr"); 01391 ERROR3IF((d!=0) && !pCheck->pParent, "Has no parent on non zero depth"); 01392 ERROR3IF((d==0) && (pCheck!=pTopElement), "Bad top element"); 01393 ERROR3IF(pCheck->Depth!=d,"Bad depth"); 01394 ERROR3IF(pCheck->NumChildren!=c, "Bad Num Children"); 01395 INT32 count=0; 01396 INT32 halfwidth=(1<<(8 - pCheck->Depth))>>1; 01397 for (INT32 cc=0; cc<8; cc++) if ((pChild=pCheck->pChildren[cc]/*assign*/)!=NULL) 01398 { 01399 count++; 01400 ERROR3IF(pChild->pParent != pCheck, "Bad parent link"); 01401 ERROR3IF(pChild->Depth != d+1, "Bad child depth"); 01402 INT32 R=pCheck->R + ((cc&1)?halfwidth:0); 01403 INT32 G=pCheck->G + ((cc&2)?halfwidth:0); 01404 INT32 B=pCheck->B + ((cc&4)?halfwidth:0); 01405 ERROR3IF(pChild->R != R, "Bad child R"); 01406 ERROR3IF(pChild->G != G, "Bad child G"); 01407 ERROR3IF(pChild->B != B, "Bad child B"); 01408 OctreeElement *pLChild = pChild; 01409 while (pLChild->pListPrev) pLChild=pLChild->pListPrev; 01410 ERROR3IF(pLChild!=ListHead[d+1][pLChild->NumChildren],"Child not in a list"); 01411 } 01412 ERROR3IF(c!=count, "Bad child count"); 01413 pCheck=pCheck->pListNext; 01414 } 01415 } 01416 #endif 01417 return; 01418 } 01419 01420 /******************************************************************************************** 01421 01422 > void Octree::Unlink(OctreeElement * pEl) 01423 01424 01425 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 01426 Created: 19/04/95 01427 Inputs: pEl = pointer to element to unlink 01428 Outputs: None 01429 Returns: None 01430 Purpose: Unlinks elt from lists 01431 Errors: 2 & 3 01432 Scope: 01433 SeeAlso: - 01434 01435 ********************************************************************************************/ 01436 01437 void Octree::Unlink(OctreeElement * pEl) 01438 { 01439 // Now unlink pEl from its previous chain firt by sorting out NextPtr of Prev elt 01440 if (pEl->pListPrev) 01441 { 01442 pEl->pListPrev->pListNext=pEl->pListNext; // possibly NULL 01443 } 01444 else // it was the head previously 01445 { 01446 ListHead[pEl->Depth][pEl->NumChildren]=pEl->pListNext; // possibly NULL 01447 } 01448 // then by sorting out PrevPtr of next elt 01449 if (pEl->pListNext) // if there is a next ptr 01450 { 01451 pEl->pListNext->pListPrev=pEl->pListPrev; // possibly NULL 01452 } 01453 pEl->pListNext=pEl->pListPrev=NULL; 01454 return; 01455 } 01456 01457 /******************************************************************************************** 01458 01459 > void Octree::Link(OctreeElement * pEl) 01460 01461 01462 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 01463 Created: 19/04/95 01464 Inputs: pEl = pointer to element to unlink 01465 Outputs: None 01466 Returns: None 01467 Purpose: Links elt into lists 01468 Errors: 2 & 3 01469 Scope: 01470 SeeAlso: - 01471 01472 ********************************************************************************************/ 01473 01474 void Octree::Link(OctreeElement * pEl) 01475 { 01476 // Now insert pEl on the correct child list 01477 if ((pEl->pListNext=/*assign*/ListHead[pEl->Depth][pEl->NumChildren])!=NULL) // if the list is non empty 01478 { 01479 ListHead[pEl->Depth][pEl->NumChildren]->pListPrev=pEl; // adjust the prev pointer 01480 } 01481 pEl->pListPrev=NULL; // our prev ptr set to NULL 01482 ListHead[pEl->Depth][pEl->NumChildren]=pEl; // put us at the front of the list 01483 } 01484 01485 01486 01487 /******************************************************************************************** 01488 01489 > BOOL Octree::Index(RGBQUAD * Palette, OctreeElement * pEl=NULL) 01490 01491 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 01492 Created: 19/04/95 01493 Inputs: *pEl = element to index (and its children) or NULL for top element 01494 Outputs: *Palette = palette filled in as per octree 01495 Returns: TRUE on success, FALSE on error 01496 Purpose: Resets all parameters associated with the cache 01497 Errors: 2 & 3 01498 Scope: Public 01499 SeeAlso: - 01500 01501 ********************************************************************************************/ 01502 01503 BOOL Octree::Index(RGBQUAD * Palette, OctreeElement * pEl) 01504 { 01505 CheckIntegrity(); 01506 01507 if (!pEl) 01508 { 01509 pEl=pTopElement; 01510 CurrentIndex=0; 01511 if (!pEl) return TRUE; // for we have done 01512 } 01513 01514 if (pEl->Pixels) 01515 { 01516 if (CurrentIndex>=MaxLeaves) 01517 { 01518 ERROR3("CurrentIndex>=MaxLeaves in Octree::Index"); 01519 CurrentIndex=0; 01520 } 01521 pEl->Index=CurrentIndex; 01522 Palette[CurrentIndex].rgbRed=(BYTE)(pEl->R); 01523 Palette[CurrentIndex].rgbGreen=(BYTE)(pEl->G); 01524 Palette[CurrentIndex].rgbBlue=(BYTE)(pEl->B); 01525 CurrentIndex++; 01526 } 01527 else 01528 { 01529 pEl->Index=-1; 01530 } 01531 for (INT32 c=0; c<8; c++) if (pEl->pChildren[c]) if (!Index(Palette, pEl->pChildren[c])) return FALSE; 01532 return TRUE; 01533 } 01534 01535 /******************************************************************************************** 01536 01537 > DWORD Octree::GetIndex(INT32 r, INT32 g, INT32 b) 01538 01539 Author: Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> 01540 Created: 19/04/95 01541 Inputs: r, g, b to get 01542 Outputs: None 01543 Returns: Index for this element 01544 Purpose: Resets all parameters associated with the cache 01545 Errors: 2 & 3 01546 Scope: Public 01547 SeeAlso: - 01548 01549 ********************************************************************************************/ 01550 01551 INT32 Octree::GetIndex(INT32 r, INT32 g, INT32 b) 01552 { 01553 OctreeElement * pEl=GetElement(r, g, b); 01554 if (!pEl) 01555 { 01556 ERROR3("Help! Can't find an enclosing octree element"); 01557 return 0; 01558 } 01559 if (pEl->Index<0) 01560 { 01561 ERROR3("You've given us an RGB value you didn't give us on the first pass, quoth the octree"); 01562 return 0; 01563 } 01564 return pEl->Index; 01565 }