bfxpixop.cpp

Go to the documentation of this file.
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 }

Generated on Sat Nov 10 03:48:06 2007 for Camelot by  doxygen 1.4.4