bfxalu.cpp

Go to the documentation of this file.
00001 // $Id: bfxalu.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 effect ALU
00099 
00100 /*
00101 */
00102 
00103 #include "camtypes.h"
00104 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00105 #include "bfxalu.h"
00106 #include "GDrawIntf.h"
00107 #include "gdrawcon.h"
00108 //#include "bitmap.h"              - in camtypes.h [AUTOMATICALLY REMOVED]
00109 #include "bitmpinf.h"
00110 #include "oilbitmap.h"
00111 //#include "ccobject.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 //#include "paths.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00114 //#include "accures.h"
00115 //#include "extfilts.h"
00116 //#include "resource.h" // for _R(IDS_OUT_OF_MEMORY)
00117 #include "tracectl.h"
00118 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00119 //#include "bmplist.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00120 #include "bfxpixop.h"
00121 //#include "bfxrc.h"
00122 #include "progress.h"
00123 //#include "richard2.h"
00124 
00125 // The asm file defines FASTxxxxxx if there are fast versions of the routeines available
00126 // #include "bfxasm.h"
00127 
00128 // Set this whilst GDraw persists in expecting monochrome bitmaps to be screwy
00129 //#define GAVIN_MONOCHROME_BITMAPS_BROKEN
00130 
00131 // Set this whilst Accusoft persist in making IMG_promote_8 incorrectly size their 2 colour palette
00132 #define ACCUSOFT_HAS_BROKEN_NON_FULL_PALETTES
00133 
00134 //#undef FASTMARKBITBYWORD
00135 //#undef FASTMARKWORDBYBIT
00136 //#undef FASTMARKREGIONS
00137 //#undef FASTMARKPOSITIVE
00138 //#undef FASTMARKCOLOURTHRESHOLD
00139 //#undef FASTCLEARBITBYWORD
00140 //#undef FASTSCANBIT
00141 //#undef FASTSCANTHRESHOLD
00142 //#undef FASTREMOVEDITHER
00143 
00144 #ifdef STANDALONE
00145     #undef FASTLINEARABK
00146     #undef FASTMARKBITBYWORD
00147     #undef FASTCLEARBITBYWORD
00148     #undef FASTMARKWORDBYBIT
00149     #undef FASTSCANBIT
00150     #undef FASTSCANTHRESHOLD
00151     #undef FASTSCANTHRESHOLD8
00152     #undef FASTMARKREGIONS
00153     #undef FASTMARKLARGESTAREA
00154     #undef FASTBUILDERRORREGIONLIST
00155     #undef FASTMARKTHRESHOLD
00156     #undef FASTMARKPOSITIVE
00157     #undef FASTMARKCOLOURTHRESHOLD
00158     #undef FASTREMOVEDITHER
00159 #endif
00160 
00161 // This is not compulsory, but you may as well put it in so that the correct version
00162 // of your file can be registered in the .exe
00163 DECLARE_SOURCE("$Revision: 1282 $");
00164 
00165 // An implement to match the Declare in the .h file.
00166 // If you have many classes, it is recommended to place them all together, here at the start of the file
00167 CC_IMPLEMENT_DYNCREATE(BfxALU, CCObject)
00168 
00169 #ifndef EXCLUDE_FROM_RALPH
00170 CC_IMPLEMENT_DYNCREATE(BfxALULUT, CCObject)
00171 CC_IMPLEMENT_DYNCREATE(BfxErrorRegionList, CCObject);
00172 
00173 // This will get Camelot to display the filename and linenumber of any memory allocations
00174 // that are not released at program exit
00175 #define new CAM_DEBUG_NEW
00176 
00177 #define ALUC_PART       0
00178 #define ALUC_PARTMUL    1
00179 #define ALUC_PARTREVMUL 2
00180 #define ALUC_ADD        6
00181 #define ALUC_SUB        7
00182 
00183 // Here's a macro to fix GDraw monochrome bitmaps
00184 #ifndef GAVIN_MONOCHROME_BITMAPS_BROKEN
00185 #define FixMono(i,s) { /* empty macro*/ }
00186 #else
00187 #define FixMono(i,s) { BYTE __lut[256]; for(UINT32 __l=0;__l<256;__l++) __lut[__l]= (BYTE)(\
00188 ((__l & 0x80)>>7) + ((__l & 0x40)>>5) + ((__l & 0x20)>>3) + ((__l & 0x10)>>1) + \
00189 ((__l & 0x08)<<1) + ((__l & 0x04)<<3) + ((__l & 0x02)<<5) + ((__l & 0x01)<<7) ); \
00190 for (UINT32 __b=0; __b<((UINT32)s);__b++) ((BYTE *)(void *)i)[__b]=__lut[((BYTE *)(void *)i)[__b]];}
00191 #endif
00192 
00193 // Accusoft have a bug in their bitmap resize with interpolation which puts a grey line
00194 // down the left hand side of the bitmap. This enables a complete bodge to try and fix it
00195 #define BODGE_ACCUSOFT_RESIZE
00196 
00197 /********************************************************************************************
00198 
00199 >   BOOL BfxALULUT::LinearABK(double PropA, double PropB, double Offset)
00200                     
00201     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
00202     Created:    02/11/94
00203     Inputs:     None
00204     Outputs:    Initialises LUT
00205     Returns:    TRUE if succeeded, FALSE & error set if not
00206     Purpose:    Initialises LUT as below
00207     Errors:     None at present
00208     SeeAlso:    -
00209 
00210 This call initialises the LUT so
00211     out = A*PropA + B*PropB + Offset
00212 Note everything in the above formula works 0..1 whereas the LUT works 0..255
00213 
00214 ********************************************************************************************/
00215 
00216 #define LUTBYTE(x,y) Data[x+(y<<8)]
00217 
00218 BOOL BfxALULUT::LinearABK(double PropA, double PropB, double Offset)
00219 {
00220     INT32 pa=(INT32)(PropA*(1<<15));
00221     INT32 pb=(INT32)(PropB*(1<<15));
00222     INT32 po=(INT32)(Offset*((1<<15)*255)+/* for rounding */(1<<14));
00223 
00224     // Please note how we're *NOT* using doubles in the loop as that's
00225     // sooooo sloooooow on 486SX. We use 17.15 arithmetic throughout
00226 
00227 #ifndef FASTLINEARABK
00228     INT32 a;
00229     INT32 b;
00230     INT32 r;
00231     for (a=0; a<256; a++) for (b=0; b<256; b++)
00232     {
00233         r=(a*pa+b*pb+po)>>15; /* we did the rounding in the offset calc */
00234         LUTBYTE(a,b)=(r<0)?0:((r>255)?255:(BYTE)(INT32)(r));
00235     }
00236 #else
00237     FastLinearABK(Data, pa, pb, po, 256);
00238 #if 0
00239     INT32 a;
00240     INT32 b;
00241     INT32 r;
00242     for (a=0; a<256; a++) for (b=0; b<256; b++)
00243     {
00244         r=(a*pa+b*pb+po)>>15; /* we did the rounding in the offset calc */
00245         if (LUTBYTE(a,b)!=((r<0)?0:((r>255)?255:(BYTE)(INT32)(r))))
00246         {
00247             TRACEUSER( "Alex", _T("Byte %x,%x was %x should be %x\n"),a,b,
00248                 LUTBYTE(a,b),( (r<0)?0:((r>255)?255:(BYTE)(INT32)(r)) ) );
00249         }
00250     }
00251 #endif
00252 #endif
00253 
00254 
00255     return(TRUE);
00256 }
00257 
00258 /********************************************************************************************
00259 
00260 >   BYTE BfxALULUT::BYTE GetLUT(UINT32 A, UINT32 B)
00261                     
00262     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
00263     Created:    02/11/94
00264     Inputs:     A & B LUT address
00265     Outputs:    None
00266     Returns:    Byte in LUT
00267     Purpose:    Gets a value out a LUT
00268     Errors:     None at present
00269     SeeAlso:    -
00270 
00271 The addresses must be 0..255
00272 
00273 ********************************************************************************************/
00274 
00275 BYTE BfxALULUT::GetLUT(UINT32 A, UINT32 B)
00276 {
00277     return LUTBYTE(A,B);
00278 }
00279 
00280 #endif // EXCLUDE_FROM_RALPH
00281 
00282 /********************************************************************************************
00283 
00284 >   BfxALU::BfxALU()
00285                     
00286     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
00287     Created:    12/10/94
00288     Inputs:     None
00289     Outputs:    Constructs object
00290     Returns:    Nothing
00291     Purpose:    Default constructor for ALU
00292     Errors:     None yet
00293     SeeAlso:    -
00294 
00295 This constructs the ALU - most of the work is done in the Init function
00296 
00297 ********************************************************************************************/
00298 
00299 BfxALU::BfxALU()
00300 {
00301 #ifndef EXCLUDE_FROM_RALPH
00302     GC = NULL;
00303     ResetAccusoftDibsToRuns = FALSE;
00304 #endif
00305 }
00306 
00307 /********************************************************************************************
00308 
00309 >   BfxALU::~BfxALU()
00310                     
00311     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
00312     Created:    12/10/94
00313     Inputs:     None
00314     Outputs:    Constructs object
00315     Returns:    Nothing
00316     Purpose:    Default constructor for ALU
00317     Errors:     Error3 if DeInit hasn't been called.
00318     SeeAlso:    -
00319 
00320 This destructs the ALU - most of the work should be done in the Init function
00321 
00322 ********************************************************************************************/
00323 
00324 BfxALU::~BfxALU()
00325 {
00326 #ifndef EXCLUDE_FROM_RALPH
00327     // has to be a level 3 check - we can't return an error code
00328     ERROR3IF( (GC!=NULL), "Someone hasn't called the BfxALU deinit function!");
00329 #endif
00330 }
00331 
00332 #ifndef EXCLUDE_FROM_RALPH
00333 
00334 /********************************************************************************************
00335 
00336 >   BOOL BfxALU::Init()
00337                     
00338     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
00339     Created:    27/10/94
00340     Inputs:     None
00341     Outputs:    Initialises subsystem
00342     Returns:    TRUE if succeeded, FALSE & error set if not
00343     Purpose:    Initialises the bitmap effect subsystem
00344     Errors:     Level 2 if out of memory (this isn't a resource problem as we can't start
00345                 camelot if this fails...)
00346     SeeAlso:    -
00347 
00348 This call's primary purposes is to initialise the BfxALU, claiming a GDraw context etc.
00349 
00350 ********************************************************************************************/
00351 
00352 BOOL BfxALU::Init()
00353 {
00354     GC = new GDrawAsm;  
00355     ERROR2IF((GC==NULL),FALSE,"Couldn't get a GDrawContext for the BfxALU");
00356     if (!GC->Init())
00357     {
00358         GC=NULL;
00359         ERROR2(FALSE,"Couldn't initialise GDrawContext for the BfxALU");
00360     }
00361     
00362     identity.AX=identity.BY=1<<(FX+16);identity.CX=identity.CY=identity.AY=identity.BX=0;
00363     GC->SetupBitmap(256,256,32,NULL,TRUE);
00364     GC->SetMatrix(&identity);
00365     GC->SetAntialiasFlag(FALSE);
00366     GC->SelectPalette(0);
00367     GC->SetHalftoneOrigin(0,0);
00368 
00369     return TRUE;
00370 }
00371 
00372 
00373 void BfxALU::TestGD()
00374 {
00375     identity.AX=identity.BY=1<<(FX+16);identity.CX=identity.CY=identity.AY=identity.BX=0;
00376     GC->SetupBitmap(256,256,32,NULL,TRUE);
00377     GC->SetMatrix(&identity);
00378     GC->SetAntialiasFlag(FALSE); // should cause a context swap or 2
00379     GC->SelectPalette(0);
00380     GC->SetHalftoneOrigin(0,0);
00381 }   
00382 
00383 /********************************************************************************************
00384 
00385 >   BOOL BfxALU::DeInit()
00386                     
00387     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
00388     Created:    27/10/94
00389     Inputs:     None
00390     Outputs:    DeInitialises subsystem
00391     Returns:    TRUE if succeeded, FALSE & error set if not
00392     Purpose:    Initialises the bitmap effect subsystem
00393     Errors:     None from this one as yet
00394     SeeAlso:    -
00395 
00396 This call's primary purposes is to deinitialise the BfxALU, releasing a GDraw context etc.
00397 
00398 ********************************************************************************************/
00399 
00400 BOOL BfxALU::DeInit()
00401 {
00402     if (GC)
00403     {
00404         delete GC; 
00405         GC=NULL;
00406     }
00407     return TRUE;
00408 }
00409 
00410 /********************************************************************************************
00411 
00412 >   KernelBitmap * BfxALU::NewBitmap(KernelBitmap *pBitmap,INT32 XAdjust=0,INT32 YAdjust=0,
00413                                      INT32 NewDepth=0, String_256 * pName =NULL, UINT32 ResID =0)
00414 
00415                     
00416     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
00417     Created:    27/10/94
00418     Inputs:     pBitmap = pointer to the bitmap whose size to copy or NULL
00419                 XAdjust = Amount to alter X size by
00420                 YAdjust = Amount to alter Y size by
00421                 Depth   = bpp  of new bitmap or 0 for as pBitmap
00422     Outputs:    Claims a new bitmap
00423     Returns:    Pointer to bitmap, or NULL on failure
00424     Purpose:    General purpose call to claim a new kernel bitmap.
00425     Errors:     Error 2 if init hasn't been called or GDraw fails
00426                 Error 3 if windows and some other Oil layer are stangely mixed...
00427     Scope:      Public
00428     SeeAlso:    -
00429 
00430 Note the new bitmap is uninitialized. I'll say that again. It's uninitialized. IE it contains
00431 potentially random bytes.
00432 
00433 Passing a null bitmap pointer is like passing a pointer to a 32bpp 0x0 bitmap, so
00434 kb=NewBitmap(NULL, 128, 128) creates a 128 pixelx128 pixel bitmap.
00435 
00436 kb2=NewBitmap(kb1, -1, -1, 8) creates a bitmap kb2 like kb1 but 8bpp and one pixel smaller.
00437 And so on.
00438 
00439 If a null pointer is returned, an error is set.
00440 
00441 ********************************************************************************************/
00442 
00443 KernelBitmap * BfxALU::NewBitmap(KernelBitmap *pBitmap,INT32 XAdjust,INT32 YAdjust,INT32 NewDepth,
00444     String_256 * pName /*=NULL*/, UINT32 ResID /*=0*/)
00445 {
00446     INT32 Width;
00447     INT32 Height;
00448     INT32 Depth;
00449     INT32 DPI;
00450     BOOL IsTemp=TRUE;
00451 
00452     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
00453     if (!pBitmap)
00454     {
00455         Width=0;
00456         Height=0;
00457         Depth=32;
00458         DPI=96; 
00459         IsTemp=FALSE;
00460     }
00461     else
00462     {
00463         ERROR2IF((pBitmap->ActualBitmap==NULL),FALSE,"BfxALU can't find OIL bitmap");
00464         ERROR3IF( (!(pBitmap->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
00465 
00466         BitmapInfo BMInfo;
00467         pBitmap->ActualBitmap->GetInfo(&BMInfo);
00468         Depth=BMInfo.PixelDepth;
00469         Width=BMInfo.PixelWidth;
00470         Height=BMInfo.PixelHeight;          
00471         DPI=96; /*BMInfo.DPI; not there grrrr */
00472     }
00473 
00474     Width+=XAdjust;
00475     Height+=YAdjust;
00476     if (NewDepth) Depth=NewDepth;
00477 
00478 //  Don't do the following as the constructor doesn't error properly
00479 //  Oh dear, we have to do it because OILBitmap::Create is protected. Grrr
00480     KernelBitmap * pNewBitmap = new KernelBitmap(Width,Height,Depth,DPI,IsTemp); // Note 'new' sets error for this class
00481     if (!pNewBitmap) return FALSE;
00482     if (!pNewBitmap->ActualBitmap) // the alloc failed and we must, unfortunately, assume the error is set right
00483     {
00484         delete pNewBitmap; // apparently this will work though I don't like it
00485         return FALSE;
00486     }
00487 
00488 //  OILBitmap * pNewOILBitmap = OILBitmap::Create( Width, Height, Depth, DPI );
00489 //  if (!pNewOILBitmap) return FALSE; // error already set
00490 //  KernelBitmap * pNewBitmap = new KernelBitmap(pNewOILBitmap); // Note 'new' sets error for this class
00491 //  if (!pNewBitmap)
00492 //  {
00493 //      delete pNewOILBitmap;
00494 //      return FALSE;   
00495 //  }
00496 
00497     ERROR2IF((pNewBitmap->ActualBitmap==NULL) || (((CWxBitmap *)(pNewBitmap->ActualBitmap))->BMInfo==NULL) || (((CWxBitmap *)(pNewBitmap->ActualBitmap))->BMBytes==NULL),
00498               FALSE,"BfxALU can't find OIL bitmap of the new bitmap");
00499     
00500     if (pBitmap)
00501     {
00502         BITMAPINFOHEADER * pABMI=&(((CWxBitmap *)(pBitmap->ActualBitmap))->BMInfo->bmiHeader);
00503         BITMAPINFOHEADER * pBBMI=&(((CWxBitmap *)(pNewBitmap->ActualBitmap))->BMInfo->bmiHeader);
00504         // Copy the DPI accross
00505         pBBMI->biXPelsPerMeter = pABMI->biXPelsPerMeter;
00506         pBBMI->biYPelsPerMeter = pABMI->biYPelsPerMeter;
00507         
00508         if (Depth<=8) // If the bitmaps are the same depth we make a new palette
00509         {
00510             if (pBBMI->biClrUsed==pABMI->biClrUsed && pBBMI->biBitCount==pABMI->biBitCount)
00511             {
00512                 // copy in palette if appropriate
00513                 memcpy(pBBMI+1 /*ptr arith*/, pABMI+1 /*ptr arith*/, pBBMI->biClrUsed*sizeof(DWORD));
00514             }
00515         }
00516     }
00517 
00518     String_256 BitmapName;
00519     if (pName)
00520         BitmapName=*pName;
00521     else
00522     {
00523         if (pBitmap)
00524             BitmapName=pBitmap->ActualBitmap->GetName();
00525         else
00526             BitmapName=pNewBitmap->ActualBitmap->GetName();
00527     }
00528 
00529     if ((ResID) && (BitmapName.Length()<128))
00530     {
00531         String_256 Mask(_R(IDS_BFXALU_MASK_START)); // " (*"
00532         String_256 Mask2(_R(IDS_BFXALU_MASK_END)); // ")"
00533         TCHAR Fuzz = '*';
00534         String_256 Processed(_R(IDS_BFX_PROCESSED));
00535         String_256 Res(ResID);
00536         INT32 pos = BitmapName.Sub(Mask, 0, Fuzz);
00537         if (pos>=0) if (BitmapName.Sub(Mask2, pos, Fuzz)<0) pos=-1;
00538         if (pos>=0) BitmapName.Left(&BitmapName, pos);
00539         BitmapName += String_8(_R(IDS_BFXALU_PROCESSED_START)); // " (";
00540         if (pos>=0) BitmapName+=Processed;
00541         BitmapName+=Res;
00542         BitmapName += String_8(_R(IDS_BFXALU_PROCESSED_END));   // ")";
00543     }
00544 
00545     GetApplication()->GetGlobalBitmapList()->MakeNameUnique(&BitmapName);
00546 
00547     pNewBitmap->ActualBitmap->SetName(BitmapName);
00548 
00549     return pNewBitmap;
00550 
00551 }               
00552 
00553 
00554 /********************************************************************************************
00555 
00556 >   BOOL BfxALU::SetA(KernelBitmap *pBitmap=NULL);
00557                     
00558     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
00559     Created:    27/10/94
00560     Inputs:     pBitmap = pointer to the bitmap to use as an accumulator
00561     Outputs:    Sets up GDraw to use the kernel bitmap as an accumulator
00562     Returns:    TRUE if succeeded, FALSE & error set if not
00563     Purpose:    GDraw needs a bitmap to plot to & from, this is the accumulator
00564     Errors:     Error 2 if init hasn't been called or GDraw fails
00565                 Error 3 if windows and some other Oil layer are stangely mixed...
00566     Scope:      Public
00567     SeeAlso:    -
00568 
00569 This call sets up the accumulator register of the ALU to be the kernel bitmap passed in. All
00570 adds, subtracts etc. are done on this register.
00571 
00572 pBitmap may be NULL to stop using this bitmap
00573 
00574 ********************************************************************************************/
00575 
00576 BOOL BfxALU::SetA(KernelBitmap * pBitmap)
00577 {
00578     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
00579     if (!pBitmap)
00580     {
00581         GC->SetupBitmap(256,256,32,NULL,TRUE);
00582         GC->SetMatrix(&identity);
00583         A=NULL;
00584         return(TRUE);   
00585     }
00586     else
00587     {
00588         ERROR2IF((pBitmap->ActualBitmap==NULL),FALSE,"BfxALU can't find OIL bitmap");
00589         ERROR3IF( (!(pBitmap->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
00590 //      ERROR2IF((((CWxBitmap *)(pBitmap->ActualBitmap))->BMInfo->bmiHeader.biBitCount !=32), FALSE,
00591 //               "Bad BfxALU accumulator");
00592         BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(pBitmap->ActualBitmap))->BMInfo->bmiHeader);
00593         ERROR2IF( (!GC->SetupBitmap(pBMI->biWidth,pBMI->biHeight,pBMI->biBitCount,
00594                                     ((CWxBitmap *)(pBitmap->ActualBitmap))->BMBytes)),
00595                    FALSE,"GDraw didn't like BfxALU accumulator");
00596         GC->SetMatrix(&identity);
00597         A=pBitmap;
00598         return(TRUE);
00599     }
00600 }
00601 
00602 /********************************************************************************************
00603 
00604 >   BOOL BfxALU::SetB(KernelBitmap *pBitmap=NULL,INT32 XOffset=0,INT32 YOffset=0,
00605                       const BYTE * pTable=NULL,DWORD Style=0)
00606                     
00607     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
00608     Created:    27/10/94
00609     Inputs:     pBitmap = pointer to the bitmap to use as B reg
00610                 X/YOffset = offsets in pixels
00611                 pTable = a lookup table to use on the RGB channels
00612                 Style = Tiling style
00613     Outputs:    Sets up GDraw to use the kernel bitmap as B reg
00614     Returns:    TRUE if succeeded, FALSE & error set if not
00615     Purpose:    GDraw needs a bitmap to plot to & from, this is the accumulator
00616     Errors:     Error 2 if init hasn't been called or GDraw fails
00617                 Error 3 if windows and some other Oil layer are stangely mixed...
00618     Scope:      Public
00619     SeeAlso:    -
00620 
00621 This call sets up the B register of the ALU to be the kernel bitmap passed in.
00622 
00623 pBitmap may be null to stop using this bitmap
00624 
00625 ********************************************************************************************/
00626 
00627 BOOL BfxALU::SetB(KernelBitmap * pBitmap,INT32 XOffset,INT32 YOffset,const BYTE * pTable,DWORD Style)
00628 {
00629     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
00630     if (!pBitmap)
00631     {
00632         B=NULL;
00633         BColour=0;
00634         return(TRUE);   
00635     }
00636     else
00637     {
00638         ERROR2IF((pBitmap->ActualBitmap==NULL),FALSE,"BfxALU can't find OIL bitmap");
00639         ERROR3IF( (!(pBitmap->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
00640         BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(pBitmap->ActualBitmap))->BMInfo->bmiHeader);
00641         //ERROR2IF((pBMI->biBitCount !=32), FALSE,"Bad BfxALU B reg");
00642         BPoints[0].x = XOffset;                         BPoints[0].y = YOffset;
00643         BPoints[1].x = XOffset+(INT32)(pBMI->biWidth);  BPoints[1].y = YOffset;
00644         BPoints[2].x = XOffset;                         BPoints[2].y = YOffset+(INT32)(pBMI->biHeight);
00645         B=pBitmap;
00646         BpTable=pTable;
00647         BStyle=Style;
00648         return(TRUE); 
00649     }
00650 }
00651 
00652 /********************************************************************************************
00653 
00654 >   BOOL BfxALU::SetB(DWORD Colour)
00655                     
00656     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
00657     Created:    27/10/94
00658     Inputs:     Colour is the colour word we're using
00659     Outputs:    Sets up GDraw to use the kernel bitmap as B reg
00660     Returns:    TRUE if succeeded, FALSE & error set if not
00661     Purpose:    GDraw needs a bitmap to plot to & from, this is the accumulator
00662     Errors:     Error 2 if init hasn't been called or GDraw fails
00663                 Error 3 if windows and some other Oil layer are stangely mixed...
00664     Scope:      Public
00665     SeeAlso:    -
00666 
00667 This call sets up the B register of the ALU to be the kernel bitmap passed in.
00668 
00669 pBitmap may be null to stop using this bitmap
00670 
00671 ********************************************************************************************/
00672 
00673 BOOL BfxALU::SetB(DWORD Colour)
00674 {
00675     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
00676     B=NULL;
00677     BColour=Colour;
00678     return TRUE;
00679 }
00680 
00681 /********************************************************************************************
00682 
00683 >   BOOL BfxALU::SetT(KernelBitmap *pBitmap=NULL,INT32 XOffset=0,INT32 YOffset=0,
00684                       const BYTE * pTable=NULL,DWORD Style=0)
00685                     
00686     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
00687     Created:    27/10/94
00688     Inputs:     pBitmap = pointer to the bitmap to use as T reg
00689                 X/YOffset = offsets in pixels
00690                 pTable = a lookup table to use on the RGB channels
00691                 Style = Tiling style
00692     Outputs:    Sets up GDraw to use the kernel bitmap as T reg
00693     Returns:    TRUE if succeeded, FALSE & error set if not
00694     Purpose:    GDraw needs a bitmap to plot to & from, this is the accumulator
00695     Errors:     Error 2 if init hasn't been called or GDraw fails
00696                 Error 3 if windows and some other Oil layer are stangely mixed...
00697     Scope:      Public
00698     SeeAlso:    -
00699 
00700 This call sets up the T register of the ALU to be the kernel bitmap passed in.
00701 
00702 pBitmap may be null to stop using this bitmap
00703 
00704 ********************************************************************************************/
00705 
00706 BOOL BfxALU::SetT(KernelBitmap * pBitmap,INT32 XOffset,INT32 YOffset,const BYTE * pTable,DWORD Style)
00707 {
00708     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
00709     if (!pBitmap)
00710     {
00711         T=NULL;
00712         TValue=0;
00713         return(TRUE);   
00714     }
00715     else
00716     {
00717         ERROR2IF((pBitmap->ActualBitmap==NULL),FALSE,"BfxALU can't find OIL bitmap");
00718         ERROR3IF( (!(pBitmap->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
00719         BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(pBitmap->ActualBitmap))->BMInfo->bmiHeader);
00720 // Some operations now allow 32 bit 'T' regs though they aren't used for transparency
00721 //      ERROR2IF((pBMI->biBitCount !=8), FALSE,"Bad BfxALU T reg");
00722         TPoints[0].x = XOffset;                         TPoints[0].y = YOffset;
00723         TPoints[1].x = XOffset+(INT32)(pBMI->biWidth);  TPoints[1].y = YOffset;
00724         TPoints[2].x = XOffset;                         TPoints[2].y = YOffset+(INT32)(pBMI->biHeight);
00725         T=pBitmap;
00726         TpTable=pTable;
00727         TStyle=Style;
00728         return(TRUE);
00729     }
00730 }
00731 
00732 /********************************************************************************************
00733 
00734 >   BOOL BfxALU::SetT(DWORD Value)
00735                     
00736     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
00737     Created:    27/10/94
00738     Inputs:     Value is the value we're passing in
00739     Outputs:    Sets up GDraw to use the kernel bitmap as T reg
00740     Returns:    TRUE if succeeded, FALSE & error set if not
00741     Purpose:    GDraw needs a bitmap to plot to & from, this is the accumulator
00742     Errors:     Error 2 if init hasn't been called or GDraw fails
00743                 Error 3 if windows and some other Oil layer are stangely mixed...
00744     Scope:      Public
00745     SeeAlso:    -
00746 
00747 This call sets up the T register of the ALU to be the kernel bitmap passed in.
00748 
00749 pBitmap may be null to stop using this bitmap
00750 
00751 ********************************************************************************************/
00752 
00753 BOOL BfxALU::SetT(DWORD Value)
00754 {
00755     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
00756     T = NULL;
00757     TValue = Value;
00758     return TRUE;
00759 }
00760 
00761 /********************************************************************************************
00762 
00763 >   BOOL BfxALU::DoRect()
00764                     
00765     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
00766     Created:    27/10/94
00767     Inputs:     None 
00768     Outputs:    Accumulator altered
00769     Returns:    TRUE if succeeded, FALSE & error set if not
00770     Purpose:    Calls GDraw to perform the desired ALU operation
00771     Errors:     Error 2 if init hasn't been called or GDraw fails
00772                 Error 3 if windows and some other Oil layer are stangely mixed...
00773     Scope:      Protected
00774     SeeAlso:    -
00775 
00776 ********************************************************************************************/
00777 
00778 BOOL BfxALU::DoRect()
00779 {
00780     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
00781     ERROR2IF( ((!A) || (A->ActualBitmap==NULL)),FALSE,"BfxALU can't find OIL bitmap");
00782     ERROR3IF( (!(A->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
00783     BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
00784     RECT Rect={/*L*/0,/*T*/pBMI->biHeight,/*R*/pBMI->biWidth,/*B*/0};
00785     ERROR2IF((!GC->FillRectangle(&Rect)),FALSE,"BfxALU GDraw_FillRectangle failed");
00786 
00787 #if 0   
00788 GC->SetColour((COLORREF) 0x0000FF00);   
00789 GC->SetTransparency((COLORREF) 0x0000FF00,(enum TransparencyEnum) 0);   
00790 RECT Rect2={/*L*/0+40,/*T*/pBMI->biHeight-40,/*R*/pBMI->biWidth-40,/*B*/0+40};
00791 ERROR2IF((!GC->FillRectangle(&Rect2)),FALSE,"BfxALU GDraw_FillRectangle failed");
00792 #endif  
00793     
00794     
00795     return(TRUE);
00796 }
00797 
00798 /********************************************************************************************
00799 
00800 >   BOOL BfxALU::ZeroA(DWORD FillValue = 0)
00801                     
00802     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
00803     Created:    27/10/94
00804     Inputs:     FillValue - Value to fill with 
00805     Outputs:    Accumulator altered
00806     Returns:    TRUE if succeeded, FALSE & error set if not
00807     Purpose:    Zeros the accumulator
00808     Errors:     Error 2 if init hasn't been called or GDraw fails
00809                 Error 3 if windows and some other Oil layer are stangely mixed...
00810     Scope:      Protected
00811     SeeAlso:    -
00812 
00813 ********************************************************************************************/
00814 
00815 BOOL BfxALU::ZeroA(DWORD FillValue)
00816 {
00817     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
00818     ERROR2IF( ((!A) || (A->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
00819     ERROR3IF( (!(A->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
00820     BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
00821     
00822     memset(((CWxBitmap *)(A->ActualBitmap))->BMBytes, FillValue ,pBMI->biSizeImage);
00823 #if 0
00824     RECT Rect={/*L*/0,/*T*/pBMI->biHeight,/*R*/pBMI->biWidth,/*B*/0};
00825     GC->SetColour((COLORREF) 0x00000000);   
00826     GC->SetTransparency((COLORREF) 0x00000000,(enum TransparencyEnum) 0);   
00827     ERROR2IF((!GC->FillRectangle(&Rect)),FALSE,"BfxALU GDraw_FillRectangle failed");
00828 #endif  
00829     return(TRUE);
00830 }
00831 
00832 /********************************************************************************************
00833 
00834 >   BOOL BfxALU::UseBT(DWORD TransparencyStyle=0)
00835                     
00836     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
00837     Created:    27/10/94
00838     Inputs:     TransparencyStyle = the transparency method to use
00839     Outputs:    Performs an ALU operation using B & T with a given transparency type
00840     Returns:    TRUE if succeeded, FALSE & error set if not
00841     Purpose:    This routine sets up GDraw for A & B, and calls DoRect()
00842     Errors:     Error 2 if init hasn't been called or GDraw fails
00843                 Error 3 if windows and some other Oil layer are stangely mixed...
00844     Scope:      Protected
00845     SeeAlso:    -
00846 
00847 ********************************************************************************************/
00848 
00849 BOOL BfxALU::UseBT(DWORD TransparencyStyle)
00850 {
00851     DWORD Style;
00852     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
00853     
00854     if (T)
00855         Style = TransparencyStyle+7;
00856     else
00857         Style = (TransparencyStyle+4)+(TValue<<8);
00858 
00859     if ((!B) && (!T)) // Flat B, Flat T
00860     {
00861         ERROR2IF((!GC->SetTransparency(BColour | TValue,(enum TransparencyEnum) Style)),FALSE,"Bad BfxALU BT reg");
00862     }
00863     
00864     if ((B) && (!T)) // Bitmap B, Flat T
00865     {
00866         ERROR2IF((B->ActualBitmap==NULL),FALSE,"BfxALU can't find OIL bitmap");
00867         ERROR3IF( (!(B->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
00868         BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader);
00869         //ERROR2IF((pBMI->biBitCount !=32), FALSE,"Bad BfxALU B reg");
00870         ERROR2IF( (!GC->SetBitmapFill(pBMI,(((CWxBitmap *)(B->ActualBitmap))->BMBytes),
00871                                     BStyle | (Style<<8),
00872                                     BPoints,
00873                                     0,
00874                                     ((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiColors,
00875                                     (unsigned char *) BpTable,
00876                                     (unsigned char *) BpTable,
00877                                     (unsigned char *) BpTable,
00878                                     NULL
00879                                     )),
00880                    FALSE,"GDraw didn't like BfxALU B reg");
00881 
00882     }
00883     if ((!B) && (T)) // Ftat B, Bitmap T
00884     {
00885 
00886         ERROR2IF((!GC->SetTransparency(BColour,(enum TransparencyEnum) Style)),FALSE,"Bad BfxALU BT reg");
00887 
00888         ERROR2IF((T->ActualBitmap==NULL),FALSE,"BfxALU can't find OIL bitmap");
00889         ERROR3IF( (!(T->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
00890         BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(T->ActualBitmap))->BMInfo->bmiHeader);
00891         ERROR2IF((pBMI->biBitCount !=8), FALSE,"Bad BfxALU T reg");
00892         ERROR2IF( (!GC->SetTransparentBitmapFill(pBMI,(((CWxBitmap *)(T->ActualBitmap))->BMBytes),
00893                                     TStyle | (Style<<8),
00894                                     TPoints,
00895                                     0
00896                                     )),
00897                    FALSE,"GDraw didn't like BfxALU T reg");
00898     }
00899 
00900     if ((B) && (T)) // Bitmap B, Bitmap T
00901     {
00902         ERROR2IF((B->ActualBitmap==NULL),FALSE,"BfxALU can't find OIL bitmap");
00903         ERROR3IF( (!(B->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
00904         BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader);
00905         //ERROR2IF((pBMI->biBitCount !=32), FALSE,"Bad BfxALU B reg");
00906         ERROR2IF( (!GC->SetBitmapFill(pBMI,(((CWxBitmap *)(B->ActualBitmap))->BMBytes),
00907                                     BStyle | (Style<<8),
00908                                     BPoints,
00909                                     0,
00910                                     ((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiColors,
00911                                     (unsigned char *) BpTable,
00912                                     (unsigned char *) BpTable,
00913                                     (unsigned char *) BpTable,
00914                                     NULL
00915                                     )),
00916                    FALSE,"GDraw didn't like BfxALU B reg");
00917 
00918         ERROR2IF((T->ActualBitmap==NULL),FALSE,"BfxALU can't find OIL bitmap");
00919         ERROR3IF( (!(T->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
00920         pBMI=&(((CWxBitmap *)(T->ActualBitmap))->BMInfo->bmiHeader);
00921         ERROR2IF((pBMI->biBitCount !=8), FALSE,"Bad BfxALU T reg");
00922         ERROR2IF( (!GC->SetTransparentBitmapFill(pBMI,(((CWxBitmap *)(T->ActualBitmap))->BMBytes),
00923                                     TStyle | (Style<<8),
00924                                     TPoints,
00925                                     0
00926                                     )),
00927                    FALSE,"GDraw didn't like BfxALU T reg");
00928     }
00929 
00930 
00931     return DoRect();
00932 }
00933 
00934 /********************************************************************************************
00935 
00936 >   BOOL BfxALU::UseBK(DWORD TransparencyStyle,DWORD Value)
00937                     
00938     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
00939     Created:    27/10/94
00940     Inputs:     TransparencyStyle = the transparency method to use
00941                 Value = Value of T
00942     Outputs:    Performs an ALU operation using B & Value with a given transparency type
00943     Returns:    TRUE if succeeded, FALSE & error set if not
00944     Purpose:    This routine sets up GDraw for A & B, and calls DoRect()
00945     Errors:     Error 2 if init hasn't been called or GDraw fails
00946                 Error 3 if windows and some other Oil layer are stangely mixed...
00947     Scope:      Protected
00948     SeeAlso:    -
00949 
00950 ********************************************************************************************/
00951 
00952 BOOL BfxALU::UseBK(DWORD TransparencyStyle,DWORD Value)
00953 {
00954     DWORD Style;
00955     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
00956     
00957     Style = (TransparencyStyle+4)+(Value<<8);
00958 
00959     if (!B)
00960     {
00961         ERROR2IF((!GC->SetTransparency(BColour | TValue,(enum TransparencyEnum) Style)),FALSE,"Bad BfxALU BT reg");
00962     }
00963     else
00964     {
00965         ERROR2IF((B->ActualBitmap==NULL),FALSE,"BfxALU can't find OIL bitmap");
00966         ERROR3IF( (!(B->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
00967         BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader);
00968         //ERROR2IF((pBMI->biBitCount !=32), FALSE,"Bad BfxALU B reg");
00969         ERROR2IF( (!GC->SetBitmapFill(pBMI,(((CWxBitmap *)(B->ActualBitmap))->BMBytes),
00970                                     BStyle | (Style<<8),
00971                                     BPoints,
00972                                     0,
00973                                     ((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiColors,
00974                                     (unsigned char *) BpTable,
00975                                     (unsigned char *) BpTable,
00976                                     (unsigned char *) BpTable,
00977                                     NULL
00978                                     )),
00979                    FALSE,"GDraw didn't like BfxALU B reg");
00980 
00981     }
00982     
00983     return DoRect();
00984 }
00985 
00986 /********************************************************************************************
00987 
00988 >   BOOL BfxALU::PlotB()
00989                     
00990     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
00991     Created:    27/10/94
00992     Inputs:     None
00993     Outputs:    Performs an ALU operation A<-B
00994     Returns:    TRUE if succeeded, FALSE & error set if not
00995     Purpose:    This routine sets up GDraw for A & B, and calls DoRect()
00996     Errors:     Error 2 if init hasn't been called or GDraw fails
00997                 Error 3 if windows and some other Oil layer are stangely mixed...
00998     Scope:      Public
00999     SeeAlso:    -
01000 
01001 ********************************************************************************************/
01002 
01003 BOOL BfxALU::PlotB()
01004 {
01005     DWORD Style=0;
01006     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
01007 
01008     if (!B)
01009     {
01010         ERROR2IF((!GC->SetTransparency(BColour,(enum TransparencyEnum) Style)),FALSE,"Bad BfxALU B reg");
01011     }
01012     else
01013     {
01014         ERROR2IF((B->ActualBitmap==NULL),FALSE,"BfxALU can't find OIL bitmap");
01015         ERROR3IF( (!(B->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01016         BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader);
01017         //ERROR2IF((pBMI->biBitCount !=32), FALSE,"Bad BfxALU B reg");
01018         ERROR2IF( (!GC->SetBitmapFill(pBMI,(((CWxBitmap *)(B->ActualBitmap))->BMBytes),
01019                                     BStyle | (Style<<8),
01020                                     BPoints,
01021                                     0,
01022                                     ((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiColors,
01023                                     (unsigned char *) BpTable,
01024                                     (unsigned char *) BpTable,
01025                                     (unsigned char *) BpTable,
01026                                     NULL
01027                                     )),
01028                    FALSE,"GDraw didn't like BfxALU B reg");
01029 
01030     }
01031     
01032     return DoRect();
01033 }
01034 
01035 /********************************************************************************************
01036 
01037 >   BOOL BfxALU::PlotBLUT(BfxALULUT * LUT)
01038                     
01039     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01040     Created:    27/10/94
01041     Inputs:     None
01042     Outputs:    Performs an ALU operation A<-B
01043     Returns:    TRUE if succeeded, FALSE & error set if not
01044     Purpose:    This routine sets up GDraw for A & B, and calls DoRect()
01045     Errors:     Error 2 if init hasn't been called or GDraw fails
01046                 Error 3 if windows and some other Oil layer are stangely mixed...
01047     Scope:      Public
01048     SeeAlso:    -
01049 
01050 ********************************************************************************************/
01051 
01052 BOOL BfxALU::PlotBLUT(BfxALULUT * LUT)
01053 {
01054     DWORD Style=12;
01055     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
01056     ERROR2IF((GC==NULL),FALSE,"BfxALU::PlotBLUT() where's my LUT then?");
01057 
01058     if (!B)
01059     {
01060         ERROR2IF((!GC->SetTransparency(BColour,(enum TransparencyEnum) Style)),FALSE,"Bad BfxALU B reg");
01061     }
01062     else
01063     {
01064         ERROR2IF((B->ActualBitmap==NULL),FALSE,"BfxALU can't find OIL bitmap");
01065         ERROR3IF( (!(B->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01066         BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader);
01067         //ERROR2IF((pBMI->biBitCount !=32), FALSE,"Bad BfxALU B reg");
01068         ERROR2IF( (!GC->SetTransparencyLookupTable((CONST BYTE *) (LUT->Data))),FALSE,"Bad LUT");
01069         ERROR2IF( (!GC->SetBitmapFill(pBMI,(((CWxBitmap *)(B->ActualBitmap))->BMBytes),
01070                                     BStyle | (Style<<8),
01071                                     BPoints,
01072                                     0,
01073                                     ((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiColors,
01074                                     (unsigned char *) BpTable,
01075                                     (unsigned char *) BpTable,
01076                                     (unsigned char *) BpTable,
01077                                     NULL
01078                                     )),
01079                    FALSE,"GDraw didn't like BfxALU B reg");
01080 
01081     }
01082     
01083     return DoRect();
01084 }
01085 
01086 /********************************************************************************************
01087 
01088 >   BOOL BfxALU::PartTAB()
01089                     
01090     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01091     Created:    27/10/94
01092     Inputs:     None
01093     Outputs:    A <- TA + (1-T)B
01094     Returns:    TRUE if succeeded, FALSE & error set if not
01095     Purpose:    Arithemtic operation to do the above
01096     Errors:     Error 2 & 3 from called routines
01097     Scope:      Public
01098     SeeAlso:    -
01099 
01100 ********************************************************************************************/
01101 
01102 BOOL BfxALU::PartTAB()
01103 {
01104     return UseBT(ALUC_PART);    
01105 }
01106 
01107 /********************************************************************************************
01108 
01109 >   BOOL BfxALU::PartMulTAB()
01110                     
01111     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01112     Created:    27/10/94
01113     Inputs:     None
01114     Outputs:    A <- TAB + (1-T)B
01115     Returns:    TRUE if succeeded, FALSE & error set if not
01116     Purpose:    Arithemtic operation to do the above
01117     Errors:     Error 2 & 3 from called routines
01118     Scope:      Public
01119     SeeAlso:    -
01120 
01121 ********************************************************************************************/
01122 
01123 BOOL BfxALU::PartMulTAB()
01124 {
01125     return UseBT(ALUC_PARTMUL); 
01126 }
01127 
01128 /********************************************************************************************
01129 
01130 >   BOOL BfxALU::PartRevMulTAB()
01131                     
01132     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01133     Created:    27/10/94
01134     Inputs:     None
01135     Outputs:    A <- T(1-(1-A)(1-B)) + (1-T)B
01136     Returns:    TRUE if succeeded, FALSE & error set if not
01137     Purpose:    Arithemtic operation to do the above
01138     Errors:     Error 2 & 3 from called routines
01139     Scope:      Public
01140     SeeAlso:    -
01141 
01142 ********************************************************************************************/
01143 
01144 BOOL BfxALU::PartRevMulTAB()
01145 {
01146     return UseBT(ALUC_PARTREVMUL);  
01147 }
01148 
01149 /********************************************************************************************
01150 
01151 >   BOOL BfxALU::AddTAB()
01152                     
01153     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01154     Created:    27/10/94
01155     Inputs:     None
01156     Outputs:    A <- A + TB
01157     Returns:    TRUE if succeeded, FALSE & error set if not
01158     Purpose:    Arithemtic operation to do the above
01159     Errors:     Error 2 & 3 from called routines
01160     Scope:      Public
01161     SeeAlso:    -
01162 
01163 ********************************************************************************************/
01164 
01165 BOOL BfxALU::AddTAB()
01166 {
01167     return UseBT(ALUC_ADD); 
01168 }
01169 
01170 /********************************************************************************************
01171 
01172 >   BOOL BfxALU::SubTAB()
01173                     
01174     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01175     Created:    27/10/94
01176     Inputs:     None
01177     Outputs:    A <- A - TB
01178     Returns:    TRUE if succeeded, FALSE & error set if not
01179     Purpose:    Arithemtic operation to do the above
01180     Errors:     Error 2 & 3 from called routines
01181     Scope:      Public
01182     SeeAlso:    -
01183 
01184 ********************************************************************************************/
01185 
01186 BOOL BfxALU::SubTAB()
01187 {
01188     return UseBT(ALUC_SUB); 
01189 }
01190 
01191 /********************************************************************************************
01192 
01193 >   BOOL BfxALU::PartKAB(DWORD Value)
01194                     
01195     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01196     Created:    27/10/94
01197     Inputs:     None
01198     Outputs:    A <- TA + (1-Value)B
01199     Returns:    TRUE if succeeded, FALSE & error set if not
01200     Purpose:    Arithemtic operation to do the above
01201     Errors:     Error 2 & 3 from called routines
01202     Scope:      Public
01203     SeeAlso:    -
01204 
01205 ********************************************************************************************/
01206 
01207 BOOL BfxALU::PartKAB(DWORD Value)
01208 {
01209     return UseBK(ALUC_PART, Value); 
01210 }
01211 
01212 /********************************************************************************************
01213 
01214 >   BOOL BfxALU::PartMulKAB(DWORD Value)
01215                     
01216     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01217     Created:    27/10/94
01218     Inputs:     None
01219     Outputs:    A <- TAB + (1-Value)B
01220     Returns:    TRUE if succeeded, FALSE & error set if not
01221     Purpose:    Arithemtic operation to do the above
01222     Errors:     Error 2 & 3 from called routines
01223     Scope:      Public
01224     SeeAlso:    -
01225 
01226 ********************************************************************************************/
01227 
01228 BOOL BfxALU::PartMulKAB(DWORD Value)
01229 {
01230     return UseBK(ALUC_PARTMUL, Value);  
01231 }
01232 
01233 /********************************************************************************************
01234 
01235 >   BOOL BfxALU::PartRevMulKAB(DWORD Value)
01236                     
01237     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01238     Created:    27/10/94
01239     Inputs:     None
01240     Outputs:    A <- Value.(1-(1-A)(1-B)) + (1-Value)B
01241     Returns:    TRUE if succeeded, FALSE & error set if not
01242     Purpose:    Arithemtic operation to do the above
01243     Errors:     Error 2 & 3 from called routines
01244     Scope:      Public
01245     SeeAlso:    -
01246 
01247 ********************************************************************************************/
01248 
01249 BOOL BfxALU::PartRevMulKAB(DWORD Value)
01250 {
01251     return UseBK(ALUC_PARTREVMUL, Value);   
01252 }
01253 
01254 /********************************************************************************************
01255 
01256 >   BOOL BfxALU::AddKAB(DWORD Value)
01257                     
01258     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01259     Created:    27/10/94
01260     Inputs:     None
01261     Outputs:    A <- A + Value.B
01262     Returns:    TRUE if succeeded, FALSE & error set if not
01263     Purpose:    Arithemtic operation to do the above
01264     Errors:     Error 2 & 3 from called routines
01265     Scope:      Public
01266     SeeAlso:    -
01267 
01268 ********************************************************************************************/
01269 
01270 BOOL BfxALU::AddKAB(DWORD Value)
01271 {
01272     return UseBK(ALUC_ADD, Value);  
01273 }
01274 
01275 /********************************************************************************************
01276 
01277 >   BOOL BfxALU::SubKAB(DWORD Value)
01278                     
01279     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01280     Created:    27/10/94
01281     Inputs:     None
01282     Outputs:    A <- A - Value.B
01283     Returns:    TRUE if succeeded, FALSE & error set if not
01284     Purpose:    Arithemtic operation to do the above
01285     Errors:     Error 2 & 3 from called routines
01286     Scope:      Public
01287     SeeAlso:    -
01288 
01289 ********************************************************************************************/
01290 
01291 BOOL BfxALU::SubKAB(DWORD Value)
01292 {
01293     return UseBK(ALUC_SUB, Value);  
01294 }
01295 
01296 
01297 /********************************************************************************************
01298 
01299 >   BOOL BfxALU::MarkThresholdError(INT32 Value, DWORD MarkValue, DWORD ClearValue)
01300                     
01301     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01302     Created:    18/1/95
01303     Inputs:     Value = the threshold
01304                 MarkValue = the value to mark over the threshold pixels with
01305                 ClearValue = the value to mark other pixels with
01306     Outputs:    A <- ( (B-T)^2 >= Value ) ? MarkValue : ClearValue
01307     Returns:    TRUE if succeeded, FALSE & error set if not
01308     Purpose:    Arithemtic operation to do the above
01309     Errors:     Error 2 & 3 from called routines
01310     Scope:      Public
01311     SeeAlso:    TraceControl::MarkInitialArea
01312 
01313 This is used by the tracer routines to find an initial area to mark.
01314 
01315 ********************************************************************************************/
01316 
01317 BOOL BfxALU::MarkThresholdError(INT32 Value, DWORD MarkValue, DWORD ClearValue)
01318 {
01319     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
01320     ERROR2IF( ((!A) || (A->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
01321     ERROR3IF( (!(A->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01322     ERROR2IF( ((!B) || (B->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
01323     ERROR3IF( (!(B->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01324     ERROR2IF( ((!T) || (T->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
01325     ERROR3IF( (!(T->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01326 
01327     BITMAPINFOHEADER * pABMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
01328     BITMAPINFOHEADER * pBBMI=&(((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader);
01329     BITMAPINFOHEADER * pTBMI=&(((CWxBitmap *)(T->ActualBitmap))->BMInfo->bmiHeader);
01330 
01331     ERROR2IF((pABMI->biBitCount !=32), FALSE,"Bad BfxALU A reg");
01332     ERROR2IF((pBBMI->biBitCount !=32), FALSE,"Bad BfxALU B reg");
01333     ERROR2IF((pTBMI->biBitCount !=32), FALSE,"Bad BfxALU T reg");
01334 
01335     ERROR2IF( ((pABMI->biSizeImage != pBBMI->biSizeImage) || (pABMI->biSizeImage != pTBMI->biSizeImage)), FALSE,
01336               "Incompatible bitmaps for MarkThresholdError");
01337     
01338 //  AluPix32 * pA = (AluPix32 *)(void *)(((CWxBitmap *)(A->ActualBitmap))->BMBytes);
01339     AluPix32 * pB = (AluPix32 *)(void *)(((CWxBitmap *)(B->ActualBitmap))->BMBytes);
01340     AluPix32 * pT = (AluPix32 *)(void *)(((CWxBitmap *)(T->ActualBitmap))->BMBytes);
01341     DWORD * pO = (DWORD *)(void *)(((CWxBitmap *)(A->ActualBitmap))->BMBytes);
01342     
01343     ERROR3IF((sizeof(DWORD) != sizeof(AluPix32)), "OK who's broken AluPix32 not to be 32 bits");
01344 
01345     INT32 Size = (pABMI->biSizeImage)>>2;
01346     
01347 #ifdef FASTMARKTHRESHOLD
01348     XLONG BError = 0;
01349     INT32 MarkedPixels = 0;
01350 
01351     FastMarkThreshold((DWORD *)(void *)pA, (DWORD *)(void *)pB, (DWORD *)(void *)pT, Size, Value, MarkValue, ClearValue,
01352                      &BError, &MarkedPixels);
01353 
01354     //if (pBError) *pBError = BError.MakeDouble();
01355     //if (pMarkedPixels) *pMarkedPixels = MarkedPixels;
01356 #else
01357     for (INT32 Pixel = 0; Pixel < Size; Pixel ++)
01358         pO[Pixel] =  (( IntegerSquare( ((INT32)(pB[Pixel].R)) - ((INT32)(pT[Pixel].R)))
01359                       + IntegerSquare( ((INT32)(pB[Pixel].G)) - ((INT32)(pT[Pixel].G)))
01360                       + IntegerSquare( ((INT32)(pB[Pixel].B)) - ((INT32)(pT[Pixel].B)))) >= Value ) ? MarkValue : ClearValue;
01361 #endif
01362     return TRUE;
01363 }
01364 
01365 /********************************************************************************************
01366 
01367 >   BOOL BfxALU::MarkColourThresholdError(INT32 Value, DWORD Colour, DWORD MarkValue, DWORD ClearValue,
01368                               double * pAError = NULL, double * pBError = NULL, INT32 * pTotalPixels = NULL)
01369                     
01370     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01371     Created:    27/10/94
01372     Inputs:     Value = the threshould
01373                 MarkValue = the value to mark positively affected pixels with
01374                 ClearValue = the value to mark other pixels with
01375                 Colour = the intended colour to use
01376     Outputs:    A <- ( ((B-T)^2 >= Value ) && ((Colour-T)^2 < Value)) ? MarkValue : ClearValue
01377                 *pAError = the total error (Colour-T) (or NULL not to fill in)
01378                 *pBError = the total error in B (or NULL not to fill in)
01379                 *TotalPixels = the total number of pixels (or NULL not to fill in)
01380                 *pMarkedPixels = the number of pixels marked (or NULL not to fill in)
01381     Returns:    TRUE if succeeded, FALSE & error set if not
01382     Purpose:    Arithemtic operation to do the above
01383     Errors:     Error 2 & 3 from called routines
01384     Scope:      Public
01385     SeeAlso:    TraceControl::MarkPositiveArea
01386 
01387 This is used by the tracer routines to find positively affected areas to mark.
01388 
01389 ********************************************************************************************/
01390 
01391 BOOL BfxALU::MarkColourThresholdError(INT32 Value, DWORD Colour, DWORD MarkValue, DWORD ClearValue,
01392                               double * pAError, double * pBError, INT32 * pTotalPixels, INT32 * pMarkedPixels)
01393 {
01394     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
01395     ERROR2IF( ((!A) || (A->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
01396     ERROR3IF( (!(A->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01397     ERROR2IF( ((!B) || (B->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
01398     ERROR3IF( (!(B->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01399     ERROR2IF( ((!T) || (T->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
01400     ERROR3IF( (!(T->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01401 
01402     BITMAPINFOHEADER * pABMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
01403     BITMAPINFOHEADER * pBBMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
01404     BITMAPINFOHEADER * pTBMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
01405 
01406     ERROR2IF((pABMI->biBitCount !=32), FALSE,"Bad BfxALU A reg");
01407     ERROR2IF((pBBMI->biBitCount !=32), FALSE,"Bad BfxALU B reg");
01408     ERROR2IF((pTBMI->biBitCount !=32), FALSE,"Bad BfxALU T reg");
01409 
01410     ERROR2IF( ((pABMI->biSizeImage != pBBMI->biSizeImage) || (pABMI->biSizeImage != pTBMI->biSizeImage)), FALSE,
01411               "Incompatible bitmaps for MarkThresholdError");
01412     
01413 //  AluPix32 * pA = (AluPix32 *)(void *)(((CWxBitmap *)(A->ActualBitmap))->BMBytes);
01414     AluPix32 * pB = (AluPix32 *)(void *)(((CWxBitmap *)(B->ActualBitmap))->BMBytes);
01415     AluPix32 * pT = (AluPix32 *)(void *)(((CWxBitmap *)(T->ActualBitmap))->BMBytes);
01416     DWORD * pO = (DWORD *)(void *)(((CWxBitmap *)(A->ActualBitmap))->BMBytes);
01417 
01418     ERROR3IF((sizeof(DWORD) != sizeof(AluPix32)), "OK who's broken AluPix32 not to be 32 bits");
01419 
01420     AluPix32 TheColour;
01421     *(DWORD *)(void *)(&TheColour)=Colour; // Yuck
01422 
01423     INT32 Size = (pABMI->biSizeImage)>>2;
01424     if (pTotalPixels) *pTotalPixels = Size;
01425 
01426 #ifdef FASTMARKCOLOURTHRESHOLD
01427     XLONG AError = 0;
01428     XLONG BError = 0;
01429     INT32 MarkedPixels = 0;
01430 
01431     FastMarkColourThreshold((DWORD *)(void *)pA, (DWORD *)(void *)pB, (DWORD *)(void *)pT, Size, Value, Colour,
01432                      MarkValue, ClearValue, &AError, &BError, &MarkedPixels);
01433 
01434     if (pAError) *pAError = AError.MakeDouble();
01435     if (pBError) *pBError = BError.MakeDouble();
01436     if (pMarkedPixels) *pMarkedPixels = MarkedPixels;
01437 
01438 #else
01439     double AError = 0.0;
01440     double BError = 0.0;
01441     INT32 BE;
01442     INT32 AE;
01443     INT32 MarkedPixels=0; 
01444     
01445     for (INT32 Pixel = 0; Pixel < Size; Pixel ++)
01446     {   AE = ( IntegerSquare( ((INT32)(TheColour.R)) - ((INT32)(pT[Pixel].R)))
01447              + IntegerSquare( ((INT32)(TheColour.G)) - ((INT32)(pT[Pixel].G)))
01448              + IntegerSquare( ((INT32)(TheColour.B)) - ((INT32)(pT[Pixel].B))) );
01449 
01450         BE = ( IntegerSquare( ((INT32)(pB[Pixel].R)) - ((INT32)(pT[Pixel].R)))
01451              + IntegerSquare( ((INT32)(pB[Pixel].G)) - ((INT32)(pT[Pixel].G)))
01452              + IntegerSquare( ((INT32)(pB[Pixel].B)) - ((INT32)(pT[Pixel].B))) );
01453 
01454         AError += AE;
01455         BError += BE;
01456         
01457         pO[Pixel] = ((AE<Value) && (BE>=Value)) ? (MarkedPixels++,MarkValue) : ClearValue;
01458     }
01459 
01460     if (pAError) *pAError = AError;
01461     if (pBError) *pBError = BError;
01462     if (pMarkedPixels) *pMarkedPixels = MarkedPixels;
01463 #endif
01464 
01465     return TRUE;
01466 }
01467 
01468 /********************************************************************************************
01469 
01470 >   BOOL BfxALU::MarkPositive(INT32 Value, DWORD MarkValue, DWORD ClearValue,
01471                               double * pAError = NULL, double * pBError = NULL, INT32 * pTotalPixels = NULL)
01472                     
01473     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01474     Created:    27/10/94
01475     Inputs:     Value = the threshould
01476                 MarkValue = the value to mark positively affected pixels with
01477                 ClearValue = the value to mark other pixels with
01478     Outputs:    A <- ( ((B-T)^2 >= Value ) && ((A-T)^2 < Value)) ? MarkValue : ClearValue
01479                 *pAError = the total error in A (or NULL not to fill in)
01480                 *pBError = the total error in B (or NULL not to fill in)
01481                 *TotalPixels = the total number of pixels (or NULL not to fill in)
01482                 *pMarkedPixels = the number of pixels marked (or NULL not to fill in)
01483     Returns:    TRUE if succeeded, FALSE & error set if not
01484     Purpose:    Arithemtic operation to do the above
01485     Errors:     Error 2 & 3 from called routines
01486     Scope:      Public
01487     SeeAlso:    TraceControl::MarkPositiveArea
01488 
01489 This is used by the tracer routines to find positively affected areas to mark.
01490 
01491 ********************************************************************************************/
01492 
01493 BOOL BfxALU::MarkPositive(INT32 Value, DWORD MarkValue, DWORD ClearValue,
01494                               double * pAError, double * pBError, INT32 * pTotalPixels, INT32 * pMarkedPixels)
01495 {
01496     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
01497     ERROR2IF( ((!A) || (A->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
01498     ERROR3IF( (!(A->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01499     ERROR2IF( ((!B) || (B->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
01500     ERROR3IF( (!(B->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01501     ERROR2IF( ((!T) || (T->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
01502     ERROR3IF( (!(T->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01503 
01504     BITMAPINFOHEADER * pABMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
01505     BITMAPINFOHEADER * pBBMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
01506     BITMAPINFOHEADER * pTBMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
01507 
01508     ERROR2IF((pABMI->biBitCount !=32), FALSE,"Bad BfxALU A reg");
01509     ERROR2IF((pBBMI->biBitCount !=32), FALSE,"Bad BfxALU B reg");
01510     ERROR2IF((pTBMI->biBitCount !=32), FALSE,"Bad BfxALU T reg");
01511 
01512     ERROR2IF( ((pABMI->biSizeImage != pBBMI->biSizeImage) || (pABMI->biSizeImage != pTBMI->biSizeImage)), FALSE,
01513               "Incompatible bitmaps for MarkThresholdError");
01514     
01515     AluPix32 * pA = (AluPix32 *)(void *)(((CWxBitmap *)(A->ActualBitmap))->BMBytes);
01516     AluPix32 * pB = (AluPix32 *)(void *)(((CWxBitmap *)(B->ActualBitmap))->BMBytes);
01517     AluPix32 * pT = (AluPix32 *)(void *)(((CWxBitmap *)(T->ActualBitmap))->BMBytes);
01518     DWORD * pO = (DWORD *)(void *)(((CWxBitmap *)(A->ActualBitmap))->BMBytes);
01519 
01520     ERROR3IF((sizeof(DWORD) != sizeof(AluPix32)), "OK who's broken AluPix32 not to be 32 bits");
01521 
01522     INT32 Size = (pABMI->biSizeImage)>>2;
01523     if (pTotalPixels) *pTotalPixels = Size;
01524 
01525 #ifdef FASTMARKPOSITIVE
01526     XLONG AError = 0;
01527     XLONG BError = 0;
01528     INT32 MarkedPixels = 0;
01529 
01530     FastMarkPositive((DWORD *)(void *)pA, (DWORD *)(void *)pB, (DWORD *)(void *)pT, Size, Value, MarkValue, ClearValue,
01531                      &AError, &BError, &MarkedPixels);
01532 
01533     if (pAError) *pAError = AError.MakeDouble();
01534     if (pBError) *pBError = BError.MakeDouble();
01535     if (pMarkedPixels) *pMarkedPixels = MarkedPixels;
01536 
01537 #else
01538     double AError = 0.0;
01539     double BError = 0.0;
01540     INT32 BE;
01541     INT32 AE;
01542     INT32 MarkedPixels=0; 
01543     
01544     for (INT32 Pixel = 0; Pixel < Size; Pixel ++)
01545     {   AE = ( IntegerSquare( ((INT32)(pA[Pixel].R)) - ((INT32)(pT[Pixel].R)))
01546              + IntegerSquare( ((INT32)(pA[Pixel].G)) - ((INT32)(pT[Pixel].G)))
01547              + IntegerSquare( ((INT32)(pA[Pixel].B)) - ((INT32)(pT[Pixel].B))) );
01548 
01549         BE = ( IntegerSquare( ((INT32)(pB[Pixel].R)) - ((INT32)(pT[Pixel].R)))
01550              + IntegerSquare( ((INT32)(pB[Pixel].G)) - ((INT32)(pT[Pixel].G)))
01551              + IntegerSquare( ((INT32)(pB[Pixel].B)) - ((INT32)(pT[Pixel].B))) );
01552 
01553         AError += AE;
01554         BError += BE;
01555         
01556         pO[Pixel] = ((AE<Value) && (BE>=Value)) ? (MarkedPixels++,MarkValue) : ClearValue;
01557     }
01558 
01559     if (pAError) *pAError = AError;
01560     if (pBError) *pBError = BError;
01561     if (pMarkedPixels) *pMarkedPixels = MarkedPixels;
01562 #endif
01563 
01564     return TRUE;
01565 }
01566 
01567 
01568 /********************************************************************************************
01569 
01570 >   BOOL BfxALU::MarkBitByWord(DWORD BitMask, DWORD TheWord)
01571                     
01572     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01573     Created:    27/10/94
01574     Inputs:     TheWord = value to look for to mark
01575     Outputs:    A |= BitMask if B=TheWord
01576                   &= ~BitMask otherwise
01577     Returns:    TRUE if succeeded, FALSE & error set if not
01578     Purpose:    Arithemtic operation to do the above
01579     Errors:     Error 2 & 3 from called routines
01580     Scope:      Public
01581     SeeAlso:    BfxALU::MarkWordByBit, TraceControl::FindInitialArea
01582 
01583 ********************************************************************************************/
01584 
01585 BOOL BfxALU::MarkBitByWord(DWORD BitMask, DWORD TheWord)
01586 {
01587     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
01588     ERROR2IF( ((!A) || (A->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
01589     ERROR3IF( (!(A->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01590     ERROR2IF( ((!B) || (B->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
01591     ERROR3IF( (!(B->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01592 
01593     BITMAPINFOHEADER * pABMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
01594     BITMAPINFOHEADER * pBBMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
01595 
01596     ERROR2IF((pABMI->biBitCount !=32), FALSE,"Bad BfxALU A reg");
01597     ERROR2IF((pBBMI->biBitCount !=32), FALSE,"Bad BfxALU B reg");
01598 
01599     ERROR2IF( (pABMI->biSizeImage != pBBMI->biSizeImage), FALSE, "Incompatible bitmaps for MarkBitByWord");
01600     
01601     DWORD * pA = (DWORD *)(void *)(((CWxBitmap *)(A->ActualBitmap))->BMBytes);
01602     DWORD * pB = (DWORD *)(void *)(((CWxBitmap *)(B->ActualBitmap))->BMBytes);
01603 
01604     ERROR3IF((sizeof(DWORD) != sizeof(AluPix32)), "OK who's broken AluPix32 not to be 32 bits");
01605 
01606     INT32 Size = (pABMI->biSizeImage)>>2;
01607 
01608 #ifdef FASTMARKBITBYWORD
01609     FastMarkBitByWord(pB, pA, Size, BitMask, TheWord);
01610 #else
01611     for (INT32 Pixel = 0; Pixel < Size; Pixel ++) if (pB[Pixel]==TheWord) pA[Pixel]|=BitMask; else pA[Pixel]&=~BitMask;
01612 #endif
01613 
01614     return TRUE;
01615 }
01616 
01617 /********************************************************************************************
01618 
01619 >   BOOL BfxALU::ClearBitByWord(DWORD BitMask, DWORD TheWord)
01620                     
01621     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01622     Created:    27/10/94
01623     Inputs:     TheWord = value to look for to mark
01624     Outputs:    A &= ~BitMask if B=TheWord else intact
01625     Returns:    TRUE if succeeded, FALSE & error set if not
01626     Purpose:    Arithemtic operation to do the above
01627     Errors:     Error 2 & 3 from called routines
01628     Scope:      Public
01629     SeeAlso:    BfxALU::MarkWordByBit, TraceControl::FindInitialArea
01630 
01631 ********************************************************************************************/
01632 
01633 BOOL BfxALU::ClearBitByWord(DWORD BitMask, DWORD TheWord)
01634 {
01635     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
01636     ERROR2IF( ((!A) || (A->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
01637     ERROR3IF( (!(A->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01638     ERROR2IF( ((!B) || (B->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
01639     ERROR3IF( (!(B->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01640 
01641     BITMAPINFOHEADER * pABMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
01642     BITMAPINFOHEADER * pBBMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
01643 
01644     ERROR2IF((pABMI->biBitCount !=32), FALSE,"Bad BfxALU A reg");
01645     ERROR2IF((pBBMI->biBitCount !=32), FALSE,"Bad BfxALU B reg");
01646 
01647     ERROR2IF( (pABMI->biSizeImage != pBBMI->biSizeImage), FALSE, "Incompatible bitmaps for MarkBitByWord");
01648     
01649     DWORD * pA = (DWORD *)(void *)(((CWxBitmap *)(A->ActualBitmap))->BMBytes);
01650     DWORD * pB = (DWORD *)(void *)(((CWxBitmap *)(B->ActualBitmap))->BMBytes);
01651 
01652     ERROR3IF((sizeof(DWORD) != sizeof(AluPix32)), "OK who's broken AluPix32 not to be 32 bits");
01653 
01654     INT32 Size = (pABMI->biSizeImage)>>2;
01655 
01656 #ifdef FASTCLEARBITBYWORD
01657     FastClearBitByWord(pB, pA, Size, BitMask, TheWord);
01658 #else
01659     for (INT32 Pixel = 0; Pixel < Size; Pixel ++) if (pB[Pixel]==TheWord) pA[Pixel]&=~BitMask;
01660 #endif
01661 
01662     return TRUE;
01663 }
01664         
01665 /********************************************************************************************
01666 
01667 >   BOOL BfxALU::MarkWordByBit(DWORD BitMask, DWORD MarkValue, DWORD ClearValue)
01668                     
01669     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01670     Created:    27/10/94
01671     Inputs:     MarkValue & ClearValue = the two workds with which to mark
01672     Outputs:    A = ((B & BitMask) ? MarkValue:ClearValue);
01673     Returns:    TRUE if succeeded, FALSE & error set if not
01674     Purpose:    Arithemtic operation to do the above
01675     Errors:     Error 2 & 3 from called routines
01676     Scope:      Public
01677     SeeAlso:    BfxALU::MarkWordByBit, TraceControl::FindInitialArea
01678 
01679 ********************************************************************************************/
01680 
01681 BOOL BfxALU::MarkWordByBit(DWORD BitMask, DWORD MarkValue, DWORD ClearValue)
01682 {
01683     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
01684     ERROR2IF( ((!A) || (A->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
01685     ERROR3IF( (!(A->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01686     ERROR2IF( ((!B) || (B->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
01687     ERROR3IF( (!(B->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01688 
01689     BITMAPINFOHEADER * pABMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
01690     BITMAPINFOHEADER * pBBMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
01691 
01692     ERROR2IF((pABMI->biBitCount !=32), FALSE,"Bad BfxALU A reg");
01693     ERROR2IF((pBBMI->biBitCount !=32), FALSE,"Bad BfxALU B reg");
01694 
01695     ERROR2IF( (pABMI->biSizeImage != pBBMI->biSizeImage), FALSE, "Incompatible bitmaps for MarkWordByBit");
01696     
01697     DWORD * pB = (DWORD *)(void *)(((CWxBitmap *)(B->ActualBitmap))->BMBytes);
01698     DWORD * pA = (DWORD *)(void *)(((CWxBitmap *)(A->ActualBitmap))->BMBytes);
01699 
01700     ERROR3IF((sizeof(DWORD) != sizeof(AluPix32)), "OK who's broken AluPix32 not to be 32 bits");
01701 
01702     INT32 Size = (pABMI->biSizeImage)>>2;
01703 
01704 #ifdef FASTMARKWORDBYBIT
01705     FastMarkWordByBit(pB, pA, Size, BitMask, MarkValue, ClearValue);
01706 #else   
01707     for (INT32 Pixel = 0; Pixel < Size; Pixel ++) pA[Pixel] = (pB[Pixel] & BitMask) ? MarkValue : ClearValue;
01708 #endif
01709 
01710     return TRUE;
01711 }
01712 
01713         
01714 /********************************************************************************************
01715 
01716 >   BOOL BfxALU::MarkRegions(DWORD MarkValue, DWORD ClearValue,
01717                                  BOOL * FoundRegion, INT32 * InitialX, INT32 * InitialY, INT32 * Area,
01718                                  INT32 * pSize, INT32 * pHighestChain, INT32 * pWidth, DWORD * * ppA)
01719                     
01720     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01721     Created:    27/10/94
01722     Inputs:     MarkValue = the value marked pixel have
01723                 ClearValue = the value cleared pixels have
01724     Outputs:    A = RegionValue if pixel is in largest region, otherwise a different number
01725                     ClearValue if pixel is not marked
01726                     otherwise a different value from the above two.
01727                 *pAError = the total error in A (or NULL not to fill in)
01728                 *pBError = the total error in B (or NULL not to fill in)
01729                 *TotalPixels = the total number of pixels (or NULL not to fill in)
01730                 *pSize = Size of image if not NULL
01731                 *pHighestChain = chain ID of highest chain if not NULL
01732                 *pWidth=Width if not NULL
01733                 *ppA=pointer to bitmap if not null
01734     Returns:    TRUE if succeeded, FALSE & error set if not
01735     Purpose:    Arithemtic operation to do the above
01736     Errors:     Error 2 & 3 from called routines
01737     Scope:      Public
01738     SeeAlso:    TraceControl::FindInitialPoint, BfxALU::MarkLargestArea, BfxALU::BuildErrorRegionList
01739 
01740 The areas are chain coded.
01741 
01742 ********************************************************************************************/
01743 
01744 #define MLATestPixel(q) \
01745 { \
01746     OtherPixel = q; \
01747     while (pA[OtherPixel] < 0x80000000) OtherPixel = pA[OtherPixel]; /* get top of pixel chain */ \
01748     /* only count marked pixels (we can do this by eliminating clear pixels as we've processed all the pixels */ \
01749     /*  this routine considers). Don't count pixels which are attached to the same chain as us already */ \
01750     if ((pA[OtherPixel] != ClearValue) && (OtherPixel !=TopChain)) \
01751     { \
01752         /* OtherPixel points to the top of the other pixel's pixel chain */ \
01753         /* Always use lowest numbered chain */ \
01754         if (TopChain<OtherPixel) {SwapTemp=TopChain;TopChain=OtherPixel;OtherPixel=SwapTemp;} \
01755         pA[OtherPixel]+=pA[TopChain]-0x80000000; /* Add chain values together */ \
01756         pA[TopChain]= OtherPixel; /* attach top of current chain to pixel */ \
01757         TopChain=OtherPixel; /* Move the current chain top. */ \
01758     } \
01759 }
01760 
01761 BOOL BfxALU::MarkRegions(DWORD MarkValue, DWORD ClearValue,
01762                              BOOL * FoundRegion, INT32 * InitialX, INT32 * InitialY, INT32 * Area,
01763                              INT32 * pSize, INT32 * pHighestChain, INT32 * pWidth, DWORD * * ppA)
01764 
01765 {
01766     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
01767     ERROR2IF( ((!A) || (A->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
01768     ERROR2IF(!FoundRegion,FALSE,"Found Region flag is compulsorary");
01769     ERROR3IF( (!(A->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
01770 
01771     BITMAPINFOHEADER * pABMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
01772 
01773     ERROR2IF((pABMI->biBitCount !=32), FALSE,"Bad BfxALU A reg");
01774     
01775     DWORD * pA = (DWORD *)(void *)(((CWxBitmap *)(A->ActualBitmap))->BMBytes);
01776 
01777     INT32 Size = (pABMI->biSizeImage)>>2;
01778     INT32 Width = pABMI->biWidth;
01779     INT32 x=0;
01780     INT32 y=0;
01781     INT32 HighestChainVal = 0;
01782     INT32 HighestChain = -1;
01783 
01784 #ifdef FASTMARKREGIONS
01785     FastMarkRegions(pA, Size, Width, MarkValue, ClearValue, &HighestChain, &HighestChainVal);
01786 #else
01787     INT32 Pixel;
01788     INT32 TopChain;
01789     INT32 OtherPixel;
01790     INT32 SwapTemp;
01791             
01792     for (Pixel = 0; Pixel < Size; Pixel ++)
01793     {
01794         
01795         if (pA[Pixel] != ClearValue)
01796         {
01797             pA[Pixel] = 0x80000001; // Mark as a single pixel chain
01798             TopChain = Pixel; // and this is it's top
01799             // OK, we've found a new pixel. First work out if it is connected to any other previously
01800             if (x!=0) MLATestPixel(Pixel-1);
01801             if (y!=0)
01802             {
01803                 if (x!=Width-1) MLATestPixel(Pixel-Width+1);
01804                 MLATestPixel(Pixel-Width);
01805                 if (x!=0) MLATestPixel(Pixel-Width-1);
01806             }
01807             if (((INT32)(pA[TopChain]-0x80000000))>HighestChainVal)
01808             {
01809                 HighestChainVal = (INT32)(pA[TopChain]-0x80000000);
01810                 HighestChain = TopChain;
01811             }
01812         }
01813         if ((++x)==Width)
01814         {
01815             x=0;
01816             y++;
01817         }
01818     }
01819 #endif
01820 
01821     if (InitialX) *InitialX = 0;
01822     if (InitialY) *InitialY = 0;
01823     if (Area) *Area = HighestChainVal;
01824     if ( (*FoundRegion =/*assign*/ (HighestChain != -1) ) != FALSE )
01825     {
01826         if (InitialX) *InitialX = HighestChain % Width;
01827         if (InitialY) *InitialY = HighestChain / Width;
01828     }
01829     if (pSize) *pSize = Size;
01830     if (pHighestChain) *pHighestChain = HighestChain;
01831     if (ppA) *ppA=pA;
01832     if (pWidth) *pWidth=Width;
01833     return TRUE;
01834 }
01835 
01836 
01837 /********************************************************************************************
01838 
01839 >   BOOL BfxALU::MarkLargestArea(DWORD MarkValue, DWORD ClearValue, DWORD RegionValue
01840                                  BOOL * FoundRegion, INT32 * InitialX, INT32 * InitialY, INT32 * Area)
01841 
01842                     
01843     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01844     Created:    27/10/94
01845     Inputs:     MarkValue = the value marked pixel have
01846                 ClearValue = the value cleared pixels have
01847                 RegionValue = the value to mark pixels in the largest region witgh
01848     Outputs:    A = RegionValue if pixel is in largest region, otherwise a different number
01849                     ClearValue if pixel is not marked
01850                     otherwise a different value from the above two.
01851                 *pAError = the total error in A (or NULL not to fill in)
01852                 *pBError = the total error in B (or NULL not to fill in)
01853                 *TotalPixels = the total number of pixels (or NULL not to fill in)
01854     Returns:    TRUE if succeeded, FALSE & error set if not
01855     Purpose:    Arithemtic operation to do the above
01856     Errors:     Error 2 & 3 from called routines
01857     Scope:      Public
01858     SeeAlso:    TraceControl::FindInitialPoint, BfxALU::MarkRegions, BfxALU::BuildErrorRegionList
01859 
01860 This is used by the tracer routines work out the area to mark.
01861 
01862 ********************************************************************************************/
01863 
01864 BOOL BfxALU::MarkLargestArea(DWORD MarkValue, DWORD ClearValue, DWORD RegionValue,
01865                              BOOL * FoundRegion, INT32 * InitialX, INT32 * InitialY, INT32 * Area)
01866 {
01867     INT32 Size;
01868     INT32 HighestChain;
01869     DWORD * pA;
01870     // Our error checking done in MarkRegions
01871     if (!MarkRegions(MarkValue, ClearValue, FoundRegion, InitialX, InitialY, Area,
01872                      &Size, &HighestChain, NULL, &pA)) return FALSE;
01873 
01874     if (!*FoundRegion) return TRUE; //No need for this poxy coding then
01875 
01876 #ifdef FASTMARKLARGESTAREA
01877     FastMarkLargestArea(pA, Size, MarkValue, ClearValue, RegionValue, HighestChain);
01878 #else
01879     INT32 OtherPixel;
01880     INT32 Pixel;
01881     for (Pixel = (Size-1); Pixel >= 0; Pixel--)
01882     {
01883         OtherPixel = Pixel;
01884         while (pA[OtherPixel] < 0x80000000) OtherPixel = pA[OtherPixel]; // get top of pixel chain
01885         if (OtherPixel==HighestChain)
01886         {
01887             pA[Pixel] = RegionValue;
01888         }
01889         else
01890         {
01891             if (pA[Pixel]!=ClearValue)
01892 #if 1
01893                 pA[Pixel] = MarkValue;
01894 #else           
01895                 pA[Pixel] = 0x7F020202 | (_lrotl((OtherPixel ^ 0xabcdef13),(OtherPixel % 31)) % 0xFFFFFF);
01896 #endif
01897         }
01898     }
01899 #endif
01900     return TRUE;
01901 }
01902 
01903 /********************************************************************************************
01904 
01905 >   BOOL BfxALU::MarkGivenArea(DWORD MarkValue, DWORD ClearValue, DWORD RegionValue
01906                                  BOOL * FoundRegion, INT32 * InitialX, INT32 * InitialY, INT32 * Area)
01907 
01908                     
01909     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01910     Created:    27/10/94
01911     Inputs:     MarkValue = the value marked pixel have
01912                 ClearValue = the value cleared pixels have
01913                 RegionValue = the value to mark pixels in the largest region witgh
01914                 *InitialX,Y = A coordinate in the region to be marked
01915     Outputs:    A = RegionValue if pixel is in largest region, otherwise a different number
01916                     ClearValue if pixel is not marked
01917                     otherwise a different value from the above two.
01918                 *pAError = the total error in A (or NULL not to fill in)
01919                 *pBError = the total error in B (or NULL not to fill in)
01920                 *TotalPixels = the total number of pixels (or NULL not to fill in)
01921                 *InitialX,Y = Initial point in region to be marked
01922     Returns:    TRUE if succeeded, FALSE & error set if not
01923     Purpose:    Arithemtic operation to do the above
01924     Errors:     Error 2 & 3 from called routines
01925     Scope:      Public
01926     SeeAlso:    TraceControl::FindInitialPoint, BfxALU::MarkRegions, BfxALU::BuildErrorRegionList
01927 
01928 This is used by the tracer routines work out the area to mark.
01929 
01930 ********************************************************************************************/
01931 
01932 BOOL BfxALU::MarkGivenArea(DWORD MarkValue, DWORD ClearValue, DWORD RegionValue,
01933                              BOOL * FoundRegion, INT32 * InitialX, INT32 * InitialY, INT32 * Area)
01934 {
01935     INT32 Size;
01936     INT32 HighestChain;
01937     DWORD * pA;
01938     ERROR2IF((!InitialX)||(!InitialY),FALSE, "Why not pass in an InitialX & InitialY");
01939     INT32 ix = *InitialX;
01940     INT32 iy = *InitialY;
01941     INT32 Width;
01942     // Our error checking done in MarkRegions
01943     if (!MarkRegions(MarkValue, ClearValue, FoundRegion, InitialX, InitialY, Area,
01944                      &Size, &HighestChain, &Width, &pA)) return FALSE;
01945 
01946     HighestChain=ix+Width*iy;
01947     while (pA[HighestChain] < 0x80000000) HighestChain = pA[HighestChain]; // get top of pixel chain
01948     if (pA[HighestChain] == ClearValue) HighestChain=-1;
01949 
01950     if (InitialX) *InitialX = 0;
01951     if (InitialY) *InitialY = 0;
01952     if (Area) *Area = 0;
01953     if ( (*FoundRegion =/*assign*/ (HighestChain != -1) ) != FALSE )
01954     {
01955         if (InitialX) *InitialX = HighestChain % Width;
01956         if (InitialY) *InitialY = HighestChain / Width;
01957         if (Area) *Area = pA[HighestChain] - 0x80000000;
01958     }
01959     
01960     if (!*FoundRegion) return TRUE; //No need for this poxy coding then
01961 
01962 #ifdef FASTMARKLARGESTAREA
01963     FastMarkLargestArea(pA, Size, MarkValue, ClearValue, RegionValue, HighestChain);
01964 #else
01965     INT32 OtherPixel;
01966     INT32 Pixel;
01967     for (Pixel = (Size-1); Pixel >= 0; Pixel--)
01968     {
01969         OtherPixel = Pixel;
01970         while (pA[OtherPixel] < 0x80000000) OtherPixel = pA[OtherPixel]; // get top of pixel chain
01971         if (OtherPixel==HighestChain)
01972         {
01973             pA[Pixel] = RegionValue;
01974         }
01975         else
01976         {
01977             if (pA[Pixel]!=ClearValue)
01978 #if 1
01979                 pA[Pixel] = MarkValue;
01980 #else           
01981                 pA[Pixel] = 0x7F020202 | (_lrotl((OtherPixel ^ 0xabcdef13),(OtherPixel % 31)) % 0xFFFFFF);
01982 #endif
01983         }
01984     }
01985 #endif
01986     return TRUE;
01987 }
01988 
01989 /********************************************************************************************
01990 
01991 >   BOOL BfxALU::BuildErrorRegionList(DWORD MarkValue, DWORD ClearValue, DWORD RegionValue,
01992                               BfxErrorRegionList * pERL, INT32 MinimumArea)
01993 
01994                     
01995     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01996     Created:    27/10/94
01997     Inputs:     MarkValue = the value marked pixel have
01998                 ClearValue = the value cleared pixels have
01999                 *pERL = error region list to alter
02000                 MinimumArea = min area to consider
02001     Outputs:    A = RegionValue if pixel is in region, otherwise a different number
02002                     ClearValue if pixel is not marked
02003                 *pERL altered
02004     Returns:    TRUE if succeeded, FALSE & error set if not
02005     Purpose:    Arithemtic operation to do the above
02006     Errors:     Error 2 & 3 from called routines
02007     Scope:      Public
02008     SeeAlso:    TraceControl::FindInitialPoint, BfxALU::MarkRegions, BfxALU::BuildErrorRegionList
02009 
02010 This is used by the tracer routines work out the area to mark.
02011 
02012 ********************************************************************************************/
02013 
02014 BOOL BfxALU::BuildErrorRegionList(DWORD MarkValue, DWORD ClearValue, DWORD RegionValue,
02015                               BfxErrorRegionList * pERL, INT32 MinimumArea)
02016 {
02017     INT32 Pixel;
02018     INT32 Size;
02019     INT32 Width;
02020     DWORD * pA;
02021     BOOL FoundRegion=FALSE;
02022     
02023     ERROR2IF(!pERL, FALSE, "OK, Where's the error region list then?");
02024     
02025     // Empty the region list
02026     if (!pERL->Empty()) return FALSE;
02027 
02028 //  INT32 ListSize=pERL->GetSize();
02029 
02030     // Most of our error checking done in MarkRegions
02031     if (!MarkRegions(MarkValue, ClearValue, &FoundRegion, NULL, NULL, NULL,
02032                      &Size, NULL, &Width, &pA)) return FALSE;
02033 
02034     INT32 Area;
02035     
02036     if (FoundRegion)
02037     {
02038         Pixel = 0;
02039         do
02040         {
02041 
02042 #ifdef FASTBUILDERRORREGIONLIST
02043             FastBuildErrorRegionList(pA, Size, RegionValue, ClearValue, MinimumArea, &Pixel, &Area);
02044 #else
02045             do
02046             {
02047                 if ((DWORD) (Area=(INT32)(pA[Pixel])) != ClearValue) pA[Pixel]=RegionValue;
02048                 // We evilly use bit 30 to check for clearvalue
02049             } while ( (((DWORD)Area & 0xC0000000)!=0x80000000) && (Pixel++<Size));
02050 #endif
02051     
02052             if (Pixel<Size)
02053             {
02054                 if ((DWORD)(Area-0x80000000) >= (DWORD)MinimumArea)
02055                 {
02056 //                  TRACEUSER( "Alex", _T("Found region at %d,%d Area %d\n"),Pixel % Width, Pixel / Width, Area-0x80000000);
02057                     if (pERL->IsSpace()) pERL->Insert(Pixel % Width, Pixel / Width, Area-0x80000000);
02058                 }
02059 
02060             }
02061         } while (Pixel<Size);
02062 
02063     }
02064     if (!pERL->IsSpace()) TRACEUSER( "Alex", _T("[[BuildErrorRegionList ran out of space]]\n"));
02065 
02066     return (pERL->Sort() && pERL->ResetRead());
02067 }
02068 
02070 // Here's the old routine
02071 #if 0
02072     if (FoundRegion)
02073     {
02074         for (Pixel = (Size-1); Pixel >= 0; Pixel--)
02075         {
02076             if (((Area/*assign*/=pA[Pixel])<0xFF000000) && (Area>=0x80000000))
02077             {
02078                 if ((INT32)(Area-0x80000000) > MinimumArea)
02079                 {
02080 //                  TRACEUSER( "Alex", _T("Found region at %d,%d Area %d\n"),Pixel % Width, Pixel / Width, Area-0x80000000);
02081                     if (pERL->IsSpace()) pERL->Insert(Pixel % Width, Pixel / Width, Area-0x80000000);
02082                 }
02083             }
02084             if (((DWORD)Area) != ClearValue) pA[Pixel]=RegionValue;
02085         }
02086     }
02087 #endif
02088 
02089 /********************************************************************************************
02090 
02091 >   BOOL BfxALU::ScanBit(DWORD BitMask, INT32 * X, INT32 * Y, INT32 * pPixel, BOOL * Found, BOOL CheckConnected=FALSE)
02092                     
02093     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
02094     Created:    27/10/94
02095     Inputs:     BitMask = the bit mask to search for
02096                 *X = the start X position or NULL
02097                 *Y = the start Y position or NULL
02098                 *pPixel = the start pixel position (takes priority over X & Y) or NULL
02099                 CheckConnected = TRUE to check at least one connected bit is also set
02100     Outputs:    *X = the end X position or 0 if none found
02101                 *Y = the end Y position or 0 if none found
02102                 *pPixel = the end pixel position or 0 if none found
02103                 *Found = TRUE if found a pixel such that (A & BitMask) is non zero
02104     Returns:    TRUE if succeeded, FALSE & error set if not
02105     Purpose:    Arithemtic operation to search A for the next pixel s.t. (A & BitMask) !=0
02106     Errors:     Error 2 & 3 from called routines
02107     Scope:      Public
02108     SeeAlso:    TraceControl::FindInitialArea
02109 
02110 ********************************************************************************************/
02111 
02112 BOOL BfxALU::ScanBit(DWORD BitMask, INT32 * X, INT32 * Y, INT32 *pPixel, BOOL * Found, BOOL CheckConnected)
02113 {
02114     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
02115     ERROR2IF( ((!A) || (A->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
02116     ERROR3IF( (!(A->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
02117 
02118     BITMAPINFOHEADER * pABMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
02119 
02120     ERROR2IF((pABMI->biBitCount !=32), FALSE,"Bad BfxALU A reg");
02121 
02122     DWORD * pA = (DWORD *)(void *)(((CWxBitmap *)(A->ActualBitmap))->BMBytes);
02123 
02124     INT32 Width = pABMI->biWidth;
02125     INT32 Size = (pABMI->biSizeImage)>>2;
02126 
02127     INT32 Pixel = 0;
02128     BOOL Connected = TRUE;
02129     if (pPixel) Pixel=*pPixel; else if (X && Y) Pixel=(*X)+(*Y)*Width;
02130     INT32 tx;
02131     INT32 ty;
02132 
02133     do
02134     {
02135 #ifdef FASTSCANBIT
02136         if (Pixel<Size) FastScanBit(pA, Size, BitMask, &Pixel);
02137 #else   
02138         while (Pixel<Size && !(pA[Pixel] & BitMask)) Pixel++;
02139 #endif
02140         if (Pixel>=Size)
02141         {
02142             if (X) *X=0;
02143             if (Y) *Y=0;
02144             if (pPixel) *pPixel=0;
02145             if (Found) *Found=FALSE;
02146             return TRUE;
02147         }
02148         tx=Pixel % Width;
02149         ty=Pixel / Width;
02150         if (pPixel) *pPixel=Pixel;
02151         if (X) *X=tx;
02152         if (Y) *Y=ty;
02153         if (Found) *Found=TRUE;
02154 
02155         Connected = !CheckConnected;
02156         if ((!Connected) && (tx!=Width-1)) Connected = ((pA[Pixel+1] & BitMask) !=0);
02157         if ((!Connected) && (Pixel+Width<Size)) Connected = ((pA[Pixel+Width] & BitMask) !=0);
02158         if ((!Connected) && (tx!=Width-1) && (Pixel+Width+1<Size)) Connected = ((pA[Pixel+Width+1] & BitMask) !=0);
02159         if ((!Connected) && (tx!=0) && (Pixel+Width-1<Size)) Connected = ((pA[Pixel+Width-1] & BitMask) !=0);
02160         if (!Connected) Pixel++;
02161 
02162     } while (!Connected);
02163 
02164 
02165     return TRUE;
02166 }
02167 
02168 /********************************************************************************************
02169 
02170 >   BOOL BfxALU::ScanThreshold(INT32 Value, INT32 * X, INT32 * Y, INT32 * pPixel, BOOL * Found, BOOL CheckConnected=FALSE)
02171                     
02172     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
02173     Created:    27/10/94
02174     Inputs:     Value = the threshold to look for
02175                 *X = the start X position or NULL
02176                 *Y = the start Y position or NULL
02177                 *pPixel = the start pixel position (takes priority over X & Y) or NULL
02178                 CheckConnected = TRUE to check at least one connected bit is also set
02179     Outputs:    *X = the end X position or 0 if none found
02180                 *Y = the end Y position or 0 if none found
02181                 *pPixel = the end pixel position or 0 if none found
02182                 *Found = TRUE if found a pixel such that (A & BitMask) is non zero
02183     Returns:    TRUE if succeeded, FALSE & error set if not
02184     Purpose:    Arithemtic operation to search A for the next pixel s.t. (A & BitMask) !=0
02185     Errors:     Error 2 & 3 from called routines
02186     Scope:      Public
02187     SeeAlso:    TraceControl::FindInitialArea
02188 
02189 ********************************************************************************************/
02190 
02191 BOOL BfxALU::ScanThreshold(INT32 Value, INT32 * X, INT32 * Y, INT32 *pPixel, BOOL * Found, BOOL CheckConnected)
02192 {
02193     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
02194     ERROR2IF( ((!B) || (B->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
02195     ERROR3IF( (!(B->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
02196     ERROR2IF( ((!T) || (T->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
02197     ERROR3IF( (!(T->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
02198 
02199     BITMAPINFOHEADER * pBBMI=&(((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader);
02200     BITMAPINFOHEADER * pTBMI=&(((CWxBitmap *)(T->ActualBitmap))->BMInfo->bmiHeader);
02201 
02202     ERROR2IF((pBBMI->biBitCount != pTBMI->biBitCount), FALSE,"Bad BfxALU B reg");
02203     ERROR2IF( (pTBMI->biSizeImage != pBBMI->biSizeImage), FALSE,
02204               "Incompatible bitmaps for ScanThreshold");
02205 
02206     switch (pTBMI->biBitCount)
02207     {
02208         case 32:
02209         {
02210 
02211             AluPix32 * pB = (AluPix32 *)(void *)(((CWxBitmap *)(B->ActualBitmap))->BMBytes);
02212             AluPix32 * pT = (AluPix32 *)(void *)(((CWxBitmap *)(T->ActualBitmap))->BMBytes);
02213     
02214             ERROR3IF((sizeof(DWORD) != sizeof(AluPix32)), "OK who's broken AluPix32 not to be 32 bits");
02215 
02216             INT32 Width = pBBMI->biWidth;
02217             INT32 Size = (pBBMI->biSizeImage)>>2;
02218     
02219             INT32 Pixel = 0;
02220             BOOL Connected = TRUE;
02221             if (pPixel) Pixel=*pPixel; else if (X && Y) Pixel=(*X)+(*Y)*Width;
02222             INT32 tx;
02223             INT32 ty;
02224             INT32 tp;
02225 
02226 #define __scanthresh(p) (( IntegerSquare( ((INT32)(pB[p].R)) - ((INT32)(pT[p].R))) \
02227                           + IntegerSquare( ((INT32)(pB[p].G)) - ((INT32)(pT[p].G))) \
02228                           + IntegerSquare( ((INT32)(pB[p].B)) - ((INT32)(pT[p].B)))) >= Value )
02229 
02230             do
02231             {
02232 
02233 #ifdef FASTSCANTHRESHOLD
02234                 if (Pixel<Size) FastScanThreshold((DWORD *)(void *)pB, (DWORD *)(void *)pT, Size, Value, &Pixel);
02235 #else   
02236                 while (Pixel<Size && !__scanthresh(Pixel)) Pixel++;
02237 #endif
02238 
02239                 if (Pixel>=Size)
02240                 {
02241                     if (X) *X=0;
02242                     if (Y) *Y=0;
02243                     if (pPixel) *pPixel=0;
02244                     if (Found) *Found=FALSE;
02245                     return TRUE;
02246                 }
02247                 tx=Pixel % Width;
02248                 ty=Pixel / Width;
02249                 if (pPixel) *pPixel=Pixel;
02250                 if (X) *X=tx;
02251                 if (Y) *Y=ty;
02252                 if (Found) *Found=TRUE;
02253 
02254                 if ((Connected = /*assign*/ !CheckConnected) != FALSE) return TRUE;
02255                 if ((!Connected) && (tx!=Width-1)) {tp=Pixel+1;Connected = __scanthresh(tp);}
02256                 if ((!Connected) && (Pixel+Width<Size)) {tp=Pixel+Width;Connected = __scanthresh(tp);}
02257                 if ((!Connected) && (tx!=Width-1) && (Pixel+Width+1<Size)) {tp=Pixel+Width+1;Connected = __scanthresh(tp);}
02258                 if ((!Connected) && (tx!=0) && (Pixel+Width-1<Size)) {tp=Pixel+Width-1;Connected = __scanthresh(tp);}
02259                 if (!Connected) Pixel++;
02260 
02261             } while (!Connected);
02262             return TRUE;
02263         }
02264 
02265         case 8:
02266         {
02267 
02268             BYTE * pB = (BYTE *)(void *)(((CWxBitmap *)(B->ActualBitmap))->BMBytes);
02269             BYTE * pT = (BYTE *)(void *)(((CWxBitmap *)(T->ActualBitmap))->BMBytes);
02270     
02271             ERROR3IF((sizeof(DWORD) != sizeof(AluPix32)), "OK who's broken AluPix32 not to be 32 bits");
02272 
02273             INT32 Width = pBBMI->biWidth;
02274             INT32 Size = pBBMI->biSizeImage;
02275     
02276             INT32 Pixel = 0;
02277             BOOL Connected = TRUE;
02278             INT32 WidthR = (Width+3) & ~3;
02279             if (pPixel) Pixel=*pPixel; else if (X && Y) Pixel=(*X)+(*Y)*WidthR;
02280             INT32 tx = Pixel % WidthR;
02281             INT32 ty = Pixel / WidthR;
02282             INT32 tp;
02283 
02284 #define __scanthresh8(p) (pB[p]!=pT[p])
02285 
02286             do
02287             {
02288 
02289 #ifdef FASTSCANTHRESHOLD8
02290                 if (Pixel<Size) FastScanThreshold8((DWORD *)(void *)pB, (DWORD *)(void *)pT, Size, Value, &Pixel,
02291                                                    Width, WidthR, &tx, &ty);
02292 #else   
02293                 while (Pixel<Size && (tx>=Width || !__scanthresh8(Pixel)))
02294                 {
02295                     Pixel++;
02296                     if ((++tx)>=WidthR)
02297                     {
02298                         ty++;
02299                         tx=0;
02300                     }
02301                 }
02302 #endif
02303 
02304                 if (Pixel>=Size)
02305                 {
02306                     if (X) *X=0;
02307                     if (Y) *Y=0;
02308                     if (pPixel) *pPixel=0;
02309                     if (Found) *Found=FALSE;
02310                     return TRUE;
02311                 }
02312                 if (pPixel) *pPixel=Pixel;
02313                 if (X) *X=tx;
02314                 if (Y) *Y=ty;
02315                 if (Found) *Found=TRUE;
02316 
02317                 if ((Connected = /*assign*/ !CheckConnected) != FALSE) return TRUE;
02318                 if ((!Connected) && (tx!=Width-1)) {tp=Pixel+1;Connected = __scanthresh8(tp);}
02319                 if ((!Connected) && (Pixel+WidthR<Size)) {tp=Pixel+WidthR;Connected = __scanthresh8(tp);}
02320                 if ((!Connected) && (tx!=Width-1) && (Pixel+WidthR+1<Size)) {tp=Pixel+WidthR+1;Connected = __scanthresh8(tp);}
02321                 if ((!Connected) && (tx!=0) && (Pixel+WidthR-1<Size)) {tp=Pixel+WidthR-1;Connected = __scanthresh8(tp);}
02322                 if (!Connected)
02323                 {
02324                     Pixel++;
02325                     if ((++tx)>=WidthR)
02326                     {
02327                         ty++;
02328                         tx=0;
02329                     }
02330                 }
02331             } while (!Connected);
02332             return TRUE;
02333         }
02334 
02335         case 1:
02336         {
02337 
02338             BYTE * pB = (BYTE *)(void *)(((CWxBitmap *)(B->ActualBitmap))->BMBytes);
02339             BYTE * pT = (BYTE *)(void *)(((CWxBitmap *)(T->ActualBitmap))->BMBytes);
02340     
02341             ERROR3IF((sizeof(DWORD) != sizeof(AluPix32)), "OK who's broken AluPix32 not to be 32 bits");
02342 
02343             INT32 Width = pBBMI->biWidth;
02344             INT32 Size = pBBMI->biSizeImage<<3;
02345     
02346             INT32 Pixel = 0;
02347             BOOL Connected = TRUE;
02348             INT32 WidthR = (Width+31) & ~31;
02349             if (pPixel) Pixel=*pPixel; else if (X && Y) Pixel=(*X)+(*Y)*WidthR;
02350             INT32 tx = Pixel % WidthR;
02351             INT32 ty = Pixel / WidthR;
02352             INT32 tp;
02353 
02354 #define __scanthresh1(p) (((pB[p>>3]^pT[p>>3]) & (0x80>>(p&7))) !=0)
02355 
02356             do
02357             {
02358 
02359 #ifdef FASTSCANTHRESHOLD1
02360                 if (Pixel<Size) FastScanThreshold1((DWORD *)(void *)pB, (DWORD *)(void *)pT, Size, Value, &Pixel);
02361 #else   
02362                 while (Pixel<Size && (tx>=Width || !__scanthresh1(Pixel)))
02363                 {
02364                     Pixel++;
02365                     if ((++tx)>=WidthR)
02366                     {
02367                         ty++;
02368                         tx=0;
02369                     }
02370                 }
02371 #endif
02372 
02373                 if (Pixel>=Size)
02374                 {
02375                     if (X) *X=0;
02376                     if (Y) *Y=0;
02377                     if (pPixel) *pPixel=0;
02378                     if (Found) *Found=FALSE;
02379                     return TRUE;
02380                 }
02381                 if (pPixel) *pPixel=Pixel;
02382                 if (X) *X=tx;
02383                 if (Y) *Y=ty;
02384                 if (Found) *Found=TRUE;
02385 
02386                 if ((Connected = /*assign*/ !CheckConnected) != FALSE) return TRUE;
02387                 if ((!Connected) && (tx!=Width-1)) {tp=Pixel+1;Connected = __scanthresh1(tp);}
02388                 if ((!Connected) && (Pixel+WidthR<Size)) {tp=Pixel+WidthR;Connected = __scanthresh1(tp);}
02389                 if ((!Connected) && (tx!=Width-1) && (Pixel+WidthR+1<Size)) {tp=Pixel+WidthR+1;Connected = __scanthresh1(tp);}
02390                 if ((!Connected) && (tx!=0) && (Pixel+WidthR-1<Size)) {tp=Pixel+WidthR-1;Connected = __scanthresh1(tp);}
02391                 if (!Connected)
02392                 {
02393                     Pixel++;
02394                     if ((++tx)>=WidthR)
02395                     {
02396                         ty++;
02397                         tx=0;
02398                     }
02399                 }
02400             } while (!Connected);
02401             return TRUE;
02402         }
02403 
02404         default: break;
02405     }
02406     ERROR2(FALSE, "BfxALU::ScanThreshold doesn't understand that BPP");
02407     return TRUE; // shouldn't get here
02408 }
02409 
02410 
02411 /********************************************************************************************
02412 
02413 >   BOOL BfxALU::GradFillPath(Path * ThePath, DWORD StartColour, DWORD EndColour,
02414                               INT32 StartX, INT32 StartY, INT32 EndX, INT32 EndY, BOOL Antialias=FALSE,
02415                               BOOL ColoursAreDWORDs = FALSE)
02416                     
02417     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
02418     Created:    26/01/95
02419     Inputs:     ThePath = pointer to path to plot or NULL for whole thing
02420                 StartColour = COLORREF of start col
02421                 EndColour = COLORREF of end colour
02422                 {Start,End}{x,y} = coords of grad fill
02423                 AntiAlias = TRUE for antialiasing
02424                 ColoursAreDWORDS = TRUE to treat the colours as memory values to be replicated
02425                                    rather than disguised COLORREFs
02426     Outputs:    Accumulator altered
02427     Returns:    TRUE if succeeded, FALSE & error set if not
02428     Purpose:    Calls GDraw to fill a path
02429     Errors:     Error 2 if init hasn't been called or GDraw fails
02430                 Error 3 if windows and some other Oil layer are stangely mixed...
02431     Scope:      Protected
02432     SeeAlso:    -
02433 
02434 The path is rendered grad filled into the accumulator
02435 
02436 NOTE! The coordinates passed to this routine, both in the parh and as the grad fill end points,
02437 are all 24.8 values (secretly), i.e. StartX=256 plots from pixel 1.
02438 
02439 ********************************************************************************************/
02440 
02441 BOOL BfxALU::GradFillPath(Path * ThePath, DWORD StartColour, DWORD EndColour,
02442                               INT32 StartX, INT32 StartY, INT32 EndX, INT32 EndY, BOOL AntiAlias, BOOL ColoursAreDWORDs)
02443 {
02444     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
02445     ERROR2IF( ((!A) || (A->ActualBitmap==NULL)),FALSE,"BfxALU can't find OIL bitmap");
02446     ERROR3IF( (!(A->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
02447     BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
02448 
02449     DWORD Style=0;
02450     GraduationTable Table;
02451     Table.Length = 0x100;                                   // set up small one
02452 
02453     if (StartColour != EndColour)
02454     {
02455         ERROR2IF(ColoursAreDWORDs, FALSE, "Grad fill DWORD colours not yet supported");
02456 
02457         ERROR2IF((!GC->BuildGraduationTable( (COLORREF) StartColour, (COLORREF) EndColour, FALSE, &Table)), FALSE,
02458                     "GDraw couldn't build grad fill table for BfxALU");
02459 
02460         // convert ArtWorks style attribute into Gavin-style
02461         POINT A,B,C;
02462 
02463         A.x = StartX;   A.y = StartY;
02464         C.x = EndX;     C.y = EndY;
02465         B.x = A.x + (C.y-A.y);                          // make 3 points into a rotated square
02466         B.y = A.y - (C.x-A.x);
02467 
02468         ERROR2IF((!GC->SetGraduation( Style, &Table, &A, &B, &C )), FALSE, "GDraw couldn't set BfxALU graduation");
02469     }
02470     else
02471     {
02472         if (ColoursAreDWORDs)
02473         {
02474             DWORD DupColour=StartColour;
02475             switch(pBMI->biBitCount)
02476             {
02477                 case 32: DupColour=StartColour; break;
02478                 case 16: DupColour=(StartColour & 0xFFFF); DupColour|=DupColour<<16; break;
02479                 case 8:  DupColour=(StartColour & 0xFF); DupColour|=DupColour<<8; DupColour|=DupColour<<16; break;
02480                 case 4:  DupColour=(StartColour & 0xF); DupColour|=DupColour<<4; DupColour|=DupColour<<8;
02481                                                         DupColour|=DupColour<<16; break;
02482                 case 2:  DupColour=(StartColour & 0x3); DupColour|=DupColour<<2; DupColour|=DupColour<<4;
02483                                                         DupColour|=DupColour<<8; DupColour|=DupColour<<16; break;
02484                 case 1:  DupColour=(StartColour & 0x1); DupColour|=DupColour<<1; DupColour|=DupColour<<2;
02485                                                         DupColour|=DupColour<<4; DupColour|=DupColour<<8;
02486                                                         DupColour|=DupColour<<16; break;
02487                 default:
02488                 {
02489                     ERROR2(FALSE, "Corrupt biBitCount in BfxALU::GradFillPath");
02490                     break;
02491                 }
02492             }
02493 
02494             ERROR2IF((!GC->SetWordColour(DupColour )), FALSE, "GDraw couldn't set BfxALU word colour");
02495         }
02496         else
02497         {
02498             ERROR2IF((!GC->SetColour( (COLORREF) StartColour )), FALSE, "GDraw couldn't set BfxALU colour");
02499         }
02500     }
02501 
02502     GMATRIX pathmatrix;
02503     pathmatrix.AX=pathmatrix.BY=1<<(FX+8);pathmatrix.CX=pathmatrix.CY=pathmatrix.AY=pathmatrix.BX=0;
02504     ERROR2IF((!GC->SetMatrix(&pathmatrix)), FALSE, "GDraw couldn't set path matrix");
02505     GC->SetAntialiasFlag(AntiAlias); // Grrr void
02506     GC->SetFlatness(AntiAlias?32:128); // 128 is half a pixel. This is a void fn;  grrr...
02507 
02508     BOOL Success;
02509     if (ThePath)
02510     {
02511         Success = GC->FillPath( (POINT*)ThePath->GetCoordArray(), ThePath->GetVerbArray(), ThePath->GetNumCoords(), 0);
02512     }
02513     else
02514     {
02515         RECT Rect={/*L*/0,/*T*/(pBMI->biHeight)<<8,/*R*/(pBMI->biWidth)<<8,/*B*/0};
02516         Success = GC->FillRectangle(&Rect);
02517     }
02518 
02519     GC->SetAntialiasFlag(FALSE); // Grrr void
02520     ERROR2IF(!(GC->SetMatrix(&identity)), FALSE, "GDraw couldn't restore BfxALU Matrix");
02521     ERROR2IF((!Success), FALSE, "GDraw couldn't fill BfxALU path");
02522     
02523     return(TRUE);
02524 }
02525 
02526 /********************************************************************************************
02527 
02528 >   BOOL BfxALU::GetStatistics(Path * ThePath, KernelStatistics * pStats)
02529                     
02530     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
02531     Created:    26/01/95
02532     Inputs:     ThePath = the path to do
02533     Outputs:    pStats filled in
02534     Returns:    TRUE if succeeded, FALSE & error set if not
02535     Purpose:    Calls GDraw to statistically analyse the contents of a path
02536     Errors:     Error 2 if init hasn't been called or GDraw fails
02537                 Error 3 if windows and some other Oil layer are stangely mixed...
02538     Scope:      Protected
02539     SeeAlso:    -
02540 
02541 NOTE! The coordinates passed to this routine, both in the parh and as the grad fill end points,
02542 are all 24.8 values (secretly), i.e. StartX=256 plots from pixel 1.
02543 
02544 ********************************************************************************************/
02545 
02546 BOOL BfxALU::GetStatistics(Path * ThePath, KernelStatistics * pStats)
02547 {
02548     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
02549     ERROR2IF( ((!A) || (A->ActualBitmap==NULL)),FALSE,"BfxALU can't find OIL bitmap");
02550     ERROR3IF( (!(A->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
02551     BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
02552 
02553     GMATRIX pathmatrix;
02554     pathmatrix.AX=pathmatrix.BY=1<<(FX+8);pathmatrix.CX=pathmatrix.CY=pathmatrix.AY=pathmatrix.BX=0;
02555     ERROR2IF((!GC->SetMatrix(&pathmatrix)), FALSE, "GDraw couldn't set path matrix");
02556     GC->SetFlatness(128); // 128 is half a pixel. This is a void fn;  grrr...
02557     STATISTICS Stats;
02558     BOOL Success = GC->GetStatistics( (POINT*)ThePath->GetCoordArray(), ThePath->GetVerbArray(), ThePath->GetNumCoords(),
02559                                       0, &Stats);
02560     ERROR2IF((!GC->SetMatrix(&identity)), FALSE, "GDraw couldn't restore BfxALU Matrix");
02561     ERROR2IF((!Success), FALSE, "GDraw couldn't fill BfxALU path");
02562 
02563     pStats->N = Stats.N;
02564     double N = (double) Stats.N;
02565     if (N==0) N=1;
02566 #if 1
02567     pStats->R = ((Stats.R )*1.0)/(N*255.0);
02568     pStats->R2= ((Stats.R2)*1.0)/(N*255.0*255.0);
02569     pStats->RX= ((Stats.RX)*1.0)/(N*255.0);
02570     pStats->RY= ((Stats.RY)*1.0)/(N*255.0);
02571     pStats->G = ((Stats.G )*1.0)/(N*255.0);
02572     pStats->G2= ((Stats.G2)*1.0)/(N*255.0*255.0);
02573     pStats->GX= ((Stats.GX)*1.0)/(N*255.0);
02574     pStats->GY= ((Stats.GY)*1.0)/(N*255.0);
02575     pStats->B = ((Stats.B )*1.0)/(N*255.0);
02576     pStats->B2= ((Stats.B2)*1.0)/(N*255.0*255.0);
02577     pStats->BX= ((Stats.BX)*1.0)/(N*255.0);
02578     pStats->BY= ((Stats.BY)*1.0)/(N*255.0);
02579     pStats->X = ((Stats.X )*1.0)/(N*255.0);
02580     pStats->Y = ((Stats.Y )*1.0)/(N*255.0);
02581     pStats->X2= ((Stats.X2)*1.0)/(N*255.0);
02582     pStats->Y2= ((Stats.Y2)*1.0)/(N*255.0);
02583     pStats->XY= ((Stats.XY)*1.0)/(N*255.0);
02584 //  pStats->Pixel = (DWORD)(Stats.C);
02585 #else
02586     pStats->R = ((Stats.R ).MakeDouble())/(N*255.0);
02587     pStats->R2= ((Stats.R2).MakeDouble())/(N*255.0*255.0);
02588     pStats->RX= ((Stats.RX).MakeDouble())/(N*255.0);
02589     pStats->RY= ((Stats.RY).MakeDouble())/(N*255.0);
02590     pStats->G = ((Stats.G ).MakeDouble())/(N*255.0);
02591     pStats->G2= ((Stats.G2).MakeDouble())/(N*255.0*255.0);
02592     pStats->GX= ((Stats.GX).MakeDouble())/(N*255.0);
02593     pStats->GY= ((Stats.GY).MakeDouble())/(N*255.0);
02594     pStats->B = ((Stats.B ).MakeDouble())/(N*255.0);
02595     pStats->B2= ((Stats.B2).MakeDouble())/(N*255.0*255.0);
02596     pStats->BX= ((Stats.BX).MakeDouble())/(N*255.0);
02597     pStats->BY= ((Stats.BY).MakeDouble())/(N*255.0);
02598     pStats->X = ((Stats.X ).MakeDouble())/(N*255.0);
02599     pStats->Y = ((Stats.Y ).MakeDouble())/(N*255.0);
02600     pStats->X2= ((Stats.X2).MakeDouble())/(N*255.0);
02601     pStats->Y2= ((Stats.Y2).MakeDouble())/(N*255.0);
02602     pStats->XY= ((Stats.XY).MakeDouble())/(N*255.0);
02603 #endif
02604 
02605     INT32 Width = pBMI->biWidth;
02606         
02607     pStats->LowX = -1;
02608     pStats->LowY = -1;
02609     pStats->Pixel = (DWORD)(-1);
02610 
02611     if (Stats.C>0)
02612     {
02613         UINT32 Offset = ((UINT_PTR)(Stats.C))-((UINT_PTR)((((CWxBitmap *)(A->ActualBitmap))->BMBytes)));
02614         if (Offset<(UINT32)pBMI->biSizeImage)
02615         {
02616             pStats->LowX = (Offset>>2) % Width;
02617             pStats->LowY = (Offset>>2) / Width;
02618             DWORD pval = *((DWORD *)(Stats.C));
02619             pStats->Pixel = (pval & 0x00FF00) | ((pval >> 16) & 0xFF) | ((pval << 16) & 0xFF0000);
02620         }
02621     }
02622 
02623     return(TRUE);
02624 }
02625 
02626 
02627 /********************************************************************************************
02628 
02629 >   BOOL BfxALU::GetSize(KernelBitmap * pBitmap, INT32 * pXSize, INT32 * pYSize, INT32 * pDepth)
02630 
02631                     
02632     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
02633     Created:    26/01/95
02634     Inputs:     pBitmap
02635     Outputs:    pXSize (if non NULL) contains X size,
02636                 pYSize (if non NULL) contains Y size,
02637                 pDepth (if non NULL) contains Depth ,
02638     Returns:    TRUE if succeeded, FALSE & error set if not
02639     Purpose:    Convenient place to overcome the inadequacies of the KernelBitmapClass
02640     Errors:     Error 2 if init hasn't been called or GDraw fails
02641                 Error 3 if windows and some other Oil layer are stangely mixed...
02642     Scope:      Protected
02643     SeeAlso:    -
02644 
02645 The non NULL pointers are filled in with the appropriate items
02646 
02647 ********************************************************************************************/
02648 
02649 BOOL BfxALU::GetSize(KernelBitmap * pBitmap, INT32 * pXSize, INT32 * pYSize, INT32 * pDepth)
02650 {
02651     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
02652     ERROR2IF( ((!pBitmap) || (pBitmap->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
02653     ERROR3IF( (!(pBitmap->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
02654 
02655     BITMAPINFOHEADER * pABMI=&(((CWxBitmap *)(pBitmap->ActualBitmap))->BMInfo->bmiHeader);
02656 
02657     if (pXSize) *pXSize=(INT32)(pABMI->biWidth);
02658     if (pYSize) *pYSize=(INT32)(pABMI->biHeight);
02659     if (pDepth) *pDepth=(INT32)(pABMI->biBitCount);
02660 
02661     return TRUE;
02662 }
02663 
02664 /********************************************************************************************
02665 
02666 >   BOOL BfxALU::ByteCopyBA()
02667                     
02668     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
02669     Created:    27/01/95
02670     Inputs:     None
02671     Outputs:    Accumulator altered
02672     Returns:    TRUE if succeeded, FALSE & error set if not
02673     Purpose:    Copies B into the accumulator
02674     Errors:     Error 2 if init hasn't been called or GDraw fails
02675                 Error 3 if windows and some other Oil layer are stangely mixed...
02676     Scope:      Protected
02677     SeeAlso:    -
02678 
02679 The bitmaps must be identical in dimension and depth - this is a bytewise copy.
02680 
02681 ********************************************************************************************/
02682 
02683 BOOL BfxALU::ByteCopyBA()
02684 {
02685     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
02686     ERROR2IF( ((!A) || (A->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
02687     ERROR3IF( (!(A->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
02688     ERROR2IF( ((!B) || (B->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
02689     ERROR3IF( (!(B->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
02690 
02691     BITMAPINFOHEADER * pABMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
02692     BITMAPINFOHEADER * pBBMI=&(((CWxBitmap *)(A->ActualBitmap))->BMInfo->bmiHeader);
02693 
02694     ERROR2IF((pABMI->biBitCount != pBBMI->biBitCount), FALSE,"Bad BfxALU A/B reg");
02695     ERROR2IF( (pABMI->biSizeImage != pBBMI->biSizeImage), FALSE,
02696               "Incompatible bitmaps for ByteCopyBA()");
02697     
02698     void * pA = (void *)(((CWxBitmap *)(A->ActualBitmap))->BMBytes);
02699     void * pB = (void *)(((CWxBitmap *)(B->ActualBitmap))->BMBytes);
02700 
02701     memcpy(pA, pB, pABMI->biSizeImage);
02702 
02703     return TRUE;
02704 }
02705 
02706 /********************************************************************************************
02707 
02708 >   BfxErrorRegionList::BfxErrorRegionList()
02709                     
02710     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
02711     Created:    01/02/95
02712     Inputs:     None
02713     Outputs:    Constructs object
02714     Returns:    Nothing
02715     Purpose:    Default constructor for ALU
02716     Errors:     None yet
02717     SeeAlso:    -
02718 
02719 This constructs the error region list - most of the work is done in the Init function
02720 
02721 ********************************************************************************************/
02722 
02723 BfxErrorRegionList::BfxErrorRegionList()
02724 {
02725     pList = NULL;
02726     ListLength = 0;
02727     Used = 0;
02728     CurrentRead = 0;
02729     CurrentWrite = 0;
02730     Sorted = FALSE;
02731 }
02732 
02733 /********************************************************************************************
02734 
02735 >   BfxErrorRegionList::~BfxErrorRegionList()
02736                     
02737     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
02738     Created:    01/02/95
02739     Inputs:     None
02740     Outputs:    Constructs object
02741     Returns:    Nothing
02742     Purpose:    Default constructor for ALU
02743     Errors:     Error3 if DeInit hasn't been called.
02744     SeeAlso:    -
02745 
02746 This destructs the region list freeing memory if appropriate
02747 
02748 ********************************************************************************************/
02749 
02750 BfxErrorRegionList::~BfxErrorRegionList()
02751 {
02752     if (pList) CCFree(pList);
02753 }
02754 
02755 /********************************************************************************************
02756 
02757 >   BOOL BfxErrorRegionList::Init(UINT32 Length)
02758                     
02759     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
02760     Created:    01/02/95
02761     Inputs:     Length = no. of items that should go into list
02762     Outputs:    None
02763     Returns:    TRUE if succeeds else FALSE & error set
02764     Purpose:    Default constructor for ALU
02765     Errors:     Memory
02766     SeeAlso:    -
02767 
02768 This claims the memory for the region list. You cna init it to 0 to remove the memory.
02769 
02770 ********************************************************************************************/
02771 
02772 BOOL BfxErrorRegionList::Init(UINT32 Length)
02773 {
02774     if (pList) CCFree(pList);
02775     pList = NULL;
02776     ListLength = 0;
02777     Used = 0;
02778     CurrentRead = 0;
02779     CurrentWrite = 0;
02780     Sorted = FALSE;
02781 
02782     if (!Length) return TRUE;
02783 
02784     if ((pList = /*assign*/ (BfxErrorRegionListItem *)CCMalloc(sizeof(BfxErrorRegionListItem) * (Length+1))) == NULL)
02785         return FALSE;
02786 
02787     ListLength = Length;
02788     
02789     return (Empty() && ResetRead());
02790 }
02791 
02792 /********************************************************************************************
02793 
02794 >   BOOL BfxErrorRegionList::Empty()
02795                     
02796     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
02797     Created:    01/02/95
02798     Inputs:     None
02799     Outputs:    None
02800     Returns:    TRUE if succeeds else FALSE & error set
02801     Purpose:    Empties the list
02802     Errors:     Memory
02803     SeeAlso:    -
02804 
02805 This empties the list
02806 
02807 ********************************************************************************************/
02808 
02809 BOOL BfxErrorRegionList::Empty()
02810 {
02811     ERROR2IF (!pList, FALSE, "No BfxErrorRegionList");
02812     CurrentRead = 0;
02813     CurrentWrite = 0;
02814     Sorted = FALSE;
02815 
02816     pList[CurrentWrite].X=pList[CurrentWrite].Y=pList[CurrentWrite].Area = 0;
02817 
02818     return TRUE;
02819 }
02820 
02821 /********************************************************************************************
02822 
02823 >   BOOL BfxErrorRegionList::ResetRead()
02824                     
02825     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
02826     Created:    01/02/95
02827     Inputs:     None
02828     Outputs:    None
02829     Returns:    TRUE if succeeds else FALSE & error set
02830     Purpose:    Resets the read pointer
02831     Errors:     Memory
02832     SeeAlso:    -
02833 
02834 ********************************************************************************************/
02835 
02836 BOOL BfxErrorRegionList::ResetRead()
02837 {
02838     CurrentRead = 0;
02839     return TRUE;
02840 }
02841 
02842 /********************************************************************************************
02843 
02844 >   BOOL BfxErrorRegionList::Insert(INT32 XCoord, INT32 YCoord, INT32 Area)
02845                     
02846     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
02847     Created:    01/02/95
02848     Inputs:     XCoord, YCoord & Area = the number of the 
02849     Outputs:    None
02850     Returns:    TRUE if succeeds else FALSE & error set
02851     Purpose:    Inserts an item into the list
02852     Errors:     Memory
02853     SeeAlso:    -
02854 
02855 This empties the list
02856 
02857 ********************************************************************************************/
02858 
02859 BOOL BfxErrorRegionList::Insert(INT32 XCoord, INT32 YCoord, INT32 Area)
02860 {
02861     ERROR2IF (!pList, FALSE, "No BfxErrorRegionList");
02862     ERROR2IF (!IsSpace(), FALSE, "It's full! Why not use IsSpace() first like a good programmer?");
02863     ERROR2IF (!Area, FALSE, "BfxErrorRegionLists cannot hold zero area regions coz they aren't really regions, are they?");
02864 
02865     pList[CurrentWrite].X=XCoord;
02866     pList[CurrentWrite].Y=YCoord;
02867     pList[CurrentWrite++].Area=Area;
02868     pList[CurrentWrite].Area=0;
02869     pList[CurrentWrite].X=0;
02870     pList[CurrentWrite].Y=0;
02871 
02872     return TRUE;
02873 }
02874 
02875 /********************************************************************************************
02876 
02877 >   BOOL BfxErrorRegionList::Sort()
02878                     
02879     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
02880     Created:    01/02/95
02881     Inputs:     None
02882     Outputs:    None
02883     Returns:    TRUE if succeeds else FALSE & error set
02884     Purpose:    Sorts the list
02885     Errors:     Memory
02886     SeeAlso:    -
02887 
02888 SSSSLLLLOOOOOWWWW sort. But never mind.
02889 
02890 ********************************************************************************************/
02891 
02892 
02893 BOOL BfxErrorRegionList::Sort()
02894 {
02895     ERROR2IF (!pList, FALSE, "No BfxErrorRegionList");
02896     Sorted = FALSE;
02897 
02898     // Handle special cases
02899     if ((pList[0].Area == 0) || (pList[1].Area ==0))
02900     {
02901         Sorted = TRUE;
02902         return TRUE;
02903     }
02904     
02905     while (!Sorted)
02906     {
02907         INT32 Current = 0;
02908         Sorted = TRUE;
02909         while (pList[++Current].Area !=0) if (pList[Current].Area > pList[Current-1].Area)
02910         {   
02911             Sorted=FALSE;
02912             Swap(&pList[Current], &pList[Current-1]);
02913         }
02914     }
02915     return TRUE;
02916 }
02917 
02918 /********************************************************************************************
02919 
02920 >   BOOL BfxErrorRegionList::GetCurrent(INT32 * XCoord, INT32 * YCoord, INT32 * Area)
02921                     
02922     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
02923     Created:    01/02/95
02924     Inputs:     None
02925     Outputs:    None
02926     Returns:    TRUE if is an item, else FALSE
02927     Purpose:    gets items from list
02928     Errors:     None
02929     SeeAlso:    -
02930 
02931 This function returns FALSE at the end of a list (NOT to indicate an error condition)
02932 
02933 ********************************************************************************************/
02934 
02935 /* INLINE */
02936 
02937 PORTNOTE("other", "Disabled Accusoft filters")
02938 #ifndef EXCLUDE_FROM_XARALX
02939 #ifndef WEBSTER
02940 
02941 /********************************************************************************************
02942 
02943 >   BOOL BfxALU::MakeAccusoftHandle(INT32 * pHandle, BOOL DoBodge = FALSE)
02944                     
02945     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
02946     Created:    27/01/95
02947     Inputs:     DoBodge - tries to get round a bug in the Accusoft linear interpolation resize code
02948     Outputs:    *pHandle = Accusoft handle
02949     Returns:    TRUE if succeeded, FALSE & error set if not
02950     Purpose:    A new accusoft bitmap handle is created for the B reg
02951     Errors:     Error 2 if init hasn't been called or GDraw fails
02952                 Error 3 if windows and some other Oil layer are stangely mixed...
02953     Scope:      Public
02954     SeeAlso:    -
02955 
02956 This actually copies the bitmap. Note we'll have to fudge 32bit bmps somehow
02957 
02958 ********************************************************************************************/
02959 
02960 BOOL BfxALU::MakeAccusoftHandle(INT32 * pHandle, BOOL DoBodge)
02961 {
02962     ERROR1IF((!(AccusoftFilters::pfnIMG_create_handle_keep)), FALSE, _R(IDN_FILTERNOTPRESENT));
02963     ERROR2IF((!pHandle ),FALSE, "BfxALU handle parameter must be non-null");
02964 
02965     ERROR2IF((GC==NULL),FALSE,"BfxALU::Init not called / failed");
02966     ERROR2IF( ((!B) || (B->ActualBitmap==NULL)) ,FALSE,"BfxALU can't find OIL bitmap");
02967     ERROR3IF( (!(B->ActualBitmap->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap)) )),"BfxALU Oil layer inconsistency");
02968 
02969     BITMAPINFOHEADER * pBBMI=&(((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader);
02970 
02971     DWORD PaletteUsed = pBBMI->biClrUsed;
02972     
02973     ERROR2IF ((pBBMI->biSizeImage == 0) || (pBBMI->biCompression != BI_RGB) || (pBBMI->biHeight<0), FALSE, 
02974                 "A naughty DIB format has been used internally");
02975     
02976     // Handle wierd palette stuff
02977     if (pBBMI->biBitCount > 8)
02978     {
02979         PaletteUsed = 0;
02980     }
02981     else
02982     {
02983         // 0 is MS for maximum
02984 //Mark Howitt, 31/10/97. Set the PaletteUsed to the Bpp to ensure Accusoft filters don`t crash when using less
02985 //                       than the maximum number of colours for any given Bpp.
02986         ERROR3IF(pBBMI->biBitCount==0,"There`s no depth to this picture! Cannot set Palette Used!");
02987         switch(pBBMI->biBitCount)
02988         {
02989             case 1:
02990                 PaletteUsed = 2;    //Why bother? Just in case!
02991                 break;
02992             case 2:
02993                 PaletteUsed = 4;
02994                 break;
02995             case 4:
02996                 PaletteUsed = 16;
02997                 break;
02998             case 8:
02999                 PaletteUsed = 256;
03000                 break;
03001             default:
03002                 break;
03003         }
03004     }
03005 
03006     INT32 SizeImage = pBBMI->biSizeImage;
03007     INT32 Depth = 0;
03008     if (pBBMI->biBitCount == 32)
03009         Depth = 24;
03010     else
03011         Depth = pBBMI->biBitCount;
03012 #ifdef BODGE_ACCUSOFT_RESIZE
03013     if (DoBodge)
03014     {
03015         // Add some extra bodge pixels on the left hand side
03016         if (pBBMI->biBitCount == 32)
03017             SizeImage = DIBUtil::ScanlineSize(3 * pBBMI->biWidth, 24) * pBBMI->biHeight;
03018         else            
03019             SizeImage = DIBUtil::ScanlineSize(3 * pBBMI->biWidth, Depth) * pBBMI->biHeight;
03020     }
03021     else if (pBBMI->biBitCount == 32)
03022     {
03023         UINT32 ScanLineSize = DIBUtil::ScanlineSize(pBBMI->biWidth, 24);
03024         SizeImage = ScanLineSize * pBBMI->biHeight; 
03025     }
03026 #else
03027     if (pBBMI->biBitCount == 32)
03028     {
03029         UINT32 ScanLineSize = DIBUtil::ScanlineSize(pBBMI->biWidth, 24);
03030         SizeImage = ScanLineSize * pBBMI->biHeight; 
03031     }
03032 #endif
03033 
03034     HGLOBAL HMem = GlobalAlloc(GMEM_MOVEABLE, sizeof(BITMAPINFOHEADER) + (sizeof(DWORD)*PaletteUsed) + SizeImage);
03035     ERROR1IF(!HMem, FALSE, _R(IDS_OUT_OF_MEMORY));
03036     LPBYTE Mem = (LPBYTE) (void *) GlobalLock(HMem);
03037     ERROR1IF(!Mem, FALSE, _R(IDS_OUT_OF_MEMORY)); // wierd - we've only just got it!
03038 
03039     BITMAPINFOHEADER * pCBMI = (BITMAPINFOHEADER *) Mem;
03040     LPBYTE pPal = Mem + sizeof(BITMAPINFOHEADER);
03041     LPBYTE pBits = pPal + (sizeof(DWORD)*PaletteUsed);
03042 
03043     pCBMI->biSize = pBBMI->biSize;
03044     if (DoBodge)
03045         pCBMI->biWidth = pBBMI->biWidth * 3;
03046     else
03047         pCBMI->biWidth = pBBMI->biWidth;
03048     pCBMI->biHeight = pBBMI->biHeight;
03049     pCBMI->biPlanes = 1;
03050     pCBMI->biBitCount = (pBBMI->biBitCount != 32) ? (pBBMI->biBitCount) : 24;
03051     pCBMI->biCompression = BI_RGB;
03052     pCBMI->biSizeImage = SizeImage;
03053     pCBMI->biXPelsPerMeter = pBBMI->biXPelsPerMeter;
03054     pCBMI->biYPelsPerMeter = pBBMI->biYPelsPerMeter;
03055     if (PaletteUsed)
03056     {
03057         pCBMI->biClrUsed = PaletteUsed;
03058         pCBMI->biClrImportant = /*pBBMI->biClrImportant;*/PaletteUsed;
03059     }
03060     else
03061     {
03062         pCBMI->biClrUsed = 0;
03063         pCBMI->biClrImportant = 0;
03064     }
03065     
03066     // Copy the palette across
03067     if (PaletteUsed) memcpy(pPal /*dest*/, ((LPBYTE)(pBBMI)) + sizeof(BITMAPINFOHEADER), sizeof(DWORD) * PaletteUsed); 
03068 
03069 #ifdef BODGE_ACCUSOFT_RESIZE
03070     // Copy the main bitmap data across
03071     if (DoBodge)
03072     {
03073         LPBYTE pSourceBits = ((CWxBitmap *)(B->ActualBitmap))->BMBytes;
03074         if (!MAH_BodgeCopyBitmap(pBBMI->biWidth, pBBMI->biHeight, pBBMI->biBitCount, pSourceBits, pBits))
03075         {
03076             GlobalUnlock(HMem);
03077             GlobalFree(HMem);
03078             return FALSE;
03079         }
03080     }
03081     else
03082 #endif
03083     {
03084         if (pBBMI->biBitCount != 32)
03085         {
03086             memcpy(pBits /*dest*/, ((CWxBitmap *)(B->ActualBitmap))->BMBytes, pBBMI->biSizeImage);
03087         }
03088         else
03089         {
03090             GC->ConvertBitmap(pBBMI, ((CWxBitmap *)(B->ActualBitmap))->BMBytes, pCBMI, pBits, 8);
03091         }
03092     }
03093 
03094     if (pBBMI->biBitCount==1) FixMono(pBits, pBBMI->biSizeImage);
03095 
03096     INT32 result = AccusoftFilters::pfnIMG_create_handle_keep(pCBMI);
03097     if (result < 0)
03098     {
03099         GlobalUnlock(HMem);
03100         GlobalFree(HMem);
03101         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
03102     }
03103     *pHandle = result;
03104 
03105     return TRUE;
03106 }
03107 
03108 /********************************************************************************************
03109 
03110 >   BOOL BfxALU::MAH_BodgeCopyBitmap(INT32 Width, INT32 Height, INT32 Depth, LPBYTE pSourceBits, LPBYTE pDestBits)
03111                     
03112     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03113     Created:    20/09/96
03114     Inputs:     Width       - Width of bitmap
03115                 Height      - Height of bitmap
03116                 Depth       - ColourDepth of bitmap
03117                 pSourceBits - source data to use
03118                 pDestBits   - destination for the data
03119     Outputs:    None
03120     Returns:    TRUE if succeeded, FALSE & error set if not
03121     Purpose:    To copy the bitmap across to the destination but instead of doing a straight
03122                 copy we copy it to a bitmap which is three times the width and to the middle
03123                 section of this. We then pad the left hand side with the first left pixel.
03124                 We then pad the right hand side with the right hand pixel. 
03125     Assumes:    Destination bitmap is three times the width of the source but is the same
03126                 in all other aspects.
03127     SeeAlso:    MakeAccusoftHandle;
03128 
03129 ********************************************************************************************/
03130 
03131 BOOL BfxALU::MAH_BodgeCopyBitmap(INT32 Width, INT32 Height, INT32 Depth, LPBYTE pSourceBits, LPBYTE pDestBits)
03132 {
03133 #ifdef BODGE_ACCUSOFT_RESIZE
03134     UINT32 SourceScanline = DIBUtil::ScanlineSize(Width, Depth);
03135     UINT32 DestScanline = 1;
03136     if (Depth == 32)
03137         DestScanline = DIBUtil::ScanlineSize(Width * 3, 24);
03138     else
03139         DestScanline = DIBUtil::ScanlineSize(Width * 3, Depth);
03140 
03141     // We need to do it the hard way and copy it by hand
03142     // Repeat the first pixel in the extra bodged pixels on the left hand side
03143     // Copy the source bitmap to the centre section
03144     // Repeat the last pixel in the extra bodged pixels on the right hand side
03145     INT32 Bytes = 1;
03146     switch (Depth)
03147     {
03148         case 4:
03149         {
03150             // 2 pixels per byte
03151             // 4bpp so we must put the data into either the high or low nibble.
03152             // This will be dependent on whether we are on an odd or even pixel.
03153             // So test the LSBit of the current x, if set we will be odd.
03154             // Only move onto next byte every other pixel hence current x/2.
03155             Bytes = Width;
03156             for (INT32 i = 0; i < Height; i++ )
03157             {
03158                 // Probably not the most efficient way to copy the data but it is PROVEN!
03159                 BYTE * pDBits = pDestBits;
03160                 // Duplicate the left hand pixel into the first third
03161                 BYTE LeftHandByte = ((*pSourceBits) & 0xF0) >> 4;
03162                 for (INT32 j = 0; j < Width; j++ )
03163                 {
03164                     LPBYTE pData = pDBits + j/2;
03165                     if (j & 1)
03166                         *(pData) = ((*(pData)) & 0xF0) | (LeftHandByte & 0x0F); // add into low nibble 
03167                     else
03168                         *(pData) = ((*(pData)) & 0x0F) | ((LeftHandByte << 4) & 0xF0);  // add into top nibble
03169                 }               
03170 
03171                 BYTE Byte = 0;
03172                 INT32 k = 0;
03173                 for (; j < (2 * Width); j++ )
03174                 {
03175                     // Get the source pixel
03176                     LPBYTE pSourceData = pSourceBits + k/2;
03177                     if (k & 1)
03178                         Byte = ((*(pSourceData)) & 0x0F);   // get low nibble 
03179                     else
03180                         Byte = ((*(pSourceData)) & 0xF0) >> 4;  // get top nibble
03181                     
03182                     // Put it in the correct destination pixel
03183                     LPBYTE pData = pDBits + j/2;
03184                     if (j & 1)
03185                         *(pData) = ((*(pData)) & 0xF0) | (Byte & 0x0F); // add into low nibble 
03186                     else
03187                         *(pData) = ((*(pData)) & 0x0F) | ((Byte << 4) & 0xF0);  // add into top nibble
03188                     
03189                     k ++;
03190                 }
03191                 
03192                 // Duplicate the right hand pixel for the last third
03193                 LPBYTE pData = pDBits + Width/2;
03194                 BYTE RightHandByte = 0;
03195                 if (Width & 1)
03196                     RightHandByte = ((*(pData)) & 0x0F);    // get low nibble 
03197                 else
03198                     RightHandByte = ((*(pData)) & 0xF0) >> 4;   // get top nibble
03199 
03200                 for (; j < (3 * Width); j++ )
03201                 {
03202                     // Probably not the most efficient way but it is PROVEN!
03203                     LPBYTE pData = pDBits + j/2;
03204                     if (j & 1)
03205                     {
03206                         *(pData) = ((*(pData)) & 0xF0) | (RightHandByte & 0x0F);    // add into low nibble 
03207                     }
03208                     else
03209                         *(pData) = ((*(pData)) & 0x0F) | ((RightHandByte << 4) & 0xF0); // add into top nibble
03210                 }               
03211 
03212                 pDestBits += DestScanline;
03213                 pSourceBits += SourceScanline;
03214             }
03215 
03216             break;
03217         }
03218         case 8:
03219         {
03220             // 1 byte per pixel
03221             Bytes = Width;
03222             for (INT32 i = 0; i < Height; i++ )
03223             {
03224                 BYTE * pDBits = pDestBits;
03225                 // Duplicate the left hand pixel into the first third
03226                 BYTE LeftHandByte = *pSourceBits;
03227                 memset(pDBits, LeftHandByte, Bytes );
03228                 pDBits += Bytes;
03229                 // Copy the main centre section
03230                 memcpy(pDBits /*dest*/, pSourceBits, Bytes);
03231                 pDBits += Bytes;
03232                 // Duplicate the right hand pixel for the last third
03233                 BYTE RightHandByte = *(pSourceBits + Bytes - 1);
03234                 memset(pDBits, RightHandByte, Bytes );
03235 
03236                 pDestBits += DestScanline;
03237                 pSourceBits += SourceScanline;
03238             }
03239 
03240             break;
03241         }
03242         case 32:
03243         case 24:
03244         {
03245             // 3 bytes per pixel
03246             Bytes = 3 * Width;
03247             BYTE LeftHandByte_R     = 0;
03248             BYTE RightHandByte_R    = 0;
03249             BYTE LeftHandByte_G     = 0;
03250             BYTE RightHandByte_G    = 0;
03251             BYTE LeftHandByte_B     = 0;
03252             BYTE RightHandByte_B    = 0;
03253             for (INT32 i = 0; i < Height; i++ )
03254             {
03255                 BYTE * pDBits = pDestBits;
03256                 // Duplicate the left hand pixel into the first third
03257                 LeftHandByte_R = *pSourceBits;
03258                 LeftHandByte_G = *(pSourceBits + 1);
03259                 LeftHandByte_B = *(pSourceBits + 2);
03260                 for (INT32 j = 0; j < Width; j++ )
03261                 {
03262                     *pDBits = LeftHandByte_R;
03263                     pDBits ++;
03264                     *pDBits = LeftHandByte_G;
03265                     pDBits ++;
03266                     *pDBits = LeftHandByte_B;
03267                     pDBits ++;
03268                 }
03269                 
03270                 // Copy the main centre section
03271                 if (Depth != 32)
03272                 {
03273                     memcpy(pDBits /*dest*/, pSourceBits, Bytes);
03274                     pDBits += Bytes;
03275                 }
03276                 else
03277                 {
03278                     LPBYTE pSBits = pSourceBits;
03279                     for (INT32 j = 0; j < Width; j++ )
03280                     {
03281                         *(pDBits) = *(pSBits);
03282                         *(pDBits + 1) = *(pSBits + 1);
03283                         *(pDBits + 2) = *(pSBits + 2);
03284                         pDBits += 3;
03285                         pSBits += 4;
03286                     }
03287                 }
03288                 
03289                 // Duplicate the right hand pixel for the last third
03290                 if (Depth != 32)
03291                 {
03292                     RightHandByte_R = *(pSourceBits + Bytes - 3);
03293                     RightHandByte_G = *(pSourceBits + Bytes - 2);
03294                     RightHandByte_B = *(pSourceBits + Bytes - 1);
03295                 }
03296                 else
03297                 {
03298                     RightHandByte_R = *(pSourceBits + Bytes - 4);
03299                     RightHandByte_G = *(pSourceBits + Bytes - 3);
03300                     RightHandByte_B = *(pSourceBits + Bytes - 2);
03301                 }
03302 
03303                 for (j = 0; j < Width; j++ )
03304                 {
03305                     *pDBits = RightHandByte_R;
03306                     pDBits ++;
03307                     *pDBits = RightHandByte_G;
03308                     pDBits ++;
03309                     *pDBits = RightHandByte_B;
03310                     pDBits ++;
03311                 }
03312 
03313                 pDestBits += DestScanline;
03314                 pSourceBits += SourceScanline;
03315             }
03316 
03317             break;
03318         }
03319         default:
03320             ERROR2(FALSE,"Bad colour depth when bodge copying");
03321     }
03322 
03323 #endif
03324     return TRUE;
03325 }
03326 
03327 /********************************************************************************************
03328 
03329 >   BOOL BfxALU::MKB_BodgeCopyBitmap(INT32 Width, INT32 Height, INT32 Depth, LPBYTE pSourceBits, LPBYTE pDestBits)
03330                     
03331     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03332     Created:    20/09/96
03333     Inputs:     Width       - Width of bitmap
03334                 Height      - Height of bitmap
03335                 Depth       - ColourDepth of bitmap
03336                 pSourceBits - source data to use
03337                 pDestBits   - destination for the data
03338     Outputs:    None
03339     Returns:    TRUE if succeeded, FALSE & error set if not
03340     Purpose:    The reverse of the MAH_BodgeCopyBitmap version. This copies the bitmap across
03341                 to the destination but instead of doing a straight copy we copy the middle
03342                 section from the source bitmap which should be three times the width we want
03343                 to the destination bitmap which should be a third of the width we want.
03344     Assumes:    Source bitmap is three times the width of the destination but is the same
03345                 in all other aspects.
03346     SeeAlso:    MakeAccusoftHandle; MAH_BodgeCopyBitmap;
03347 
03348 ********************************************************************************************/
03349 
03350 BOOL BfxALU::MKB_BodgeCopyBitmap(INT32 Width, INT32 Height, INT32 Depth, LPBYTE pSourceBits, LPBYTE pDestBits)
03351 {
03352 #ifdef BODGE_ACCUSOFT_RESIZE
03353 
03354     // Copy back stripping the first bodge pixels from the start of each line
03355     UINT32 SourceScanline = DIBUtil::ScanlineSize(Width * 3, Depth);
03356     UINT32 DestScanline = DIBUtil::ScanlineSize(Width, Depth);
03357     // We need to do it the hard way and copy it by hand
03358     // Remove the repeated extra bodged pixels
03359     INT32 Bytes = 1;
03360     switch (Depth)
03361     {
03362         /* case 8:
03363         {
03364             // 1 pixel per byte
03365             Bytes = Width;
03366             // For each scanline copy the middle third, which is the original bitmap
03367             // back across to the destination
03368             for (INT32 i = 0; i < Height; i++ )
03369             { */
03370                 //memcpy(pDestBits /*dest*/, pSourceBits + Bytes, DestScanline);
03371             /*  pDestBits += DestScanline;
03372                 pSourceBits += SourceScanline;
03373             }
03374             break;
03375         } */
03376         case 24:
03377         {
03378             // Copy 8 * 3 pixels 1/3 of a pixel at a time
03379             Bytes = 3 * Width;
03380             // For each scanline copy the middle third, which is the original bitmap
03381             // back across to the destination
03382             for (INT32 i = 0; i < Height; i++ )
03383             {
03384                 memcpy(pDestBits /*dest*/, pSourceBits + Bytes, DestScanline);
03385                 pDestBits += DestScanline;
03386                 pSourceBits += SourceScanline;
03387             }
03388             break;
03389         }
03390         default:
03391             ERROR2(FALSE,"Bad colour depth when bodge copying");
03392     }
03393 
03394 #endif
03395     return TRUE;
03396 }
03397 
03398 /********************************************************************************************
03399 
03400 >   BOOL BfxALU::MakeKernelBitmap(INT32 Handle, KernelBitmap * * ppOutput, BOOL Make32Bits=FALSE,
03401                                   String_256 * pName =NULL, UINT32 ResID =0, BOOL DoBodge = FALSE)
03402                     
03403     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
03404     Created:    27/01/95
03405     Inputs:     DoBodge - tries to get round a bug in the Accusoft linear interpolation resize code
03406     Outputs:    *pHandle = Accusoft handle
03407     Returns:    TRUE if succeeded, FALSE & error set if not
03408     Purpose:    A new accusoft bitmap handle is created for the accumulator
03409     Errors:     Error 2 if init hasn't been called or GDraw fails
03410                 Error 3 if windows and some other Oil layer are stangely mixed...
03411     Scope:      Public
03412     SeeAlso:    -
03413 
03414 This actually copies the bitmap. Note we'll have to fudge 32bit bmps somehow.
03415 
03416 *** NOTE: The BfxALU A register is corrupted IFF Make32Bits is set ***
03417 
03418 ********************************************************************************************/
03419 
03420 BOOL BfxALU::MakeKernelBitmap(INT32 Handle, KernelBitmap * * ppOutput, BOOL Make32Bits,
03421                               String_256 * pName, UINT32 ResID, BOOL DoBodge)
03422 {
03423     ERROR3IF((!ppOutput ), "BfxALU output parameter must be non-null");
03424     INT32 width = 0;
03425     INT32   height = 0;
03426     INT32   bpp = 0;
03427     
03428     HANDLE MHandle = AccusoftFilters::pfnIMG_bitmap_info(Handle, &width, &height, &bpp);
03429     if (Make32Bits && bpp != 24)
03430     {
03431         INT32 result = AccusoftFilters::pfnIMG_delete_bitmap(Handle);
03432         ERROR2(FALSE, "Can't make a non-24 bit image into a 32 bit one guv");
03433     }
03434     
03435     ERROR2IF(width ==0 || height == 0 || (bpp != 1 && bpp != 4 && bpp != 8 && bpp !=24 && bpp != 32),
03436              FALSE,"Bad bitmap height, width or colour depth in MakeKernelBitmap");
03437 
03438 #ifdef BODGE_ACCUSOFT_RESIZE
03439     // if DoBodge set then we must strip our extra pixels from the left hand side and the right hand side
03440     // of the artificially wider bitmap. In fact three times wider than it should be.
03441     if (DoBodge)
03442     {
03443         width /= 3;
03444     }
03445 #endif
03446     
03447     BITMAPINFOHEADER * pBBMI = (LPBITMAPINFOHEADER) GlobalLock(MHandle);
03448     KernelBitmap * pKB = NewBitmap(NULL, width, height, Make32Bits ? 32 : bpp, pName, ResID);
03449     if (!pKB)
03450     {
03451         GlobalUnlock(MHandle);
03452         INT32 result = AccusoftFilters::pfnIMG_delete_bitmap(Handle);
03453         return FALSE; // Error already set
03454     }
03455 
03456     BITMAPINFOHEADER * pABMI=&(((CWxBitmap *)(pKB->ActualBitmap))->BMInfo->bmiHeader); // Dest
03457 
03458     if (
03459         // if our created bitmap  is not equal to the size of the accusoft one ....
03460         ((Make32Bits ? 24 : pABMI->biBitCount) != pBBMI->biBitCount) ||
03461         ((!Make32Bits && !DoBodge) && pABMI->biSizeImage != pBBMI->biSizeImage)
03462        )
03463     {
03464         GlobalUnlock(MHandle);
03465         delete pKB;
03466         INT32 result = AccusoftFilters::pfnIMG_delete_bitmap(Handle);
03467         ERROR2(FALSE,"Accusoft DLL lied about bpp / size");
03468     }
03469 
03470     // Fix dodgy Accusoft Palette returns. See how they know what they are doing. I think not.
03471     if (bpp > 8)
03472     {
03473         pBBMI->biClrUsed = 0;
03474         pBBMI->biClrImportant = 0;
03475     }
03476     else
03477     {
03478         UINT32 UsedColours = 1 << bpp;
03479 #ifdef ACCUSOFT_HAS_BROKEN_NON_FULL_PALETTES
03480 // Accusoft Promote_8 from monochrome returns ClrUsed=2 but has a 256 entry colour table. Arrrggghhh!
03481 pBBMI->biClrUsed=pBBMI->biClrImportant=UsedColours;
03482 #endif
03483         if (pBBMI->biClrUsed == 0) pBBMI->biClrUsed = UsedColours; // 0 is MS speak for maximum
03484         if (pBBMI->biClrImportant == 0) pBBMI->biClrImportant = UsedColours; // 0 is MS speak for maximum
03485         if (UsedColours < pBBMI->biClrUsed)
03486         {
03487             TRACEUSER( "Alex", _T("These Accusoft boys really know what they're doing with Palettes - NOT\n"));
03488             pBBMI->biClrUsed = UsedColours;
03489             pBBMI->biClrImportant = UsedColours;
03490         }
03491     }
03492 
03493     // This is fabby Alex code. Just check out those void * rather than LPBYTE and DWORD instead of RGBQUAD
03494     void * pA = (void *)(((CWxBitmap *)(pKB->ActualBitmap))->BMBytes); //Dest
03495     void * pB = (void *)(((char *)(void *)(pBBMI)) + sizeof (BITMAPINFOHEADER) + (pBBMI->biClrUsed * sizeof (DWORD)) ); //Source
03496 
03497     // Now fix problems with our DIB format palettes (like we don't support optimised palettes for 24 bit stuff)
03498     if (pBBMI->biClrUsed > pABMI->biClrUsed)
03499     {
03500         pBBMI->biClrUsed = pABMI->biClrUsed;
03501         TRACEUSER( "Alex", _T("We've lost some palette information\n"));
03502     }
03503     if (pBBMI->biClrUsed < pBBMI->biClrImportant) pBBMI->biClrImportant = pBBMI->biClrUsed;         
03504 
03505     if (!Make32Bits)
03506     {
03507 #ifdef BODGE_ACCUSOFT_RESIZE
03508         if (DoBodge)
03509         {
03510             // Copy the palette across
03511             if (pBBMI->biClrUsed > 0)
03512             {
03513                 LPRGBQUAD pAPAL = &(((CWxBitmap *)(pKB->ActualBitmap))->BMInfo->bmiColors[0]); // Dest
03514                 LPRGBQUAD pBPal = (LPRGBQUAD)(pBBMI + sizeof(BITMAPINFOHEADER)); // Source
03515                 memcpy(pAPAL /*dest*/, pBPal,  (pBBMI->biClrUsed * sizeof (RGBQUAD)) );
03516             }
03517 
03518             // Make sure we copy any relevent information across to the destination bitmaps header.
03519             //pABMI->biWidth = width;
03520             pABMI->biClrUsed = pBBMI->biClrUsed;
03521             pABMI->biClrImportant = pBBMI->biClrImportant;
03522 
03523             if (!MKB_BodgeCopyBitmap(width, height, bpp,(LPBYTE)pB, (LPBYTE)pA))
03524             {
03525                 GlobalUnlock(MHandle);
03526                 INT32 result = AccusoftFilters::pfnIMG_delete_bitmap(Handle);
03527                 delete pKB;// We can't delete it - what can we do?
03528                 *ppOutput = NULL;
03529                 return FALSE;
03530             }
03531         }
03532         else
03533 #endif
03534         {
03535             // Copy the header and palette across
03536             memcpy(pABMI /*dest*/, pBBMI, sizeof(BITMAPINFOHEADER) + (pBBMI->biClrUsed * sizeof (DWORD)) );
03537 
03538             // Copy the main bitmap data across
03539             memcpy(pA /*dest*/, pB, pABMI->biSizeImage);
03540         }
03541     }
03542     else
03543     {
03544         POINT tempPoints[3];
03545         tempPoints[0].x = 0;                        tempPoints[0].y = 0;
03546         tempPoints[1].x = (INT32)(pBBMI->biWidth);  tempPoints[1].y = 0;
03547         tempPoints[2].x = 0;                        tempPoints[2].y = (INT32)(pBBMI->biHeight);
03548         SetA(pKB);
03549         ZeroA();
03550         GC->SetBitmapFill(pBBMI,(LPBYTE)pB,
03551                                     0,
03552                                     tempPoints,
03553                                     0,
03554                                     NULL, // palette
03555                                     NULL,
03556                                     NULL,
03557                                     NULL,
03558                                     NULL
03559                                     );
03560         DoRect();
03561     }
03562 
03563     pABMI->biXPelsPerMeter = pBBMI->biXPelsPerMeter;
03564     pABMI->biYPelsPerMeter = pBBMI->biYPelsPerMeter;
03565 
03566     //if (pBBMI->biBitCount==1) FixMono(pA, pBBMI->biSizeImage);
03567 
03568     GlobalUnlock(MHandle);
03569 
03570     if (ResetAccusoftDibsToRuns)
03571     {
03572         //AccusoftFilters::pfnIMG_dib_to_runs (Handle);
03573         ResetAccusoftDibsToRuns = FALSE;
03574     }
03575 
03576     INT32 result = AccusoftFilters::pfnIMG_delete_bitmap(Handle);
03577     if (result < 0)
03578     {
03579         delete pKB;// We can't delete it - what can we do?
03580         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
03581     }
03582 
03583     *ppOutput = pKB;
03584 
03585 
03586 #ifdef _DEBUG
03587 // Check the memory is *really* gone and Accusoft isn't just mucking us around
03588 /*pBBMI = (LPBITMAPINFOHEADER) GlobalLock(MHandle);
03589 if (pBBMI)
03590 {
03591     TRACEUSER( "Alex", _T("Accusoft DLL failed to release memory\n"));
03592     GlobalUnlock(MHandle);
03593     GlobalFree(MHandle);
03594 }*/
03595 #endif
03596 
03597     return TRUE;
03598 }
03599 
03600 
03601 /********************************************************************************************
03602 
03603 >   BOOL BfxALU::FlipX(KernelBitmap * * ppOutput)
03604                     
03605     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
03606     Created:    27/01/95
03607     Inputs:     None
03608     Outputs:    *ppOutput = a pointer to the output bitmap
03609     Returns:    TRUE if succeeded, FALSE & error set if not
03610     Purpose:    A new bitmap is created which is the flipped version of the accumulator
03611     Errors:     Error 2 if init hasn't been called or GDraw fails
03612                 Error 3 if windows and some other Oil layer are stangely mixed...
03613     Scope:      Public
03614     SeeAlso:    -
03615 
03616 ********************************************************************************************/
03617 
03618 BOOL BfxALU::FlipX(KernelBitmap * * ppOutput)
03619 {
03620     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
03621     INT32 AccusoftHandle = -1;
03622     if (!MakeAccusoftHandle(&AccusoftHandle)) return FALSE;
03623     INT32 result = AccusoftFilters::pfnIMG_flip_bitmapx(AccusoftHandle);
03624     if (result < 0)
03625     {
03626         AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
03627         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
03628     }
03629         return MakeKernelBitmap(AccusoftHandle, ppOutput, FALSE, &(B->ActualBitmap->GetName()), _R(IDS_BFX_FLIPX));
03630 }
03631 
03632 /********************************************************************************************
03633 
03634 >   BOOL BfxALU::FlipY(KernelBitmap * * ppOutput)
03635                     
03636     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
03637     Created:    27/01/95
03638     Inputs:     None
03639     Outputs:    *ppOutput = a pointer to the output bitmap
03640     Returns:    TRUE if succeeded, FALSE & error set if not
03641     Purpose:    A new bitmap is created which is the flipped version of the accumulator
03642     Errors:     Error 2 if init hasn't been called or GDraw fails
03643                 Error 3 if windows and some other Oil layer are stangely mixed...
03644     Scope:      Public
03645     SeeAlso:    -
03646 
03647 ********************************************************************************************/
03648 
03649 
03650 BOOL BfxALU::FlipY(KernelBitmap * * ppOutput)
03651 {
03652     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
03653     INT32 AccusoftHandle = -1;
03654     if (!MakeAccusoftHandle(&AccusoftHandle)) return FALSE;
03655     INT32 result = AccusoftFilters::pfnIMG_flip_bitmapy(AccusoftHandle);
03656     if (result < 0)
03657     {
03658         AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
03659         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
03660     }
03661         return MakeKernelBitmap(AccusoftHandle, ppOutput, FALSE, &(B->ActualBitmap->GetName()), _R(IDS_BFX_FLIPY));
03662 }
03663 
03664 
03665 /********************************************************************************************
03666 
03667 >   BOOL BfxALU::Rotate90(KernelBitmap * * ppOutput)
03668                     
03669     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
03670     Created:    27/01/95
03671     Inputs:     None
03672     Outputs:    *ppOutput = a pointer to the output bitmap
03673     Returns:    TRUE if succeeded, FALSE & error set if not
03674     Purpose:    A new bitmap is created which is the flipped version of the accumulator
03675     Errors:     Error 2 if init hasn't been called or GDraw fails
03676                 Error 3 if windows and some other Oil layer are stangely mixed...
03677     Scope:      Public
03678     SeeAlso:    -
03679 
03680 ********************************************************************************************/
03681 
03682 BOOL BfxALU::Rotate90(KernelBitmap * * ppOutput)
03683 {
03684     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
03685     INT32 AccusoftHandle = -1;
03686     if (!MakeAccusoftHandle(&AccusoftHandle)) return FALSE;
03687     INT32 result = AccusoftFilters::pfnIMG_rotate_bitmap(AccusoftHandle, 9000);
03688     if (result < 0)
03689     {
03690         AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
03691         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
03692     }
03693         return MakeKernelBitmap(AccusoftHandle, ppOutput, FALSE, &(B->ActualBitmap->GetName()), _R(IDS_BFX_ROTATE90));
03694 }
03695 
03696 
03697 /********************************************************************************************
03698 
03699 >   BOOL BfxALU::Rotate180(KernelBitmap * * ppOutput)
03700                     
03701     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
03702     Created:    27/01/95
03703     Inputs:     None
03704     Outputs:    *ppOutput = a pointer to the output bitmap
03705     Returns:    TRUE if succeeded, FALSE & error set if not
03706     Purpose:    A new bitmap is created which is the flipped version of the accumulator
03707     Errors:     Error 2 if init hasn't been called or GDraw fails
03708                 Error 3 if windows and some other Oil layer are stangely mixed...
03709     Scope:      Public
03710     SeeAlso:    -
03711 
03712 ********************************************************************************************/
03713 
03714 BOOL BfxALU::Rotate180(KernelBitmap * * ppOutput)
03715 {
03716     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
03717     INT32 AccusoftHandle = -1;
03718     if (!MakeAccusoftHandle(&AccusoftHandle)) return FALSE;
03719     INT32 result = AccusoftFilters::pfnIMG_rotate_bitmap(AccusoftHandle, 18000);
03720     if (result < 0)
03721     {
03722         AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
03723         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
03724     }
03725         return MakeKernelBitmap(AccusoftHandle, ppOutput, FALSE, &(B->ActualBitmap->GetName()), _R(IDS_BFX_ROTATE180));
03726 }
03727 
03728 
03729 /********************************************************************************************
03730 
03731 >   BOOL BfxALU::Rotate270(KernelBitmap * * ppOutput)
03732                     
03733     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
03734     Created:    27/01/95
03735     Inputs:     None
03736     Outputs:    *ppOutput = a pointer to the output bitmap
03737     Returns:    TRUE if succeeded, FALSE & error set if not
03738     Purpose:    A new bitmap is created which is the flipped version of the accumulator
03739     Errors:     Error 2 if init hasn't been called or GDraw fails
03740                 Error 3 if windows and some other Oil layer are stangely mixed...
03741     Scope:      Public
03742     SeeAlso:    -
03743 
03744 ********************************************************************************************/
03745 
03746 BOOL BfxALU::Rotate270(KernelBitmap * * ppOutput)
03747 {
03748     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
03749     INT32 AccusoftHandle = -1;
03750     if (!MakeAccusoftHandle(&AccusoftHandle)) return FALSE;
03751     INT32 result = AccusoftFilters::pfnIMG_rotate_bitmap(AccusoftHandle, 27000);
03752     if (result < 0)
03753     {
03754         AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
03755         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
03756     }
03757     
03758     return MakeKernelBitmap(AccusoftHandle, ppOutput, FALSE, &(B->ActualBitmap->GetName()), _R(IDS_BFX_ROTATE270));
03759 }
03760 
03761 /********************************************************************************************
03762 
03763 >   BOOL BfxALU::BrightnessContrast(KernelBitmap * * ppOutput, INT32 Brightness, INT32 Contrast, INT32 Colour)
03764                     
03765     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
03766     Created:    28/01/95
03767     Inputs:     Brightness & Contast (-127 to +127)
03768     Outputs:    *ppOutput = a pointer to the output bitmap
03769     Returns:    TRUE if succeeded, FALSE & error set if not
03770     Purpose:    A new bitmap is created as per function name
03771     Errors:     Error 2 if init hasn't been called or GDraw fails
03772                 Error 3 if windows and some other Oil layer are stangely mixed...
03773     Scope:      Public
03774     SeeAlso:    -
03775 
03776 ********************************************************************************************/
03777 
03778 BOOL BfxALU::BrightnessContrast(KernelBitmap * * ppOutput, INT32 Brightness, INT32 Contrast, INT32 Colour)
03779 {
03780     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
03781 #if 0
03782     INT32 AccusoftHandle = -1;
03783     if (!MakeAccusoftHandle(&AccusoftHandle)) return FALSE;
03784     INT32 result = AccusoftFilters::pfnIMG_set_lut(AccusoftHandle, (INT32) Brightness, (INT32) Contrast);
03785     if (result < 0)
03786     {
03787         AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
03788         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
03789     }
03790         return MakeKernelBitmap(AccusoftHandle, ppOutput, FALSE, &(B->ActualBitmap->GetName()), _R(IDS_BFX_BRIGHTCONT));
03791 #endif
03792     
03793     *ppOutput = NewBitmap(B,0,0,0,NULL, _R(IDS_BFX_BRIGHTCONT));
03794     if (!ppOutput) return FALSE;
03795     
03796     BITMAPINFOHEADER * pBBMI=&(((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader);
03797     BITMAPINFOHEADER * pABMI=&(((CWxBitmap *)((*ppOutput)->ActualBitmap))->BMInfo->bmiHeader);
03798 
03799     DWORD PaletteUsed = pBBMI->biClrUsed;
03800     
03801     ERROR2IF ((pBBMI->biSizeImage == 0) || (pBBMI->biCompression != BI_RGB) || (pBBMI->biHeight<0), FALSE, 
03802                 "A naughty DIB format has been used internally");
03803     pABMI->biXPelsPerMeter = pBBMI->biXPelsPerMeter;
03804     pABMI->biYPelsPerMeter = pBBMI->biYPelsPerMeter;
03805     ERROR2IF ((pBBMI->biSizeImage != pABMI->biSizeImage), FALSE, "BfxALU brightness & constrast size upset");
03806     
03807     DWORD Width;
03808     DWORD Height;
03809     DWORD Size;
03810     LPBYTE Source;
03811     LPBYTE Dest;
03812     LPBYTE pSBits = (((CWxBitmap *)(B->ActualBitmap))->BMBytes);
03813     LPBYTE pDBits = (((CWxBitmap *)((*ppOutput)->ActualBitmap))->BMBytes);
03814     
03815     // We modify the image itself in the case of greyscale images
03816     BOOL SingleChannel=IsGreyscaleBitmap(B);
03817 
03818     // Handle wierd palette stuff
03819     if ((SingleChannel) || pBBMI->biBitCount>8)
03820     {
03821         if (SingleChannel && PaletteUsed)
03822         {
03823             // Copy the palette
03824             memcpy(((LPBYTE)(pABMI + 1/*ptr arith*/)) /*dest*/, ((LPBYTE)(pBBMI + 1/*ptr arith*/)) /*source*/,
03825                     PaletteUsed * sizeof(DWORD));
03826         }
03827         else
03828         {
03829             PaletteUsed = 0;
03830         }
03831         Width = pBBMI->biWidth;
03832         Height = pBBMI->biHeight;
03833         Size = (pBBMI->biBitCount / 8);
03834         Source = pSBits;
03835         Dest = pDBits;
03836     }
03837     else
03838     {
03839         // 0 is MS for maximum
03840         if (PaletteUsed == 0) PaletteUsed = 1<<pBBMI->biBitCount;
03841         Width = PaletteUsed;
03842         Height = 1;
03843         Size = 4;
03844         // This points to palette
03845         Source = ((LPBYTE)(pBBMI + 1/*ptr arith*/));
03846         Dest = ((LPBYTE)(pABMI + 1/*ptr arith*/));
03847         // Copy the image
03848         memcpy(pDBits /*dest*/, pSBits /*source*/, pBBMI->biSizeImage);
03849     } 
03850 
03851     if (!AdjustBrightnessContrastColour(Source, Dest, Size, Width, Height, Brightness, Contrast, Colour, SingleChannel))
03852     {
03853         delete *ppOutput;
03854         *ppOutput=NULL;
03855         return FALSE;
03856     }
03857     return TRUE;
03858 }
03859 
03860 /********************************************************************************************
03861 
03862 >   BOOL BfxALU::BayerMono(KernelBitmap * * ppOutput)
03863                     
03864     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
03865     Created:    28/01/95
03866     Inputs:     None
03867     Outputs:    *ppOutput = a pointer to the output bitmap
03868     Returns:    TRUE if succeeded, FALSE & error set if not
03869     Purpose:    A new bitmap is created as per function name
03870     Errors:     Error 2 if init hasn't been called or GDraw fails
03871                 Error 3 if windows and some other Oil layer are stangely mixed...
03872     Scope:      Public
03873     SeeAlso:    -
03874 
03875 ********************************************************************************************/
03876 
03877 BOOL BfxALU::BayerMono(KernelBitmap * * ppOutput)
03878 {
03879     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
03880     INT32 AccusoftHandle = -1;
03881     if (!MakeAccusoftHandle(&AccusoftHandle)) return FALSE;
03882     if ( (((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader).biBitCount <8 )
03883     {
03884         INT32 result = AccusoftFilters::pfnIMG_promote_8(AccusoftHandle);
03885         if (result < 0)
03886         {
03887             AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
03888             ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
03889         }
03890     }
03891     INT32 result = AccusoftFilters::pfnIMG_bayer_mono(AccusoftHandle);
03892     if (result < 0)
03893     {
03894         AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
03895         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
03896     }
03897     
03898     //AccusoftFilters::pfnIMG_runs_to_dib (AccusoftHandle);
03899     ResetAccusoftDibsToRuns = TRUE;
03900     
03901     return MakeKernelBitmap(AccusoftHandle, ppOutput, FALSE, &(B->ActualBitmap->GetName()), _R(IDS_BFX_BAYERMONO));
03902 }
03903 
03904 /********************************************************************************************
03905 
03906 >   BOOL BfxALU::HalftoneMono(KernelBitmap * * ppOutput)
03907                     
03908     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
03909     Created:    28/01/95
03910     Inputs:     None
03911     Outputs:    *ppOutput = a pointer to the output bitmap
03912     Returns:    TRUE if succeeded, FALSE & error set if not
03913     Purpose:    A new bitmap is created as per function name
03914     Errors:     Error 2 if init hasn't been called or GDraw fails
03915                 Error 3 if windows and some other Oil layer are stangely mixed...
03916     Scope:      Public
03917     SeeAlso:    -
03918 
03919 ********************************************************************************************/
03920 
03921 BOOL BfxALU::HalftoneMono(KernelBitmap * * ppOutput)
03922 {
03923     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
03924     INT32 AccusoftHandle = -1;
03925     if (!MakeAccusoftHandle(&AccusoftHandle)) return FALSE;
03926     if ( (((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader).biBitCount <8 )
03927     {
03928         INT32 result = AccusoftFilters::pfnIMG_promote_8(AccusoftHandle);
03929         if (result < 0)
03930         {
03931             AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
03932             ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
03933         }
03934     }
03935     INT32 result = AccusoftFilters::pfnIMG_halftone_mono(AccusoftHandle);
03936     
03937     if (result < 0)
03938     {
03939         AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
03940         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
03941     }
03942     
03943     // we MUST now call this function BEFORE we create a new bitmap from the data!
03944     // see the extfilts.h file for why this is necessary!
03945     //AccusoftFilters::pfnIMG_runs_to_dib (AccusoftHandle);
03946     ResetAccusoftDibsToRuns = TRUE;
03947 
03948     // DEBUG CODE - PUT THIS LINE BACK IN IF YOU ARE WONDERING WHAT THE HEEL IS GOING ON!   
03949 
03950     //AccusoftFilters::pfnIMG_display_bitmap (AccusoftHandle, GetDC (GetActiveWindow ()), 100, 0,
03951     //                                      100,300);
03952 
03953     return MakeKernelBitmap(AccusoftHandle, ppOutput, FALSE, &(B->ActualBitmap->GetName()), _R(IDS_BFX_HALFTONEMONO));
03954 }
03955 
03956 /********************************************************************************************
03957 
03958 >   BOOL BfxALU::DiffusionMono(KernelBitmap * * ppOutput)
03959                     
03960     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
03961     Created:    28/01/95
03962     Inputs:     None
03963     Outputs:    *ppOutput = a pointer to the output bitmap
03964     Returns:    TRUE if succeeded, FALSE & error set if not
03965     Purpose:    A new bitmap is created as per function name
03966     Errors:     Error 2 if init hasn't been called or GDraw fails
03967                 Error 3 if windows and some other Oil layer are stangely mixed...
03968     Scope:      Public
03969     SeeAlso:    -
03970 
03971 ********************************************************************************************/
03972 
03973 BOOL BfxALU::DiffusionMono(KernelBitmap * * ppOutput)
03974 {
03975     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
03976     INT32 AccusoftHandle = -1;
03977     if (!MakeAccusoftHandle(&AccusoftHandle)) return FALSE;
03978     if ( (((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader).biBitCount <8 )
03979     {
03980         INT32 result = AccusoftFilters::pfnIMG_promote_8(AccusoftHandle);
03981         if (result < 0)
03982         {
03983             AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
03984             ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
03985         }
03986     }
03987     INT32 result = AccusoftFilters::pfnIMG_diffusion_mono(AccusoftHandle);
03988     if (result < 0)
03989     {
03990         AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
03991         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
03992     }
03993     
03994     //AccusoftFilters::pfnIMG_runs_to_dib (AccusoftHandle);
03995     ResetAccusoftDibsToRuns = TRUE;
03996     
03997     return MakeKernelBitmap(AccusoftHandle, ppOutput, FALSE, &(B->ActualBitmap->GetName()), _R(IDS_BFX_DIFFUSIONMONO));
03998 }
03999 
04000 
04001 
04002 /********************************************************************************************
04003 
04004 >   BOOL BfxALU::BayerColour(KernelBitmap * * ppOutput)
04005                     
04006     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
04007     Created:    28/01/95
04008     Inputs:     None
04009     Outputs:    *ppOutput = a pointer to the output bitmap
04010     Returns:    TRUE if succeeded, FALSE & error set if not
04011     Purpose:    A new bitmap is created as per function name
04012     Errors:     Error 2 if init hasn't been called or GDraw fails
04013                 Error 3 if windows and some other Oil layer are stangely mixed...
04014     Scope:      Public
04015     SeeAlso:    -
04016 
04017 ********************************************************************************************/
04018 
04019 BOOL BfxALU::BayerColour(KernelBitmap * * ppOutput)
04020 {
04021     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
04022     INT32 AccusoftHandle = -1;
04023     if (!MakeAccusoftHandle(&AccusoftHandle)) return FALSE;
04024     if ( (((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader).biBitCount <8 )
04025     {
04026         INT32 result = AccusoftFilters::pfnIMG_promote_8(AccusoftHandle);
04027         if (result < 0)
04028         {
04029             AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
04030             ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
04031         }
04032     }
04033     INT32 result = AccusoftFilters::pfnIMG_bayer_color(AccusoftHandle);
04034     if (result < 0)
04035     {
04036         AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
04037         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
04038     }
04039         return MakeKernelBitmap(AccusoftHandle, ppOutput, FALSE, &(B->ActualBitmap->GetName()), _R(IDS_BFX_BAYERCOLOUR));
04040 }
04041 
04042 /********************************************************************************************
04043 
04044 >   BOOL BfxALU::PopularityColour(KernelBitmap * * ppOutput)
04045                     
04046     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
04047     Created:    28/01/95
04048     Inputs:     None
04049     Outputs:    *ppOutput = a pointer to the output bitmap
04050     Returns:    TRUE if succeeded, FALSE & error set if not
04051     Purpose:    A new bitmap is created as per function name
04052     Errors:     Error 2 if init hasn't been called or GDraw fails
04053                 Error 3 if windows and some other Oil layer are stangely mixed...
04054     Scope:      Public
04055     SeeAlso:    -
04056 
04057 ********************************************************************************************/
04058 
04059 BOOL BfxALU::PopularityColour(KernelBitmap * * ppOutput)
04060 {
04061     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
04062     INT32 AccusoftHandle = -1;
04063     if (!MakeAccusoftHandle(&AccusoftHandle)) return FALSE;
04064     if ( (((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader).biBitCount <8 )
04065     {
04066         INT32 result = AccusoftFilters::pfnIMG_promote_8(AccusoftHandle);
04067         if (result < 0)
04068         {
04069             AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
04070             ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
04071         }
04072     }
04073     INT32 result = AccusoftFilters::pfnIMG_popularity_color(AccusoftHandle);
04074     if (result < 0)
04075     {
04076         AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
04077         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
04078     }
04079         return MakeKernelBitmap(AccusoftHandle, ppOutput, FALSE, &(B->ActualBitmap->GetName()), _R(IDS_BFX_POPULARITYCOLOUR));
04080 }
04081 
04082 /********************************************************************************************
04083 
04084 >   BOOL BfxALU::DiffusionColour(KernelBitmap * * ppOutput)
04085                     
04086     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
04087     Created:    28/01/95
04088     Inputs:     None
04089     Outputs:    *ppOutput = a pointer to the output bitmap
04090     Returns:    TRUE if succeeded, FALSE & error set if not
04091     Purpose:    A new bitmap is created as per function name
04092     Errors:     Error 2 if init hasn't been called or GDraw fails
04093                 Error 3 if windows and some other Oil layer are stangely mixed...
04094     Scope:      Public
04095     SeeAlso:    -
04096 
04097 ********************************************************************************************/
04098 
04099 BOOL BfxALU::DiffusionColour(KernelBitmap * * ppOutput)
04100 {
04101 
04102 //ERROR2(FALSE, "The Accusoft boys have chosen to make this function rampantly crash");
04103 
04104     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
04105     INT32 AccusoftHandle = -1;
04106     if (!MakeAccusoftHandle(&AccusoftHandle)) return FALSE;
04107     if ( (((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader).biBitCount <8 )
04108     {
04109         INT32 result = AccusoftFilters::pfnIMG_promote_8(AccusoftHandle);
04110         if (result < 0)
04111         {
04112             AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
04113             ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
04114         }
04115     }
04116     INT32 result = AccusoftFilters::pfnIMG_diffusion_color(AccusoftHandle);
04117     if (result < 0)
04118     {
04119         AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
04120         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
04121     }
04122         return MakeKernelBitmap(AccusoftHandle, ppOutput, FALSE, &(B->ActualBitmap->GetName()), _R(IDS_BFX_DIFFUSIONCOLOUR));
04123 }
04124 
04125 /********************************************************************************************
04126 
04127 >   BOOL BfxALU::MakeGreyscale(KernelBitmap * * ppOutput)
04128                     
04129     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
04130     Created:    28/01/95
04131     Inputs:     None
04132     Outputs:    *ppOutput = a pointer to the output bitmap
04133     Returns:    TRUE if succeeded, FALSE & error set if not
04134     Purpose:    A new bitmap is created as per function name
04135     Errors:     Error 2 if init hasn't been called or GDraw fails
04136                 Error 3 if windows and some other Oil layer are stangely mixed...
04137     Scope:      Public
04138     SeeAlso:    BfxALU::MakeGreyscale32to8, BFXALU::IsGreyscaleBitmap
04139 
04140 ********************************************************************************************/
04141 
04142 BOOL BfxALU::MakeGreyscale(KernelBitmap * * ppOutput)
04143 {
04144     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
04145     INT32 AccusoftHandle = -1;
04146     if (!MakeAccusoftHandle(&AccusoftHandle)) return FALSE;
04147     if ( (((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader).biBitCount <8 )
04148     {
04149         INT32 result = AccusoftFilters::pfnIMG_promote_8(AccusoftHandle);
04150         if (result < 0)
04151         {
04152             AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
04153             ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
04154         }
04155     }
04156     INT32 result = AccusoftFilters::pfnIMG_color_gray(AccusoftHandle);
04157     if (result < 0)
04158     {
04159         AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
04160         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
04161     }
04162         return MakeKernelBitmap(AccusoftHandle, ppOutput, FALSE, &(B->ActualBitmap->GetName()), _R(IDS_BFX_GREYSCALE));
04163 }
04164 #endif //WEBSTER
04165 #endif //XARALX
04166 
04167 /********************************************************************************************
04168                                 
04169 >   BOOL BfxALU::MakeGreyscale32to8(KernelBitmap * * ppOutput)
04170                     
04171     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
04172     Created:    28/01/95
04173     Inputs:     None
04174     Outputs:    *ppOutput = a pointer to the output bitmap
04175     Returns:    TRUE if succeeded, FALSE & error set if not
04176     Purpose:    A new bitmap is created as per function name
04177     Errors:     Error 2 if init hasn't been called or GDraw fails
04178                 Error 3 if windows and some other Oil layer are stangely mixed...
04179     Scope:      Public
04180     SeeAlso:    BfxALU::MakeGreyscale, BFXALU::IsGreyscaleBitmap
04181 
04182 This is an optimised routine for converting 32 bit greyscale rendered bitmaps to 8 bpp
04183 
04184 ********************************************************************************************/
04185 
04186 BOOL BfxALU::MakeGreyscale32to8(KernelBitmap * * ppOutput)
04187 {
04188     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
04189 
04190     *ppOutput = NewBitmap(B,0,0,8, NULL, _R(IDS_BFX_GREYSCALE));
04191     if (!ppOutput) return FALSE;
04192     
04193     BITMAPINFOHEADER * pBBMI=&(((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader);
04194     BITMAPINFOHEADER * pABMI=&(((CWxBitmap *)((*ppOutput)->ActualBitmap))->BMInfo->bmiHeader);
04195 
04196     ERROR2IF ((pBBMI->biSizeImage == 0) || (pBBMI->biCompression != BI_RGB) || (pBBMI->biHeight<0)
04197                || (pBBMI->biBitCount !=32) , FALSE,
04198                 "Can't convert this DIB (may be it's not 32 bits)");
04199     pABMI->biXPelsPerMeter = pBBMI->biXPelsPerMeter;
04200     pABMI->biYPelsPerMeter = pBBMI->biYPelsPerMeter;
04201     ERROR2IF ((pBBMI->biWidth != pABMI->biWidth)||(pBBMI->biHeight != pABMI->biHeight)||(pABMI->biClrUsed!=0x100),
04202         FALSE, "BfxALU MakeGreyscale32to8 size upset");
04203     
04204     RGBQUAD * pSBits = (RGBQUAD *)(void *)(((CWxBitmap *)(B->ActualBitmap))->BMBytes);
04205     LPBYTE pDBits = (((CWxBitmap *)((*ppOutput)->ActualBitmap))->BMBytes);
04206 
04207     RGBQUAD * Pal = ((RGBQUAD *)(void *)(pABMI + 1/*ptr arith*/));
04208     for (INT32 x=0;x<0x100;x++)
04209     {   
04210         Pal[x].rgbRed=Pal[x].rgbGreen=Pal[x].rgbBlue=(BYTE)x;
04211         Pal[x].rgbReserved=0;
04212     }
04213 
04214     DWORD w=0;
04215     DWORD v=0;
04216     for (INT32 y=0;y<pBBMI->biHeight;y++)
04217     {
04218         for (INT32 x=0; x<pBBMI->biWidth; x++)
04219         {
04220             pDBits[v]=(2+pSBits[w].rgbRed+pSBits[w].rgbGreen+pSBits[w].rgbBlue)/3;
04221             w++;
04222             v++;
04223         }
04224         for (;v&3;v++) pDBits[v]=0;
04225     }
04226     ERROR3IF((w!=(pBBMI->biSizeImage>>2) || v!=pABMI->biSizeImage), "Alex messed up MakeGreyscale32to8 bitmap sizes");
04227     return TRUE;
04228 }
04229 
04230 #endif //EXCLUDE_FROM_RALPH
04231 
04232 /********************************************************************************************
04233 
04234 >   static BOOL BfxALU::IsGreyscaleBitmap(KernelBitmap * pKB);
04235                     
04236     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
04237     Created:    28/01/95
04238     Inputs:     pKB the bitmap to operate on
04239     Outputs:    None
04240     Returns:    TRUE if a 8bit GS bitmap else FALSE
04241     Purpose:    Determines whether or not a bitmap is 32bpp
04242     Errors:     None
04243     Scope:      Public
04244     SeeAlso:    BfxALU::MakeGreyscale, BFXALU::MakeGreyscale32to8
04245 
04246 This routine returns false if the bitmap is not a correctly formed 8 bpp bitmap. It does
04247 not return or set errors
04248 
04249 ********************************************************************************************/
04250 
04251 BOOL BfxALU::IsGreyscaleBitmap(KernelBitmap * pKB)
04252 {
04253     if ( (!pKB) || (!pKB->ActualBitmap) )
04254         return FALSE;
04255 
04256     return IsGreyscaleBitmap(pKB->ActualBitmap);
04257 }
04258 
04259 /********************************************************************************************
04260 
04261 >   static BOOL BfxALU::IsGreyscaleBitmap(OILBitmap * pKB);
04262                     
04263     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
04264     Created:    28/01/95
04265     Inputs:     pKB the bitmap to operate on
04266     Outputs:    None
04267     Returns:    TRUE if a 8bit GS bitmap else FALSE
04268     Purpose:    Determines whether or not a bitmap is 32bpp
04269     Errors:     None
04270     Scope:      Public
04271     SeeAlso:    BfxALU::MakeGreyscale, BFXALU::MakeGreyscale32to8
04272 
04273 This routine returns false if the bitmap is not a correctly formed 8 bpp bitmap. It does
04274 not return or set errors
04275 
04276 ********************************************************************************************/
04277 
04278 BOOL BfxALU::IsGreyscaleBitmap(OILBitmap * pOilBmp)
04279 {
04280     if ( (!pOilBmp) || (!pOilBmp->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap))) )
04281         return FALSE;
04282 
04283     BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)pOilBmp)->BMInfo->bmiHeader);
04284     if ((pBMI->biBitCount!=8) || (pBMI->biClrUsed!=0x100)) return FALSE;
04285     DWORD * pPal = (DWORD *)(void *)(pBMI +1 /*ptr arith*/);
04286     for (DWORD x=0; x<0x100; x++) if ((pPal[x]&0x00ffffff) != (x|(x<<8)|(x<<16))) return FALSE;
04287     return TRUE;
04288 }
04289 
04290 #ifndef WEBSTER
04291 #ifndef EXCLUDE_FROM_RALPH
04292 #ifndef EXCLUDE_FROM_XARALX
04293 
04294 /********************************************************************************************
04295 
04296 >   BOOL BfxALU::Octree (KernelBitmap * * ppOutput)
04297                     
04298     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
04299     Created:    28/01/95
04300     Inputs:     None
04301     Outputs:    *ppOutput = a pointer to the output bitmap
04302     Returns:    TRUE if succeeded, FALSE & error set if not
04303     Purpose:    A new bitmap is created as per function name
04304     Errors:     Error 2 if init hasn't been called or GDraw fails
04305                 Error 3 if windows and some other Oil layer are stangely mixed...
04306     Scope:      Public
04307     SeeAlso:    -
04308 
04309 ********************************************************************************************/
04310 
04311 BOOL BfxALU::Octree (KernelBitmap * * ppOutput)
04312 {
04313     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
04314     INT32 AccusoftHandle = -1;
04315     if (!MakeAccusoftHandle(&AccusoftHandle)) return FALSE;
04316     if ( (((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader).biBitCount <8 )
04317     {
04318         INT32 result = AccusoftFilters::pfnIMG_promote_8(AccusoftHandle);
04319         if (result < 0)
04320         {
04321             AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
04322             ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
04323         }
04324     }
04325     
04326     INT32 result = AccusoftFilters::pfnIMG_octree_color (AccusoftHandle, 8, NULL, 256);
04327 
04328     if (result < 0)
04329     {
04330         AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
04331         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
04332     }
04333     return MakeKernelBitmap(AccusoftHandle, ppOutput, FALSE, &(B->ActualBitmap->GetName()), _R(IDS_BFX_OCTREECOLOUR));
04334 }
04335 
04336 
04337 /********************************************************************************************
04338 
04339 >   BOOL BfxALU::SharpenBlur(KernelBitmap * * ppOutput, INT32 Degree, INT32 Times)
04340                     
04341     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
04342     Created:    28/01/95
04343     Inputs:     Degree = degree of sharpening (+ve) or blurring (-ve)
04344                 Times = number of times to apply
04345     Outputs:    *ppOutput = a pointer to the output bitmap
04346     Returns:    TRUE if succeeded, FALSE & error set if not
04347     Purpose:    A new bitmap is created as per function name
04348     Errors:     Error 2 if init hasn't been called or GDraw fails
04349                 Error 3 if windows and some other Oil layer are stangely mixed...
04350     Scope:      Public
04351     SeeAlso:    -
04352 
04353 ********************************************************************************************/
04354 
04355 BOOL BfxALU::SharpenBlur(KernelBitmap * * ppOutput, INT32 Degree, INT32 Times)
04356 {
04357     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
04358     INT32 AccusoftHandle = -1;
04359     if (!MakeAccusoftHandle(&AccusoftHandle)) return FALSE;
04360     if ( (((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader).biBitCount <=8 )
04361     {
04362         INT32 result = AccusoftFilters::pfnIMG_promote_24(AccusoftHandle);
04363         if (result < 0)
04364         {
04365             AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
04366             ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
04367         }
04368     }
04369     if (Times>20) Times=20;
04370     for (INT32 i=1; i<=Times; i++)
04371     {
04372         INT32 result = AccusoftFilters::pfnIMG_sharpen_bitmap(AccusoftHandle, (INT32) Degree);
04373         if (result < 0)
04374         {
04375             AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
04376             ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
04377         }
04378     }
04379         return MakeKernelBitmap(AccusoftHandle, ppOutput, FALSE, &(B->ActualBitmap->GetName()), (Degree>0)?_R(IDS_BFX_SHARPEN):_R(IDS_BFX_BLUR));
04380 }
04381 
04382 #endif
04383 
04384 /********************************************************************************************
04385 
04386 >   BOOL BfxALU::RemoveDither(KernelBitmap * * ppOutput, INT32 Thresh, INT32 QuantCols, TraceMethod Method)
04387                     
04388     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
04389     Created:    28/01/95
04390     Inputs:     Thresh = Threshold for a sharp edge (0-255). No dither removal at 0, highest at 255
04391                 QuantCols = number of quantisation colours to use (17-255 colour, 2-255 GS)
04392     Outputs:    *ppOutput = a pointer to the output bitmap
04393     Returns:    TRUE if succeeded, FALSE & error set if not
04394     Purpose:    A new bitmap is created as per function name
04395     Errors:     Error 2 if init hasn't been called or GDraw fails
04396                 Error 3 if windows and some other Oil layer are stangely mixed...
04397     Scope:      Public
04398     SeeAlso:    -
04399 
04400 The bitmap becomes 32 bits so use this for tracing only!
04401 
04402 ********************************************************************************************/
04403 
04404 INT32 BfxALUQuantisationRoutine( const void *arg1, const void *arg2 )
04405 {
04406     QuantisationCell * qc1 = *((QuantisationCell * *)(arg1));
04407     QuantisationCell * qc2 = *((QuantisationCell * *)(arg2));
04408     return ( ((qc1->pixels)>(qc2->pixels))?-1:( ((qc1->pixels)<(qc2->pixels))?1:0 ) );
04409 }
04410 
04411 // QUANT_SHIFT is Log2 width of the colour quantisation cube, i.e. 4 means the cubes are 16x16x16 colour values.
04412 // In this case there would be 17x17x17 of them (as 0 & 255 are on centre values).
04413 #define QUANT_SHIFT 4
04414 #define QUANT_SIZE ((1<<(8-QUANT_SHIFT))+1)
04415 #define QUANT_ROUND (1<<(QUANT_SHIFT-1))
04416 
04417 // here's what we want to do
04418 #define QMEMBER(x,y,z) [((x)+QUANT_SIZE*((y)+QUANT_SIZE*(z)))]
04419 // and here's how to do it faster - but gcc doesn't like it
04420 //#define QMULT(w) (((w)<<(8-QUANT_SHIFT))+(w))
04421 //#define QMEMBER(x,y,z) [(__mtemp=y+QMULT(z),x+QMULT(__mtemp))]
04422 
04423 #define QUANT_NUMBER (QUANT_SIZE*QUANT_SIZE*QUANT_SIZE)
04424 
04425 BOOL BfxALU::RemoveDither(KernelBitmap * * ppOutput, INT32 Thresh, INT32 QuantCols, TraceMethod Method)
04426 {
04427     TRACEUSER( "Alex", _T("RemoveDither called Method %d, Degree %d\n"));
04428     
04429     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
04430 
04431     INT32 OutputBPP=1;
04432     INT32 NumPasses=1;
04433     INT32 Width=0;
04434     INT32 Depth=0;
04435     INT32 Height=0;
04436     INT32 l;
04437 //  INT32 __mtemp;
04438     if (!GetSize(B, &Width, &Height, &Depth)) return FALSE;
04439 
04440     DWORD * InputLine[5];
04441     BYTE * ByteLine[5];
04442     BYTE * OutputLine = NULL;
04443     for (l=0; l<5; l++) InputLine[l]=NULL;
04444 
04445     Thresh=(Thresh*Thresh*3); // must be +ve
04446     if (Thresh>255*255*3) Thresh=255*255*3;
04447 
04448     if (QuantCols<2) QuantCols=2;
04449     if ((Method==TRACEMETHOD_256COL) && (QuantCols<17)) QuantCols=17;
04450     if (QuantCols>255) QuantCols=255;
04451 
04452     INT32 TotalCols=QuantCols;
04453 
04454     *ppOutput=NULL;
04455 
04456     // The array of quantisation cells
04457     //QuantisationCell QuantMap[QUANT_SIZE][QUANT_SIZE][QUANT_SIZE];
04458     
04459     QuantisationCell * pQuantMap=NULL;
04460     if ((pQuantMap=(QuantisationCell *)CCMalloc(sizeof(QuantisationCell)*QUANT_NUMBER))==NULL)
04461     {
04462         return FALSE;
04463     }
04464 
04465     // An array of pointers to cells which get sorted soon
04466     //QuantisationCell * QuantIndex[QUANT_SIZE][QUANT_SIZE][QUANT_SIZE];
04467     //QuantisationCell * * QuantSort = &(QuantIndex[0][0][0]);
04468     
04469     QuantisationCell * * pQuantIndex = NULL;
04470     if ((pQuantIndex=(QuantisationCell * *)CCMalloc(sizeof(QuantisationCell *)*QUANT_NUMBER))==NULL)
04471     {
04472         CCFree(pQuantMap);
04473         return FALSE;
04474     }
04475 
04476     // Make this point to the 1st pointer so we can sort it.
04477     QuantisationCell * * QuantSort = pQuantIndex;
04478 
04479 
04480     ERROR3IF(QUANT_SIZE*QUANT_SIZE*QUANT_SIZE<256, "Too few quantisation steps");
04481 
04482     switch(Method)
04483     {
04484         case TRACEMETHOD_MONO:
04485             OutputBPP=1;
04486             NumPasses=2;
04487             break;
04488         case TRACEMETHOD_GREYSCALE:
04489             OutputBPP=8;
04490             NumPasses=1;
04491             break;
04492         case TRACEMETHOD_256COL:
04493             {
04494                 OutputBPP=8;
04495                 NumPasses=2;
04496                 for (INT32 i=0; i<QUANT_SIZE; i++) for (INT32 j=0; j<QUANT_SIZE; j++) for (INT32 k=0; k<QUANT_SIZE; k++)
04497                 {
04498                     (pQuantMap)QMEMBER(i,j,k).rsum=(pQuantMap)QMEMBER(i,j,k).gsum=(pQuantMap)QMEMBER(i,j,k).bsum=(pQuantMap)QMEMBER(i,j,k).pixels=0;
04499                     (pQuantMap)QMEMBER(i,j,k).index=-1;
04500                     (pQuantIndex)QMEMBER(i,j,k)=&(pQuantMap)QMEMBER(i,j,k);
04501                 }
04502             }
04503             break;
04504         case TRACEMETHOD_TRUECOL:
04505             OutputBPP=32;
04506             NumPasses=1;
04507             break;
04508         default:
04509             ERROR2(FALSE,"BfxALU::RemoveDither doesn't understand trace method");
04510             break;
04511     }
04512 
04513     KernelBitmap * pKB = NewBitmap(B, 0, 0, OutputBPP, NULL, _R(IDS_BFX_REMOVEDITHER));
04514 
04515     if (!pKB)
04516     {
04517         CCFree(pQuantMap);
04518         CCFree(pQuantIndex);
04519         return FALSE; // error already set
04520     }
04521 
04522     if (OutputBPP==1 && Depth==1)
04523     {
04524         DWORD * SPalette= (DWORD*)(void*)(((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiColors);
04525         if ((SPalette[0] & 0x00ffffff)==0 && (SPalette[1] & 0x00ffffff)==0x00ffffff)
04526         {
04527             // Forsooth! It is a true mono bitmap.
04528         
04529             // We know a song about that:
04530             //      memcpy memcpy, its so much quicker
04531             //      mono bitmaps handled so much slicker
04532             //      don't bother trying to remove their noise
04533             //      as they don't have any (not by our definition anywoise)
04534             // (OK, enough of that).
04535 
04536             memcpy(/*dest*/(((CWxBitmap *)(pKB->ActualBitmap))->BMBytes), /*src*/(((CWxBitmap *)(B->ActualBitmap))->BMBytes),
04537                    (((CWxBitmap *)(pKB->ActualBitmap))->BMInfo->bmiHeader.biSizeImage));
04538             RGBQUAD * Palette= (((CWxBitmap *)(pKB->ActualBitmap))->BMInfo->bmiColors);
04539             Palette[0].rgbRed=Palette[0].rgbBlue=Palette[0].rgbGreen=0;
04540             Palette[1].rgbRed=Palette[1].rgbBlue=Palette[1].rgbGreen=255;
04541             *ppOutput=pKB;
04542             CCFree(pQuantMap);
04543             CCFree(pQuantIndex);
04544             return TRUE;
04545         }
04546     }
04547 
04548     INT32 x;
04549     INT32 y;
04550 
04551 /*
04552     INT32 NoiseMatrix[5][5]={
04553         {  32, 128, 192, 128,  32 },
04554         { 128, 256, 256, 256, 128 },
04555         { 192, 256, 256, 256, 192 },
04556         { 128, 256, 256, 256, 128 },
04557         {  32, 128, 192, 128,  32 }};
04558 
04559     INT32 NoiseMatrix[5][5]={
04560         { 1, 2, 3, 2, 1 },
04561         { 2, 4, 4, 4, 2 },
04562         { 3, 4, 4, 4, 3 },
04563         { 2, 4, 4, 4, 2 },
04564         { 1, 2, 3, 2, 1 }};
04565 // Sum=68
04566 */
04567     INT32 NoiseMatrix[5][5]={
04568         { 1, 4, 6, 4, 1 },
04569         { 4, 8, 8, 8, 4 },
04570         { 6, 8, 8, 8, 6 },
04571         { 4, 8, 8, 8, 4 },
04572         { 1, 4, 6, 4, 1 }};
04573 
04574     INT32 * NoiseMatrixP[5];
04575 
04576     INT32 Distrib[256];
04577     INT32 Points=0;
04578     INT32 n;
04579     for (n=0; n<256; n++) Distrib[n]=0;
04580 
04581     if (Method==TRACEMETHOD_GREYSCALE)
04582     {
04583         double QuantPoints[255];
04584         double QuantDist=256.0/(QuantCols-1);
04585         double q=-0.5*QuantDist;
04586         for (n=0; n<QuantCols; n++)
04587         {
04588             QuantPoints[n]=q;
04589             q+=QuantDist;
04590         }
04591         INT32 cp=0;
04592         for (n=0; n<256; n++)
04593         {
04594             while ((cp<QuantCols) && (n>QuantPoints[cp])) cp++;
04595             Distrib[n]=(INT32)(QuantDist*(cp-1));
04596             if (Distrib[n]<0) Distrib[n]=0;
04597             if (Distrib[n]>255) Distrib[n]=255;
04598         }
04599     }
04600 
04601     OutputLine=(BYTE *) CCMalloc(Width<<2);
04602     if (!OutputLine)
04603     {
04604             CCFree(pQuantMap);
04605             CCFree(pQuantIndex);
04606             delete pKB;
04607             return FALSE;
04608     }
04609     for (x=0; x<(Width<<2); x++) OutputLine[x]=0;
04610 
04611     for (l=0; l<5; l++)
04612     {
04613         if ((InputLine[l]=(DWORD *)/*assign*/CCMalloc((Width+4)<<2))==NULL)
04614         {
04615             for (l=0; l<5; l++) if (InputLine[l]) CCFree(InputLine[l]);
04616             CCFree(OutputLine);
04617             delete pKB;
04618             CCFree(pQuantMap);
04619             CCFree(pQuantIndex);
04620             return FALSE;
04621         };
04622         ByteLine[l]=(BYTE *)InputLine[l];
04623         NoiseMatrixP[l]=&(NoiseMatrix[l][0]);
04624     }
04625     
04626 
04627     for (INT32 Pass=0; Pass<NumPasses; Pass++)
04628     {
04629 
04630         // First of all we must convert a new block to 32 bpp
04631 
04632         for (y=0; y<Height; y++)
04633         {   
04634             // Shuffle the existing lines down
04635             // L4 shifts into L3
04636             // ..
04637             // L1 shifts into L0
04638             //
04639             // L0 is forgotten and its memory space is used by the new L4
04640             
04641             DWORD * L0=InputLine[0];
04642             for (l=0; l<5; l++)
04643             {
04644                 InputLine[l]=(l==4)?L0:InputLine[l+1];
04645             }
04646 
04647             // at y=0 we must fill in all lines, otherwise just the new line (line 4)
04648             for (l=(y==0)?0:4; l<5; l++)
04649             {
04650                 INT32 sy=y+l-2;
04651                 if (sy<0) sy=0;
04652                 if (sy>=Height) sy=Height-1;
04653                 ConvertScanLineToDWORD(B,sy,&(InputLine[l][2]));
04654                 InputLine[l][0]=InputLine[l][1]=InputLine[l][2]; // duplicate 1st pixel
04655                 InputLine[l][Width+3]=InputLine[l][Width+2]=InputLine[l][Width+1]; // duplicate last pixel
04656             }
04657 
04658             for (l=0; l<5; l++) ByteLine[l]=(BYTE *)InputLine[l];
04659 
04660             INT32 r;
04661             INT32 g;
04662             INT32 b;
04663 
04664             // First create the output scanline
04665             BYTE * pOutput=OutputLine;
04666             if (Depth==1)
04667             {
04668                 // This is a great optimisation for mono source where the pixels will always be completely different
04669                 // (and thus be unaffected as they'll be over the threshold) or identical (and won't affect things
04670                 // as they are identical). Thus we might as well just memcpy the line
04671                 memcpy(OutputLine, &(ByteLine[2][2<<2]), Width<<2);
04672             }
04673             else
04674             {
04675 #ifdef FASTREMOVEDITHER
04676 
04677                 FastRemoveDither(ByteLine, NoiseMatrixP, (DWORD *) OutputLine, Width, Thresh,
04678                     (Method==TRACEMETHOD_GREYSCALE || Method==TRACEMETHOD_MONO)?1:0);
04679 
04680 #else
04681                 SlowRemoveDither(ByteLine, NoiseMatrix, OutputLine, Width, Thresh,
04682                     (Method==TRACEMETHOD_GREYSCALE || Method==TRACEMETHOD_MONO));
04683 #endif
04684             }
04685             // Now write it back
04686 
04687             void * VImage = (((CWxBitmap *)(pKB->ActualBitmap))->BMBytes);
04688             switch (Method)
04689             {
04690                 case TRACEMETHOD_GREYSCALE:
04691                 {
04692                     BYTE * Dest = &(((BYTE *) VImage)[((Width+3)&~3)*y]);
04693                     for (x=0; x<Width; x++) 
04694                     {
04695                         *(Dest++)=(BYTE)(DWORD)Distrib[*pOutput];
04696                         pOutput+=4;
04697                     }
04698                 }
04699                 break;
04700                 case TRACEMETHOD_MONO:
04701                 {
04702                     if (!Pass) // Mono - 1st pass modify distribution curve
04703                     {
04704                         for (x=0; x<Width; x++) 
04705                         {
04706                             r=(INT32)(DWORD)(*pOutput);
04707                             pOutput+=4;
04708                             Distrib[r]++;
04709                             Points++;
04710                         }
04711                     }
04712                     else
04713                     {
04714                         BYTE * Dest = (&(((BYTE *) VImage)[(((Width+31)&~31)>>3)*y]))-1/*as we preinc*/;
04715                         for (x=0; x<Width; x++) 
04716                         {
04717                             if (!(x&7)) *(++Dest)=0;
04718                             *Dest |= Distrib[(INT32)(DWORD)(*pOutput)] >> (x&7);
04719                             pOutput+=4;
04720                         }
04721                     }
04722                 }
04723                 break;
04724                 case TRACEMETHOD_TRUECOL:
04725                 {
04726                     memcpy(&(((DWORD *) VImage)[Width*y]), pOutput, Width<<2);
04727                 }
04728                 break;
04729                 case TRACEMETHOD_256COL:
04730                 {
04731                     if (!Pass)
04732                     {
04733                         for (x=0; x<Width; x++) 
04734                         {
04735                             b=(INT32)(DWORD)*(pOutput++);
04736                             g=(INT32)(DWORD)*(pOutput++);
04737                             r=(INT32)(DWORD)*(pOutput++);
04738                             pOutput++;
04739                             INT32 qr=(r+QUANT_ROUND)>>QUANT_SHIFT;
04740                             INT32 qg=(g+QUANT_ROUND)>>QUANT_SHIFT;
04741                             INT32 qb=(b+QUANT_ROUND)>>QUANT_SHIFT;
04742                             QuantisationCell * pQuantCell=&(pQuantMap)QMEMBER(qr,qg,qb);
04743                             pQuantCell->pixels++;
04744                             pQuantCell->rsum+=r;
04745                             pQuantCell->gsum+=g;
04746                             pQuantCell->bsum+=b;
04747                         }
04748                     }
04749                     else
04750                     {
04751                         BYTE * Dest = &(((BYTE *) VImage)[((Width+3)&~3)*y]);
04752                         for (x=0; x<Width; x++) 
04753                         {
04754                             b=(INT32)(DWORD)*(pOutput++);
04755                             g=(INT32)(DWORD)*(pOutput++);
04756                             r=(INT32)(DWORD)*(pOutput++);
04757                             pOutput++;
04758                             INT32 qr=(r+QUANT_ROUND)>>QUANT_SHIFT;
04759                             INT32 qg=(g+QUANT_ROUND)>>QUANT_SHIFT;
04760                             INT32 qb=(b+QUANT_ROUND)>>QUANT_SHIFT;
04761                             QuantisationCell * pQuantCell=&(pQuantMap)QMEMBER(qr,qg,qb);
04762                             INT32 Index = pQuantCell->index;
04763                             if (Index<0)
04764                             {
04765                                 // better colourtrans it then
04766                                 INT32 rsum = pQuantCell->rsum;
04767                                 INT32 gsum = pQuantCell->gsum;
04768                                 INT32 bsum = pQuantCell->bsum;
04769 
04770                                 INT32 MinD=0x7fffffff;
04771                                 Index=0;
04772                                 for (INT32 m=0; m<TotalCols; m++)
04773                                 {
04774                                     // Find the colour difference
04775                                     INT32 d=IntegerSquare(QuantSort[m]->rsum - rsum)
04776                                             + IntegerSquare(QuantSort[m]->gsum - gsum)
04777                                             + IntegerSquare(QuantSort[m]->bsum - bsum);
04778                                     if (d<MinD)
04779                                     {
04780                                         // Note the cube with the smallest difference
04781                                         MinD=d;
04782                                         Index=m;
04783                                     }
04784                                 }
04785                                 // write it back in so we dont have to do it again
04786                                 pQuantCell->index=Index;
04787                             }
04788                             ERROR3IF(((DWORD)Index)>255, "Wierd index value");
04789                             *Dest++=(BYTE)(DWORD)Index;
04790                         }
04791                     }
04792                 }
04793                 break;
04794                 default:
04795                 {
04796                     ERROR3("We shouldn't get here...");
04797                 }
04798                 break;
04799             } // End of case
04800 
04801 
04802             BOOL Continue=TRUE;
04803             if ((y & 15)==0) Continue=ContinueSlowJob((100*y/Height+100*Pass)/NumPasses);
04804             if (!Continue)
04805             {
04806                 ERROR1RAW(_R(IDE_BFX_ABORT));
04807                 for (l=0; l<5; l++) if (InputLine[l]) CCFree(InputLine[l]);
04808                 CCFree(OutputLine);
04809                 delete pKB;
04810                 CCFree(pQuantMap);
04811                 CCFree(pQuantIndex);
04812                 return FALSE;
04813             }
04814         } // End of y loop
04815         
04816         switch (Method)
04817         {
04818             case TRACEMETHOD_MONO:
04819                 if (!Pass) {
04820                     RGBQUAD * Palette= (((CWxBitmap *)(pKB->ActualBitmap))->BMInfo->bmiColors);
04821                     INT32 Sum=0;
04822                     for (INT32 n=0; n<256; n++)
04823                     {
04824                         BOOL Thresh=(Sum>Points/2)|(n==255);
04825                         Sum+=Distrib[n];
04826                         Distrib[n]=Thresh?0x80:0;
04827                     }
04828                     Palette[0].rgbRed=Palette[0].rgbBlue=Palette[0].rgbGreen=0;
04829                     Palette[1].rgbRed=Palette[1].rgbBlue=Palette[1].rgbGreen=255;
04830                 }
04831                 break;
04832             case TRACEMETHOD_256COL:
04833                 if (!Pass) {
04834                     // First bodge the issue so the gun maxima values always appear, which ensures
04835                     // we can represent a full contrast range. This probably isn't necessary as we're not
04836                     // dithering it but heh, we might as well keep white as white etc.
04837 
04838                     RGBQUAD * Palette= (((CWxBitmap *)(pKB->ActualBitmap))->BMInfo->bmiColors);
04839                     INT32 totalpixels=Width * Height;
04840                     INT32 pixmax=totalpixels * INT32(0xff);
04841                     INT32 r;
04842                     for (r=0; r<QUANT_SIZE; r+=QUANT_SIZE-1)
04843                         for (INT32 g=0; g<QUANT_SIZE; g+=QUANT_SIZE-1) 
04844                             for (INT32 b=0; b<QUANT_SIZE; b+=QUANT_SIZE-1)                  
04845                             {
04846                                 QuantisationCell * pQuantCell=&(pQuantMap)QMEMBER(r,g,b);
04847                                 pQuantCell->rsum=r?pixmax:0;
04848                                 pQuantCell->gsum=g?pixmax:0;
04849                                 pQuantCell->bsum=b?pixmax:0;
04850                                 pQuantCell->pixels=totalpixels;
04851                             }
04852 
04853                     // And now for some greyscales
04854                     // This avoids inverse-Acorn colourtrans problems
04855                     for (r=1; r<QUANT_SIZE-1/*even*/; r+=2)
04856                     {
04857                         QuantisationCell * pQuantCell=&(pQuantMap)QMEMBER(r,r,r);
04858                         pQuantCell->rsum=pQuantCell->gsum=pQuantCell->bsum=
04859                             (r<<QUANT_SHIFT) * (pQuantCell->pixels=/*assign*/totalpixels);
04860                     }
04861 
04862                     // Now sort the index
04863                     qsort((void *)(QuantSort),QUANT_SIZE*QUANT_SIZE*QUANT_SIZE,sizeof(QuantisationCell *),
04864                         &BfxALUQuantisationRoutine);
04865                     TotalCols=0;
04866                     INT32 n;
04867 
04868                     // blank the palette
04869                     for (n=0; n<256; n++) Palette[n].rgbRed=Palette[n].rgbBlue=Palette[n].rgbGreen=Palette[n].rgbReserved=0;
04870                     
04871                     // Now calculate the real av RGB values for each subcube
04872                     for (n=0; (n<QUANT_SIZE*QUANT_SIZE*QUANT_SIZE) ; n++ ) if (QuantSort[n]->pixels>0) 
04873                     {
04874                         INT32 r=(QuantSort[n]->rsum+(INT32)(QuantSort[n]->pixels>>1))/QuantSort[n]->pixels;
04875                         INT32 g=(QuantSort[n]->gsum+(INT32)(QuantSort[n]->pixels>>1))/QuantSort[n]->pixels;
04876                         INT32 b=(QuantSort[n]->bsum+(INT32)(QuantSort[n]->pixels>>1))/QuantSort[n]->pixels;
04877                         if (r<0) r=0;                           // Clip
04878                         if (r>255) r=255;
04879                         if (g<0) g=0;                           // Clip
04880                         if (g>255) g=255;
04881                         if (b<0) b=0;                           // Clip
04882                         if (b>255) b=255;
04883                         QuantSort[n]->rsum = r;
04884                         QuantSort[n]->gsum = g;
04885                         QuantSort[n]->bsum = b;
04886                         ERROR3IF((n>0) && (QuantSort[n-1]->pixels<QuantSort[n]->pixels), "urm, they aren't in order...");
04887                     }
04888                     
04889                     // Label the most important subcubes and fill in the palette
04890                     for (n=0; (n<QuantCols)  && (QuantSort[n]->pixels>0); n++)
04891                     {
04892                         QuantSort[n]->index=n;
04893                         TotalCols=n+1;
04894                         Palette[n].rgbRed=(BYTE)(DWORD)(QuantSort[n]->rsum);
04895                         Palette[n].rgbBlue=(BYTE)(DWORD)(QuantSort[n]->bsum);
04896                         Palette[n].rgbGreen=(BYTE)(DWORD)(QuantSort[n]->gsum);
04897                     }
04898 
04899                     // Now find the nearest matches for the other colours in the colour cube
04900                     ERROR3IF(!TotalCols, "OK, how come this image had no colours in it *at all*");
04901                 }               
04902                 break;
04903             case TRACEMETHOD_GREYSCALE:
04904                 {
04905                     RGBQUAD * Palette= (((CWxBitmap *)(pKB->ActualBitmap))->BMInfo->bmiColors);
04906                     for (INT32 c=0; c<256; c++)
04907                         Palette[c].rgbRed=Palette[c].rgbBlue=Palette[c].rgbGreen=(BYTE)(DWORD)c;
04908                 }
04909                 break;
04910             default:
04911                 break;
04912         }
04913     }
04914 
04915     for (l=0; l<5; l++) if (InputLine[l]) CCFree(InputLine[l]);
04916     CCFree(OutputLine);
04917     *ppOutput=pKB;
04918     CCFree(pQuantMap);
04919     CCFree(pQuantIndex);
04920     return TRUE;
04921 }
04922 
04923 /********************************************************************************************
04924 
04925 >   void BfxALU::SlowRemoveDither(BYTE * ByteLine[5], INT32 NoiseMatrix[5][5],
04926                                   BYTE * OutputLine, INT32 Width, INT32 Thresh, BOOL Mono)
04927                     
04928     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
04929     Created:    28/04/95
04930     Inputs:     ByteLine - a ptr to 5 ptrs to extended scanlines of 32 bit source data
04931                 NoiseMatrix - the variable convolution matrix
04932                 Width = the (unextended) scanline width. Th input scanline must be extended by 2 pixels each side
04933                 Thresh = the noise cutoff threshold
04934                 Mono = true to make the output single channel
04935     Outputs:    BYTE * OutputLine - the 32 bit scanline to be filled in
04936     Returns:    None
04937     Purpose:    Removes dither (slowly)
04938     Errors:     Error 3 for algorithmic failures
04939     Scope:      Protected
04940     SeeAlso:    BfxALU::RemoveDither, FastRemoveDither
04941 
04942 ********************************************************************************************/
04943 
04944 void BfxALU::SlowRemoveDither(BYTE * ByteLine[5], INT32 NoiseMatrix[5][5], BYTE * OutputLine, INT32 Width, INT32 Thresh, BOOL Mono)
04945 {
04946     for (INT32 x=0; x<Width; x++) 
04947     {
04948         INT32 r=0;
04949         INT32 g=0;
04950         INT32 b=0;
04951 
04952         INT32 s=0;
04953 
04954         INT32 CB=(INT32)(ByteLine[2][2*4]);
04955         INT32 CG=(INT32)(ByteLine[2][2*4+1]);
04956         INT32 CR=(INT32)(ByteLine[2][2*4+2]);
04957 
04958         for (INT32 dy=0; dy<=4; dy++)
04959         {   
04960             for (INT32 dx=0; dx<=4; dx++)
04961             {
04962                 INT32 v=NoiseMatrix[dx][dy];
04963 
04964                 INT32 LB=(INT32)(DWORD)(*(ByteLine[dy]++));
04965                 INT32 LG=(INT32)(DWORD)(*(ByteLine[dy]++));
04966                 INT32 LR=(INT32)(DWORD)(*(ByteLine[dy]++));
04967 
04968                 INT32 dr=LR-CR;
04969                 INT32 dg=LG-CG;
04970                 INT32 db=LB-CB;
04971                 if (((dr*dr)+(dg*dg)+(db*db))<=Thresh)
04972                 {
04973                     s+=v;
04974                     r+=v*LR;
04975                     g+=v*LG;
04976                     b+=v*LB;
04977                 }
04978                 ByteLine[dy]++; // past reserved byte
04979             }
04980             ByteLine[dy]-=16; // we've advanced it 5 and we only wanted to advance it 1.
04981         }
04982 
04983         if (s) // should always be true as centre always has value
04984         {
04985             if (Mono)
04986             {
04987                 r=r+g+b;                                // Sum RGB
04988                 s*=3;                                   // Divide by 3x more
04989                 r+=s>>1;                                // Add rounding factor
04990                 r=r/s;                                  // Find result
04991                 if (r<0) r=0;                           // Clip
04992                 if (r>255) r=255;
04993             }
04994             else
04995             {
04996                 r+=s>>1;
04997                 g+=s>>1;
04998                 b+=s>>1;
04999                 r=r/s;
05000                 g=g/s;
05001                 b=b/s;
05002                 if (r<0) r=0;                           // Clip
05003                 if (r>255) r=255;
05004                 if (g<0) g=0;                           // Clip
05005                 if (g>255) g=255;
05006                 if (b<0) b=0;                           // Clip
05007                 if (b>255) b=255;
05008             }   
05009         }
05010         else
05011         {
05012             ERROR3("BfxALU::SlowRemoveDither should never get here!");
05013         }
05014 
05015         *(OutputLine++)=(BYTE)(DWORD)b;
05016         *(OutputLine++)=(BYTE)(DWORD)g;
05017         *(OutputLine++)=(BYTE)(DWORD)r;
05018         OutputLine++; // skip reserved byte
05019     }
05020     return;
05021 }
05022 
05023 #ifndef EXCLUDE_FROM_XARALX
05024 /********************************************************************************************
05025 
05026 >   BOOL BfxALU::SpecialEffect(KernelBitmap * * ppOutput, double * Matrix, BfxSpecialEffect Type)
05027                     
05028     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
05029     Created:    28/01/95
05030     Inputs:     Brightness & Contast (-127 to +127)
05031     Outputs:    *ppOutput = a pointer to the output bitmap
05032     Returns:    TRUE if succeeded, FALSE & error set if not
05033     Purpose:    A new bitmap is created as per function name
05034     Errors:     Error 2 if init hasn't been called or GDraw fails
05035                 Error 3 if windows and some other Oil layer are stangely mixed...
05036     Scope:      Public
05037     SeeAlso:    -
05038 
05039 ********************************************************************************************/
05040 
05041 BOOL BfxALU::SpecialEffect(KernelBitmap * * ppOutput, double * Matrix, BfxSpecialEffect Type)
05042 {
05043     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
05044     ERROR2IF((!Matrix) && (Type == BFX_SFX_USER), FALSE, "Must pass a matrix for BFX_SFX_USER");
05045     char matrix[9];
05046     if (Type==BFX_SFX_USER) for (INT32 i=0; i<=8; i++) matrix[i]=(char)(INT32)Matrix[i];
05047     
05048     INT32 AccusoftHandle = -1;
05049     if (!MakeAccusoftHandle(&AccusoftHandle)) return FALSE;
05050 
05051     if ( (((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader).biBitCount <=8 )
05052     {
05053         INT32 result = AccusoftFilters::pfnIMG_promote_24(AccusoftHandle);
05054         if (result < 0)
05055         {
05056             AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
05057             ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
05058         }
05059     }
05060 
05061     INT32 result = AccusoftFilters::pfnIMG_process_bitmap(AccusoftHandle, (INT32) Type, matrix);
05062     if (result < 0)
05063     {
05064         AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
05065         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
05066     }
05067     UINT32 res = _R(IDS_BFX_EFFECTNAME0);
05068     switch (Type)
05069     {
05070         case BFX_SFX_USER:
05071             res=_R(IDS_BFX_EFFECTNAME0);
05072             break;
05073         case BFX_SFX_ISOLATEPOINTS:
05074             res=_R(IDS_BFX_EFFECTNAME1);
05075             break;
05076         case BFX_SFX_EDGE:
05077             res=_R(IDS_BFX_EFFECTNAME2);
05078             break;
05079         case BFX_SFX_HEDGE:
05080             res=_R(IDS_BFX_EFFECTNAME3);
05081             break;
05082         case BFX_SFX_VEDGE:
05083             res=_R(IDS_BFX_EFFECTNAME4);
05084             break;
05085         case BFX_SFX_P45EDGE:
05086             res=_R(IDS_BFX_EFFECTNAME5);
05087             break;
05088         case BFX_SFX_N45EDGE:
05089             res=_R(IDS_BFX_EFFECTNAME6);
05090             break;
05091         case BFX_SFX_LAPLACIAN:
05092             res=_R(IDS_BFX_EFFECTNAME7);
05093             break;
05094         case BFX_SFX_DIALATION:
05095             res=_R(IDS_BFX_EFFECTNAME8);
05096             break;
05097         case BFX_SFX_ROBERTS:
05098             res=_R(IDS_BFX_EFFECTNAME9);
05099             break;
05100         default:
05101             res=_R(IDS_BFX_EFFECTNAME0);
05102             break;
05103     }
05104 
05105         return MakeKernelBitmap(AccusoftHandle, ppOutput, FALSE, &(B->ActualBitmap->GetName()), res);
05106 }
05107 
05108 /********************************************************************************************
05109 
05110 >   BOOL BfxALU::Resize(KernelBitmap * * ppOutput, INT32 Width, INT32 Height, BOOL LinearInterpolation)
05111                     
05112     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
05113     Created:    28/01/95
05114     Inputs:     Brightness & Contast (-127 to +127)
05115     Outputs:    *ppOutput = a pointer to the output bitmap
05116     Returns:    TRUE if succeeded, FALSE & error set if not
05117     Purpose:    A new bitmap is created as per function name
05118     Errors:     Error 2 if init hasn't been called or GDraw fails
05119                 Error 3 if windows and some other Oil layer are stangely mixed...
05120     Scope:      Public
05121     SeeAlso:    -
05122 
05123 ********************************************************************************************/
05124 
05125 BOOL BfxALU::Resize(KernelBitmap * * ppOutput, INT32 Width, INT32 Height, BOOL LinearInterpolation)
05126 {
05127     ERROR2IF((!ppOutput),FALSE, "BfxALU output parameter must be non-null");
05128         
05129     // Accusoft have a bug on their linear interpolation code which puts a grey line down
05130     // the left hand side of the image, so we must bodge it!!!!!
05131     BOOL DoBodge = FALSE;
05132     INT32 bpp = B->GetBPP();
05133 #ifdef BODGE_ACCUSOFT_RESIZE
05134     if (LinearInterpolation && (bpp == 4 || bpp == 8 || bpp == 24 || bpp == 32))
05135         DoBodge = TRUE;
05136 #endif
05137 
05138     INT32 AccusoftHandle = -1;
05139     if (!MakeAccusoftHandle(&AccusoftHandle, DoBodge))
05140         return FALSE;
05141 
05142     INT32 result = 0;
05143     if (LinearInterpolation)
05144     {
05145         // Accusoft require a 24bpp bitmap for linear interpolation
05146         // If less than or equal 8bpp 
05147 //      if ( (((CWxBitmap *)(B->ActualBitmap))->BMInfo->bmiHeader).biBitCount <=8 ) SCARY!!!!!
05148         INT32 NewWidth = Width;
05149 #ifdef BODGE_ACCUSOFT_RESIZE
05150         // If doing the bodge to get around the Accusoft 24bpp linear interpolation problem, then
05151         // we make the bitmap 3 times as wide as it should be to hide the grey pixels on the left
05152         // hand side when we remove this extra space after the inerpolation has happened.
05153         // We therefore need to make the resize 3 times the width it should be.
05154         if (DoBodge)
05155             NewWidth *= 3;
05156 #endif
05157         if (bpp <= 8)
05158         {
05159             result = AccusoftFilters::pfnIMG_promote_24(AccusoftHandle);
05160             if (result < 0)
05161             {
05162                 AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
05163                 ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
05164             }
05165         }
05166         result = AccusoftFilters::pfnIMG_resize_bitmap_interp(AccusoftHandle, (INT32) NewWidth, (INT32) Height);
05167     }
05168     else
05169     {
05170         // Do a straight resize
05171         result = AccusoftFilters::pfnIMG_resize_bitmap(AccusoftHandle, (INT32) Width, (INT32) Height);
05172     }
05173     
05174     if (result < 0)
05175     {
05176         AccusoftFilters::pfnIMG_delete_bitmap(AccusoftHandle);
05177         ERROR1(FALSE, _R(IDE_ACCUSOFT_ERROR) - result);
05178     }
05179     
05180     return MakeKernelBitmap(AccusoftHandle, ppOutput, FALSE, &(B->ActualBitmap->GetName()), _R(IDS_BFX_RESIZE), DoBodge);
05181 }
05182 #endif
05183 
05184 /********************************************************************************************
05185 
05186 >   BOOL BfxALU::AdjustBrightnessContrastColour(LPBYTE Source, LPBYTE Dest, INT32 Size, INT32 Width, INT32 Height,
05187                             INT32 Brightness, INT32 Contrast, INT32 Colour, BOOL SingleChannel)
05188                     
05189     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
05190     Created:    28/01/95
05191     Inputs:     Source = pointer to source bytes
05192                 Size = size of entries
05193                 Brightness, Contast, Colour (-127 to +127)
05194                 SingleChannel set if just to do a .. urm ... single channel.
05195     Outputs:    Dest bytes filled in
05196     Returns:    TRUE if succeeded, FALSE & error set if not
05197     Purpose:    A new bitmap is created as per function name
05198     Errors:     Error 2 if init hasn't been called or GDraw fails
05199                 Error 3 if windows and some other Oil layer are stangely mixed...
05200     Scope:      Public
05201     SeeAlso:    -
05202 
05203 ********************************************************************************************/
05204 
05205 BOOL BfxALU::AdjustBrightnessContrastColour(LPBYTE Source, LPBYTE Dest, INT32 Size, INT32 Width, INT32 Height,
05206                             INT32 Brightness, INT32 Contrast, INT32 Colour, BOOL SingleChannel)
05207 {
05208     // We make a LUT which is Output = LUT[gun, sumofguns]
05209 
05210     double dBrightness = (Brightness*1.0)/127.0   *0.75; // *0.75 is the 'Charles' factor.
05211     double dContrast = pow(2.0,3.0*(Contrast*1.0)/127.0);
05212     double dColour = pow(2.0,3.0*(Colour*1.0)/127.0);
05213 
05214     // GunOut = dBrightness + dContrast * ((GunSum/3) + dColour * (GunIn- GunSum/3)) + (1-dContrast)*0.5;
05215     //        = (dBrightness + ((1-dContrast)*0.5)) + GunSum * (dContrast/3.0 * (1-dColour)) + GunIn * (dContrast*dColour)
05216 
05217     double PropA = dContrast * dColour;
05218     double PropB = dContrast / 3.0 * (1.0-dColour);
05219     double Offset = dBrightness + (1.0-dContrast)*0.5;
05220 
05221     INT32 pa=(INT32)(PropA*(1<<15));
05222     INT32 pb=(INT32)(PropB*(1<<15));
05223     INT32 po=(INT32)(Offset*((1<<15)*255)+/* for rounding */(1<<14));
05224 
05225     BYTE * Data = (BYTE *) CCMalloc(3*256*256);
05226     if (!Data) return FALSE; // error already set
05227 
05228     // Please note how we're *NOT* using doubles in the loop as that's
05229     // sooooo sloooooow on 486SX. We use 17.15 arithmetic throughout
05230 
05231 #ifndef FASTLINEARABK
05232     INT32 a;
05233     INT32 b;
05234     INT32 r;
05235     for (a=0; a<256; a++) for (b=0; b<256*3; b++)
05236     {
05237         r=(a*pa+b*pb+po)>>15; /* we did the rounding in the offset calc */
05238         LUTBYTE(a,b)=(r<0)?0:((r>255)?255:(BYTE)(INT32)(r));
05239     }
05240 #else
05241     FastLinearABK(Data, pa, pb, po, 256*3);
05242 #endif
05243     
05244     DWORD Sum;
05245 
05246     if (!SingleChannel)
05247     {
05248         for (INT32 y = 0 ;y<Height; y++)
05249         {
05250             for (INT32 x = 0; x<Width; x++)
05251             {
05252                 Sum=((DWORD)Source[0])+((DWORD)Source[1])+((DWORD)Source[2]);
05253                 Dest[0]=LUTBYTE(Source[0], Sum);
05254                 Dest[1]=LUTBYTE(Source[1], Sum);
05255                 Dest[2]=LUTBYTE(Source[2], Sum);
05256                 Source+=Size;
05257                 Dest+=Size;
05258             }
05259             Source = (LPBYTE)(void *)((((UINT_PTR)(void *)Source) +3)&(~3));
05260             Dest = (LPBYTE)(void *)((((UINT_PTR)(void *)Dest) +3)&(~3));
05261         }
05262     }
05263     else
05264     {
05265         for (INT32 y = 0 ;y<Height; y++)
05266         {
05267             for (INT32 x = 0; x<Width; x++)
05268             {
05269                 *Dest=LUTBYTE((*Source), (*Source));
05270                 Source+=Size;
05271                 Dest+=Size;
05272             }
05273             Source = (LPBYTE)(void *)((((UINT_PTR)(void *)Source) +3)&(~3));
05274             Dest = (LPBYTE)(void *)((((UINT_PTR)(void *)Dest) +3)&(~3));
05275         }
05276     }
05277 
05278     CCFree(Data);   
05279     return TRUE;
05280 }
05281 
05282 /********************************************************************************************
05283 
05284 >   void BfxALU::ConvertScanLineToDWORD(KernelBitmap * pBitmap, INT32 Line, DWORD * pBuffer)
05285                     
05286     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
05287     Created:    28/01/95
05288     Inputs:     pBitmap pointer to bitmap
05289                 Line = line number
05290                 pBuffer = buffer
05291     Outputs:    None
05292     Returns:    None
05293     Purpose:    Converts a scanline in the bitmap to a 32 bit scanline
05294     Errors:     None
05295     Scope:      Protected
05296     SeeAlso:    -
05297 
05298 THIS FUNCTION HAS NO ERROR CHECKING. How does it smell? TERRIBLE
05299 
05300 (i.e. you are expected to do your own.). This is because it must be **FAST**
05301 
05302 ********************************************************************************************/
05303 
05304 void BfxALU::ConvertScanLineToDWORD(KernelBitmap * pBitmap, INT32 Line, DWORD * pBuffer)
05305 {
05306     BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)(pBitmap->ActualBitmap))->BMInfo->bmiHeader);
05307     RGBQUAD * pPal=(((CWxBitmap *)(pBitmap->ActualBitmap))->BMInfo->bmiColors);
05308     void * VImage = (((CWxBitmap *)(pBitmap->ActualBitmap))->BMBytes);
05309     INT32 Width=pBMI->biWidth;
05310     switch (pBMI->biBitCount)
05311     {
05312         case 32:
05313         {
05314             DWORD * Source = &(((DWORD *) VImage)[Width*Line]);
05315             for (INT32 w=0; w<Width; w++) pBuffer[w]=Source[w] & 0x00ffffff;
05316             return;
05317         }
05318         break; // not really needed
05319         case 24:
05320         {
05321             BYTE * Source = &(((BYTE *) VImage)[(((Width*3)+3)&~3)*Line]);
05322             INT32 b=0;
05323             for (INT32 w=0; w<Width; w++)
05324             {   
05325                 pBuffer[w]=(((INT32)(Source[b])))|(((INT32)(Source[b+1]))<<8)|(((INT32)(Source[b+2]))<<16);
05326                 b+=3; // Grrr MS bug prevents us from doing this efficiently
05327             }
05328             return;
05329         }
05330         break; // not really needed
05331         case 8:
05332         {
05333             BYTE * Source = &(((BYTE *) VImage)[((Width+3)&~3)*Line]);
05334             for (INT32 w=0; w<Width; w++)
05335             {
05336                 pBuffer[w]=0x00ffffff & *((DWORD *)(&pPal[Source[w]]));
05337             }
05338             return;
05339         }
05340         break; // not really needed
05341         case 4:
05342         {
05343             BYTE * Source = &(((BYTE *) VImage)[(((Width+7)&~7)>>1)*Line]);
05344             for (INT32 w=0; w<Width; w++)
05345             {
05346                 pBuffer[w]=0x00ffffff & *((DWORD *)(&pPal[ (Source[w>>1]>>( (1-(w&1)) <<2) )&0xf]));
05347             }
05348             return;
05349         }
05350         break; // not really needed
05351         case 2:
05352         {
05353             BYTE * Source = &(((BYTE *) VImage)[(((Width+15)&~15)>>2)*Line]);
05354             for (INT32 w=0; w<Width; w++)
05355             {
05356                 pBuffer[w]=0x00ffffff & *((DWORD *)(&pPal[ (Source[w>>2]>>( (3-(w&3)) <<1) )&0x3]));
05357             }
05358             return;
05359         }
05360         break; // not really needed
05361         case 1:
05362         {
05363             BYTE * Source = &(((BYTE *) VImage)[(((Width+31)&~31)>>3)*Line]);
05364             for (INT32 w=0; w<Width; w++)
05365             {
05366                 pBuffer[w]=0x00ffffff & *((DWORD *)(&pPal[ (Source[w>>3]>>( (7-(w&7)) /*<<0*/) )&0x1]));
05367             }
05368             return;
05369         }
05370         break; // not really needed
05371         default:
05372         {
05373             ERROR3("BPP not supported");
05374         }
05375         break; // not really needed
05376     }
05377     return; // not really needed
05378 }
05379 
05380 /********************************************************************************************
05381 
05382 >   void BfxALU::ConvertScanLineToDWORD(KernelBitmap * pBitmap, INT32 Line, DWORD * pBuffer)
05383                     
05384     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
05385     Created:    28/01/95
05386     Inputs:     pBitmap pointer to bitmap
05387                 Line = line number
05388                 pBuffer = buffer
05389     Outputs:    None
05390     Returns:    None
05391     Purpose:    Converts 32 bit scanline to a scanline in the bitmap
05392     Errors:     None
05393     Scope:      Protected
05394     SeeAlso:    -
05395 
05396 THIS FUNCTION HAS NO ERROR CHECKING. How does it smell? TERRIBLE
05397 
05398 (i.e. you are expected to do your own.). This is because it must be **FAST**
05399 
05400 ********************************************************************************************/
05401 
05402 void BfxALU::ConvertScanLineFromDWORD(KernelBitmap * pBitmap, INT32 Line, DWORD * pBuffer)
05403 {
05404     return;
05405 }
05406 
05407 #endif // EXCLUDE_FROM_RALPH
05408 #endif //WEBSTER

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