grndbmp.cpp

Go to the documentation of this file.
00001 // $Id: grndbmp.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 
00099 // RenderRegion to render into a bitmap
00100 
00101 // This file used to use the ScaleFactor as part of its code to work
00102 // out the size of a bitmap.  Due to changes I have made elsewhere in
00103 // the code, the scale factor should always be one (DPI is used to
00104 // generate bitmaps of different sizes).  Therefore, I have removed
00105 // all references to ScaleFactor in this code and replaced them with
00106 // ERROR3s.  -- Jonathan Payne, 8/9/2000
00107 
00108 // The above comment fails to take into account the need for the 
00109 // feathering code to know the scale factor so it can adjust the size of 
00110 // its bitmaps correctly when rendering to a bitmap for printing or on-
00111 // screen preview of separations.  This causes feathers to be rendered 
00112 // incorrectly at any scale factor other than 100%!!!!!
00113 // Gerry - 15/04/2004
00114 
00115 #include "camtypes.h"
00116 #include "grndbmp.h"
00117 #include "colcontx.h"
00118 //#include "bitmap.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00119 #include "oilbitmap.h"
00120 //#include "dibutil.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00121 //#include "dibconv.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00122 #include "osrndrgn.h"
00123 //#include "outptdib.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00124 #include "palman.h"
00125 #include "progress.h"
00126 #include "GDrawIntf.h"          // GAT
00127 
00128 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00129 
00130 //#include "app.h"      // GetApplication - in camtypes.h [AUTOMATICALLY REMOVED]
00131 #include "bmapprev.h"
00132 
00133 #define FIXEDBANDSIZE 512
00134 
00135 CC_IMPLEMENT_DYNAMIC( GRenderBitmap, GRenderDIB )
00136 #if !defined(EXCLUDE_FROM_RALPH)
00137 CC_IMPLEMENT_DYNAMIC( GRenderOptPalette, GRenderBitmap )
00138 #endif
00139 
00140 #define new CAM_DEBUG_NEW
00141 
00142 #if !defined(EXCLUDE_FROM_RALPH)
00143 // Preference as to whether we round the colours of a 1bpp optimised palette
00144 BOOL GRenderOptPalette::DoTwoColourRoundingToPrimary = TRUE;
00145 #endif
00146 
00147 
00148 // This is a static GDraw context, which is initialised to use a 256-colour greyscale palette
00149 // This is used when rendering airbrushed strokes, which need to generate 8bpp transparency
00150 // bitmaps. initialising this context can take 2 seconds or so, so we only do it once
00151 // (on demand, the first time it is actually needed).
00152 GDrawContext *GRenderBitmap::pGreyscaleContext = NULL;
00153 
00154 BOOL GRenderOptPalette::DoGDrawConversion = TRUE;
00155 BOOL GRenderOptPalette::UseOldPalette = TRUE;
00156 
00157 /********************************************************************************************
00158 
00159 >   GRenderBitmap::GRenderBitmap(DocRect ClipRegion, Matrix ConvertMatrix, FIXED16 ViewScale, 
00160                              UINT32 Depth, INT32 dpi, BOOL Printing, UINT32 Dither, LPLOGPALETTE pPalette, 
00161                              BOOL AutoConvert)
00162 
00163     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00164     Created:    15/8/94
00165     Inputs:     -
00166     Outputs:    -
00167     Returns:    -
00168     Purpose:    GRenderBitmap constructor. Doesn't do anything actually, just calls base class.
00169                 INT32 dpi changed to double dpi (12/12/95) to improve the range of values allowed
00170                 at the < 1000dpi settings that we will be using.
00171     Errors:     -
00172     SeeAlso:    GRenderRegion::GRenderRegion
00173 
00174 ********************************************************************************************/
00175 
00176 GRenderBitmap::GRenderBitmap(DocRect ClipRegion, Matrix ConvertMatrix, FIXED16 ViewScale, 
00177                              UINT32 Depth, double dpi, BOOL Printing, UINT32 Dither, LPLOGPALETTE pPalette, 
00178                              BOOL AutoConvert)
00179     : GRenderDIB( ClipRegion, ConvertMatrix, ViewScale, Depth, dpi)
00180 {
00181     // normally our colour context is obtained by RenderRegion::InitDevice,
00182     // but sadly this requires a RenderWindow, which we ain't got. There must
00183     // be a better way than this, but don't knock it. This must be done BEFORE
00184     // InitDevice as that renders default attributes, which tend to rely on a colour context
00185 
00186     if (RenderView==NULL)
00187         CurrentColContext = ColourContext::GetGlobalDefault(COLOURMODEL_RGBT);
00188 
00189     // we do not want to overlap the bands by default
00190     OverlapBands = FALSE;
00191 
00192     // We do want to render bottom to top by default
00193     RenderBottomToTop = TRUE;
00194 
00195     // Render flag stuff
00196     RenderFlags.Printing = Printing;
00197 
00198     // This next bit was added to cope with the conversion needed when using certain
00199     // dithering techniques
00200     DitherType = Dither;
00201     uOutputDepth = Depth;       // If different from the actual RR bpp, then the bitmap will
00202                                 // be converted before output
00203     lpOutputInfo = NULL;    
00204     lpOutputBits = NULL;    
00205 
00206     m_dXCentralAdjust = 0;
00207     m_dYCentralAdjust = 0;
00208 
00209     pConvPalette = pPalette;
00210 
00211     if (AutoConvert && uOutputDepth<32)
00212     {
00213         // The dithering we are using requires us to render to 32bpp and then convert it down
00214         // to our output bpp at the end
00215 
00216         // Force rendering to 32bpp, we will convert it to 'Depth' at the end
00217         uBitmapDepth = 32;
00218     }
00219 
00220     pPreviousGDrawContext = NULL;
00221 }
00222 
00223 /********************************************************************************************
00224 
00225 >   static BOOL GRenderBitmap::DitheringNeeds32bpp(UINT32 Dither)
00226 
00227     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00228     Created:    28/5/96
00229     Inputs:     -
00230     Outputs:    -
00231     Returns:    -
00232     Purpose:    -
00233     Errors:     -
00234 
00235 ********************************************************************************************/
00236 
00237 BOOL GRenderBitmap::DitheringNeeds32bpp(UINT32 Dither)
00238 {
00239     return (Dither != XARADITHER_ORDERED_GREY);
00240 }
00241 
00242 /********************************************************************************************
00243 
00244 >   BOOL GRenderBitmap::StartRender()
00245 
00246     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00247     Created:    15/8/94
00248     Inputs:     
00249     Outputs:    
00250     Returns:    TRUE if worked, FALSE if failed
00251     Purpose:    Uses base class to do normal stuff, then fills bitmap with White as a sort
00252                 of paper background.
00253     Errors:     -
00254     SeeAlso:    GRenderDIB::StartRender
00255 
00256 ********************************************************************************************/
00257 
00258 BOOL GRenderBitmap::StartRender()
00259 {
00260     // call base class first
00261     const BOOL ok = GRenderDIB::StartRender();
00262     if (!ok)
00263         return FALSE;
00264 /*
00265     In an attempt to standardise things, all bmp initing is now done by the
00266     InitBmpBits() virtual function. I am pretty sure that in the past, double
00267     bmp initialisation was occuring
00268     ie here, and in the GetDrawContext()->SetupBitmap(..) function as well.
00269 
00270 */
00271     // set bitmap size field so gets written out correctly
00272     pBitmapInfo->bmiHeader.biXPelsPerMeter = (INT32)((PixelsPerInch * 10000 ) / 254);
00273     //lpBitmapInfo->bmiHeader.biXPelsPerMeter = Mul32Div32( PixelsPerInch, 10000, 254 );
00274     pBitmapInfo->bmiHeader.biYPelsPerMeter = pBitmapInfo->bmiHeader.biXPelsPerMeter;
00275 
00276     // done OK
00277     return TRUE;
00278 }
00279 
00280 /********************************************************************************************
00281 
00282 >   virtual WinRect GRenderBitmap::CalculateWinRect( const Matrix& RenderMatrix, const DocRect& docrect,
00283                                                      const double dpi)
00284 
00285     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00286     Created:    4/10/96
00287     Inputs:     DocRect is a rectangle on document co-ords.
00288                 dpi is the resolution of the device we are rendering to
00289     Outputs:    RenderMatrix is the rendering matrix, may have e anf f components changed by the call
00290     Returns:    Object containing the new rectangle coordinates.                
00291     Purpose:    To convert a rectangle in Doc coordinates to a rectangle in Win coordinates
00292                 taking account of the destination dpi rather than assuming screen dpi.
00293                 Virtual so that it can be overriden by different render regions if so required.
00294     SeeAlso:    OSRenderRegion::DocRectToWin;
00295 
00296 ********************************************************************************************/
00297 
00298 WinRect GRenderBitmap::CalculateWinRect( Matrix& RenderMatrix, const DocRect& docrect,
00299                                          const double dpi)
00300 {
00301     // lets get the Rect into screen co-ords so we can use our big screen bitmap
00302     // Use a version of OSRenderRegion::DocRectToWin that uses the actual dpi we have stored
00303     // in PixelsPerInch and that tries to sort out the pixel problems
00304     return OSRenderRegion::BitmapDocRectToWin( RenderMatrix, docrect, dpi );
00305 }
00306 
00307 /********************************************************************************************
00308 
00309 >   virtual GMATRIX GRenderBitmap::MakeGavinMatrix(Matrix NewRenderMatrix, DocRect ClipRect, double dPixelsPerInch, BOOL bMasterCapture)
00310 
00311     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> (from Will (from Phil code))
00312     Created:    ??/??/2004
00313     Inputs:     The Kernel Matrix and cliprect to use to create the Gavin Matrix.
00314     Returns:    TRUE if the GMatrix was created ok.
00315     Purpose:    Make a Gavin Matrix out of a Kernel Matrix
00316     SeeAlso:    GRenderRegion::SetGavinMatrix
00317     Notes:      Doesn't rely on current state of CurrentClipRect like the above version
00318 
00319 ********************************************************************************************/
00320 
00321 GMATRIX GRenderBitmap::MakeGavinMatrix(Matrix NewRenderMatrix, DocRect ClipRect, double dPixelsPerInch, BOOL bMasterCapture)
00322 {
00323     GMATRIX gmat;
00324     // Get the scale factors from the original render matrix
00325     FIXED16 abcd[4];
00326     NewRenderMatrix.GetComponents( abcd, NULL );
00327 
00328     // Use them to call DocRect to win on the clipping region, without attempting any translation.
00329     // Thus, the DocCoord cliprect gets turned directly into a Windows pixel values cliprect!
00330     Matrix UnscrolledRender(abcd[0], abcd[1], abcd[2], abcd[3], 0, 0);
00331 
00332     // in order to get Gavin's matrix calcs to agree with ours, we have to force him to
00333     // round before shifting down. We do this by adding half a pixel to the offsets in
00334     // his matrices. There is a school of thought which says that his matrix code
00335     // should be made to round, but it might have unpleasant side-effects. For now, we do
00336     // it this way. A pixel is 1<<(FX+16), so half a pixel is this incantation:
00337 
00338     // sjk's (5/12/00) preferred version as this works with the decimal places that may be in PixelsPerInch
00339     const XLONG Mult = (INT32)(dPixelsPerInch*(double)(1 << FX) + 0.5);
00340 
00341     gmat.AX = ( (XLONG)abcd[0].GetRawLong() * Mult ) / XLONG(72000);
00342     gmat.AY = ( (XLONG)abcd[1].GetRawLong() * Mult ) / XLONG(72000);
00343     gmat.BX = ( (XLONG)abcd[2].GetRawLong() * Mult ) / XLONG(72000);
00344     gmat.BY = ( (XLONG)abcd[3].GetRawLong() * Mult ) / XLONG(72000);
00345 
00346     // Work out the offsets in the GMatrix, taking into account special handling
00347     // to centralise the drawing within the bitmap
00348     // If we're making the matrix for the master capture
00349     // Then DO centralise teh rendering within the whole-pixel bitmap
00350     // Else DON'T centralise again, just re-use the offsets we calculated the first time
00351     OSRenderRegion::CalculateGavinOffsetsWinRect(UnscrolledRender, ClipRect, dPixelsPerInch, &gmat, bMasterCapture, &m_dXCentralAdjust, &m_dYCentralAdjust);
00352 
00353     return gmat;
00354 }
00355 
00356 /********************************************************************************************
00357 
00358 >   GRenderBitmap::~GRenderBitmap()
00359 
00360     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00361     Created:    15/8/94
00362     Inputs:     -
00363     Outputs:    -
00364     Returns:    -
00365     Purpose:    GRenderBitmap destructor. Frees up the bitmap.
00366     Errors:     -
00367 
00368 ********************************************************************************************/
00369 
00370 GRenderBitmap::~GRenderBitmap()
00371 {
00372     // we should NOT delete the CurrentColContext cos we didn't alloc it - we just
00373     // got a pointer to something allocated by somebody else
00374 
00375     if (lpOutputInfo!=NULL || lpOutputBits!=NULL)
00376     {
00377         // Free up the conversion bitmap
00378         FreeDIB(lpOutputInfo, lpOutputBits);
00379         lpOutputInfo = NULL;
00380         lpOutputBits = NULL;
00381     }
00382 
00383     // Free up the bitmap here, as the call to FreeLPBits in the
00384     // GRenderDIB will not call the correct version (the virtual-ness will be
00385     // broken as it is called from a destructor
00386     if (pBitmapInfo!=NULL)
00387     {
00388         // NB Export rendering can be cancelled by user
00389         // Hence can be in the middle of offscreen rendering at this point
00390         FreeOffscreenState();
00391         pBitmapInfo = NULL;
00392         pBits = NULL;
00393     }
00394 
00395     // Make sure we restore the state of the GDrawContext if our client forgot to 
00396     // turn off the context replacement. See UseGreyscaleContextDangerous(), below.
00397     if (pPreviousGDrawContext != NULL)
00398     {
00399         if (SetTempDrawContext(pPreviousGDrawContext) != pGreyscaleContext)
00400         {
00401             ERROR3("Not pGreyscaleContext when restoring");
00402         }
00403         pPreviousGDrawContext = NULL;
00404     }
00405 }
00406 
00407 
00408 
00409 /********************************************************************************************
00410 
00411 >   INT32 GRenderBitmap::GetNumBands()
00412 
00413     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00414     Created:    12/5/95
00415     Returns:    The number of strips the banded region will take.
00416     Purpose:    The bitmap export and printing both need to know how many bands there will
00417                 be when doing banded rendering. Since the bands are of a fixed size in
00418                 GRenderBitmaps we are able to work out how many there will be before hand.
00419                 This function tells you how many bands there would be if you were to
00420                 banded render this region.
00421 
00422 ********************************************************************************************/
00423 
00424 INT32 GRenderBitmap::GetNumBands()
00425 {
00426     // Find out how big in millipoints we can do
00427     double TruePixelHeight = 72000.0 / PixelsPerInch; //.MakeDouble();
00428 
00429 // Removed due to problems with printing feathers (see comment at top of file)
00430 //  ERROR3IF(ScaleFactor.MakeDouble() != 1.0, "ScaleFactor not 1, see comment at top of grndbmp.cpp");
00431 
00432     // Work out how many scan lines That works out to be
00433     INT32 Height = (INT32)((double)RegionRect.Height() / TruePixelHeight);
00434 
00435     // count the bands
00436     INT32 Bands = 0;
00437     while (Height>0)
00438     {
00439         Bands++;
00440         Height -= FIXEDBANDSIZE;
00441     }
00442 
00443     // say how many we found
00444     return Bands;
00445 }
00446 
00447 /********************************************************************************************
00448 
00449 >   INT32 GRenderBitmap::GetFullRegionHeight()
00450 
00451     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00452     Created:    17/5/95
00453     Returns:    The total height of the render region.
00454     Purpose:    The bitmap export needs to know what the total height of the bitmap is
00455                 when doing banded rendering as the region will be created the height of the
00456                 band and not the full height of the bitmap.
00457 
00458 ********************************************************************************************/
00459 
00460 INT32 GRenderBitmap::GetFullRegionHeight()
00461 {
00462     // Find out the actual size in pixels of this render region
00463     // Use the same method that is used to construct the matrix and we use in
00464     // the bitmap options dialog box to work out the size so that we are consistent 
00465     Matrix Identity;    // default construction is an identity matrix
00466     WinRect Rect = OSRenderRegion::BitmapDocRectToWin( Identity, RegionRect, PixelsPerInch );
00467     return Rect.height;
00468 }   
00469 
00470 
00471 /********************************************************************************************
00472 
00473 >   void GRenderBitmap::SetOverlapBands(BOOL NewVal)
00474 
00475     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00476     Created:    16/5/95
00477     Inputs:     TRUE to start overlapping bands, FALSE to switch overlapping off
00478     Purpose:    This function allows to you switch band overlapping on and off.
00479                 It is off by default. Bands need to be overlapped when printing to
00480                 stop the error at the edge of dither pattens.
00481 
00482 ********************************************************************************************/
00483 
00484 void GRenderBitmap::SetOverlapBands(BOOL NewVal)
00485 {
00486     OverlapBands = NewVal;
00487 }
00488 
00489 /********************************************************************************************
00490 
00491 >   void GRenderBitmap::SetOverlapBands(BOOL NewVal)
00492 
00493     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00494     Created:    17/5/95
00495     Inputs:     TRUE to render bottom to top, FALSE to render top to bottom
00496     Purpose:    This function allows to you switch the direction that the bands are rendered
00497                 in.
00498                 It is bottom to top by default. We need to switch the direction when exporting
00499                 as a bitmap as the Accusoft code needs it in both directions.
00500 
00501 ********************************************************************************************/
00502 
00503 BOOL GRenderBitmap::SetRenderBottomToTop(BOOL NewVal)
00504 {
00505     BOOL OldVal = RenderBottomToTop;
00506     RenderBottomToTop = NewVal;
00507     return OldVal;  
00508 }   
00509 
00510 
00511 /********************************************************************************************
00512 
00513 >   virtual BOOL GRenderBitmap::SetFirstBand()
00514 
00515     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00516     Created:    5/5/95
00517     Returns:    TRUE if it worked, FLASE if it failed
00518     Purpose:    Sets up for banded rendering. This class will always band the region into
00519                 128 pixel high bands.
00520 
00521 ********************************************************************************************/
00522 
00523 BOOL GRenderBitmap::SetFirstBand()
00524 {
00525     // if we are already banded, or we already have a bitmap, then stop looking
00526     // SMFIX we do want to come in here twice - once sometimes to do the palette, the second time to do the render
00527 //  if (IsBanded() || lpBitmapInfo!=NULL)
00528 //      return TRUE;
00529 
00530 //  ENSURE(GetCaptureDepth()==0, "Can't set a band while there are any captures running");
00531     ENSURE(GetCaptureDepth()==0 || MasterCaptureIsCurrent(), "Can't set a band while there are any non-master captures running\n");
00532 
00533     // They can be merged for the time being
00534     CanRegionBeMerged = TRUE;
00535 
00536     // Make sure the InitDevice has been called.
00537     if (!RenderFlags.ValidDevice)
00538     {
00539         // Device needs to be initialised
00540         if (!InitDevice())
00541         {
00542             // Something's gone wrong - inform the user.
00543             TRACE( _T("InitDevice failed in Render Region"));
00544             return FALSE;
00545         }
00546 
00547         // Make sure we don't do this again for this render region
00548         RenderFlags.ValidDevice = TRUE;
00549     }
00550 
00551     // Work out how many scan lines there are
00552     double TruePixelHeight = 72000.0 / PixelsPerInch; //.MakeDouble();
00553 // Removed due to problems with printing feathers (see comment at top of file)
00554 //  ERROR3IF(ScaleFactor.MakeDouble() != 1.0, "ScaleFactor not 1, see comment at top of grndbmp.cpp");
00555     INT32 Height = (INT32) ((double)(RegionRect.hi.y - RegionRect.lo.y) / TruePixelHeight);
00556 
00557     // Work out how many scan lines we could fit into the available ram
00558     INT32 MaxScanLines = FIXEDBANDSIZE;
00559 
00560     // See if we can do it
00561     if (MaxScanLines>=Height)
00562     {
00563         // No Banding needed
00564         IsRegionBanded = FALSE;
00565         IsWaitingForRAM = FALSE;
00566         IsLastBand = TRUE;
00567         return TRUE;
00568     }
00569     else
00570     {
00571         // Lets band this region then
00572         IsRegionBanded = TRUE;
00573         IsWaitingForRAM = FALSE;
00574         IsLastBand = FALSE;
00575         CanRegionBeMerged = FALSE;
00576 
00577         // Find out how big in millipoints we can do
00578         MILLIPOINT MaxHeight = (MILLIPOINT)(TruePixelHeight * (double)MaxScanLines);
00579 
00580         // Set up the new clip rect ready
00581         DocRect NewClipRect = CurrentClipRect;
00582         if (RenderBottomToTop)
00583         {
00584             // Render from the bottom upwards
00585             NewClipRect.hi.y = NewClipRect.lo.y + MaxHeight;
00586 
00587             // Sanity check
00588             if (NewClipRect.hi.y > CurrentClipRect.hi.y)
00589                 NewClipRect.hi.y = CurrentClipRect.hi.y;
00590         }
00591         else
00592         {
00593             // Render from the top downwards
00594             NewClipRect.lo.y = NewClipRect.hi.y - MaxHeight;
00595 
00596             // Sanity check
00597             if (NewClipRect.lo.y < CurrentClipRect.lo.y)
00598                 NewClipRect.lo.y = CurrentClipRect.lo.y;
00599         }
00600 
00601         // Set the new clip rect up ready for rendering
00602         SetClipRect(NewClipRect);       
00603         return TRUE;
00604     }
00605 }
00606 
00607 
00608 
00609 /********************************************************************************************
00610 
00611 >   virtual BOOL GRenderBitmap::GetNextBand()
00612 
00613     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00614     Created:    5/5/95
00615     Returns:    FALSE
00616     Purpose:    Since this class does not do banded rendering, there are never any more bands
00617 
00618 ********************************************************************************************/
00619 
00620 BOOL GRenderBitmap::GetNextBand()
00621 {
00622     // Go find the next band, if there is one.
00623     // Give back the memory we already have
00624     if (pBitmapInfo!=NULL)
00625     {
00626         FreeOffscreenState();
00627         pBitmapInfo = NULL;
00628         pBits = NULL;
00629     }
00630 
00631 //  ENSURE(GetCaptureDepth()==0, "Can't set a band while there are any captures running");
00632     ENSURE(GetCaptureDepth()==0 || MasterCaptureIsCurrent(), "Can't set a band while there are any non-master captures running\n");
00633 
00634     // if this is not a banded render region, then there are no more bands
00635     if (!IsBanded())
00636         return FALSE;
00637 
00638     if (RenderBottomToTop)
00639     {
00640         // Render from the bottom upwards
00641         // See if we are out of bands
00642         if ((CurrentClipRect.hi.y >= RegionRect.hi.y) || (IsLastBand))
00643             return FALSE;
00644     }
00645     else
00646     {
00647         // Render from the top downwards
00648         // See if we are out of bands
00649         if ((CurrentClipRect.lo.y <= RegionRect.lo.y) || (IsLastBand))
00650             return FALSE;
00651     }
00652 
00653     // we're going to need to be re-rendered
00654     IsPaperRendered = FALSE;
00655     IsInkRenderStarted = FALSE;
00656 
00657     // Get the number of scan lines we are prepared to do
00658     INT32 MaxScanLines = FIXEDBANDSIZE;
00659 
00660     // Work out how many scan lines there are left to do
00661     double TruePixelHeight = 72000.0 / PixelsPerInch; //.MakeDouble();
00662 // Removed due to problems with printing feathers (see comment at top of file)
00663 //  ERROR3IF(ScaleFactor.MakeDouble() != 1.0, "ScaleFactor not 1, see comment at top of grndbmp.cpp");
00664 
00665     INT32 Height = 0;
00666     if (RenderBottomToTop)
00667     {
00668         // Render from the bottom upwards
00669         Height = (INT32) ((double)(RegionRect.hi.y - CurrentClipRect.hi.y) / TruePixelHeight);
00670     }
00671     else
00672     {
00673         // Render from the top downwards
00674         Height = (INT32) ((double)(CurrentClipRect.lo.y - RegionRect.lo.y ) / TruePixelHeight);
00675     }
00676 
00677     // see if there are enought to bother with
00678     IsWaitingForRAM = FALSE;
00679 
00680     // Do what we can
00681     INT32 ScanLinesToDo = (MaxScanLines < Height) ? MaxScanLines : Height;
00682     if (ScanLinesToDo==Height)
00683         IsLastBand = TRUE;
00684     else
00685         IsLastBand = FALSE;
00686 
00687     // Find out how big in millipoints we can do
00688     MILLIPOINT MaxHeight = (MILLIPOINT) (TruePixelHeight * (double)ScanLinesToDo);
00689 
00690     DocRect NewClipRect = CurrentClipRect;
00691     if (RenderBottomToTop)
00692     {
00693         // Render from the bottom upwards
00694         // Set up the new clip rect ready
00695         NewClipRect.lo.y = CurrentClipRect.hi.y;
00696         NewClipRect.hi.y = NewClipRect.lo.y + MaxHeight;
00697 
00698         // if we want to overlap the bands, make an adjustment
00699         if (OverlapBands)
00700             NewClipRect.lo.y -= (INT32)(2 * TruePixelHeight);
00701 
00702         // Sanity check
00703         if ((NewClipRect.hi.y > RegionRect.hi.y) || (IsLastBand))
00704             NewClipRect.hi.y = RegionRect.hi.y;
00705     }
00706     else
00707     {
00708         // Render from the top downwards
00709         // Set up the new clip rect ready
00710         NewClipRect.hi.y = CurrentClipRect.lo.y;
00711         NewClipRect.lo.y = NewClipRect.hi.y - MaxHeight;
00712 
00713         // if we want to overlap the bands, make an adjustment
00714         if (OverlapBands)
00715             NewClipRect.hi.y -= (INT32)(2 * TruePixelHeight);
00716 
00717         // Sanity check
00718         if ((NewClipRect.lo.y < RegionRect.lo.y) || (IsLastBand))
00719             NewClipRect.lo.y = RegionRect.lo.y;
00720     }
00721         
00722     // Make sure that we are not dealing with an empty rect
00723     if (NewClipRect.Height()==0)
00724         return FALSE;
00725 
00726     // Set the new clip rect up ready for rendering
00727     SetClipRect(NewClipRect);
00728 
00729     // we're going to need to be re-rendered
00730     IsPaperRendered = FALSE;
00731     IsInkRenderStarted = FALSE;
00732     TRACEUSER("Gavin",_T("GRenderBitmap::GetNextBand - RenderFlags.Rendering = FALSE;\n"));
00733     RenderFlags.Rendering = FALSE;
00734 
00735     // Say it all worked
00736     return TRUE;
00737 }
00738 
00739 
00740 
00741 /********************************************************************************************
00742 
00743 >   LPBITMAPINFO GRenderBitmap::GetLPBits( INT32 Width, INT32 Height, INT32 Depth, LPBYTE*)
00744 
00745     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00746     Created:    5/5/95
00747     Inputs:     Width, Height - the width and height of the required bitmap
00748                 Depth - the bpp of the bitmap
00749     Returns:    Pointer to a bitmap header block
00750     Purpose:    Allocates a bitmap from the CCMalloc heap
00751 
00752 ********************************************************************************************/
00753 
00754 LPBITMAPINFO GRenderBitmap::GetLPBits( INT32 Width, INT32 Height, INT32 Depth, LPBYTE* lplpBits)
00755 {
00756     // Get a DIB out of the CCMalloc heap
00757     LPBITMAPINFO bmInfo = NULL;
00758     bmInfo = AllocDIB( abs(Width), abs(Height), Depth, lplpBits, NULL, FALSE);
00759 
00760     // return it.
00761     return bmInfo;
00762 }
00763 
00764 
00765 
00766 
00767 /********************************************************************************************
00768 
00769 >   void GRenderBitmap::FreeLPBits( LPBITMAPINFO, LPBYTE )
00770 
00771     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00772     Created:    5/5/95
00773     Purpose:    Frees the memory allocated in GetLPBits.
00774 
00775 ********************************************************************************************/
00776 
00777 void GRenderBitmap::FreeLPBits(LPBITMAPINFO lpBMI, LPBYTE lpB)
00778 {
00779     // Free up the memory. Not from Limited Heap
00780     FreeDIB(lpBMI, lpB, NULL, FALSE);
00781 }
00782 
00783 
00784 
00785 
00786 /********************************************************************************************
00787 
00788 >   BOOL GRenderBitmap::DisplayBits(LPBITMAPINFO lpDisplayBitmapInfo = NULL, LPBYTE lpDisplayBits = NULL)
00789 
00790     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00791     Created:    15/8/94
00792     Inputs:     -
00793     Outputs:    -
00794     Returns:    TRUE if worked, FALSE if failed.
00795     Purpose:    None really, except that the base class needs one, so we supply it.
00796     Errors:     -
00797 
00798 ********************************************************************************************/
00799 
00800 BOOL GRenderBitmap::DisplayBits(LPBITMAPINFO lpDisplayBitmapInfo, LPBYTE lpDisplayBits)
00801 {
00802     return TRUE;
00803 }
00804 
00805 /********************************************************************************************
00806 
00807 >   OILBitmap *GRenderBitmap::ExtractBitmap(LPLOGPALETTE pPalette)
00808 
00809     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00810     Created:    15/8/94
00811     Returns:    A pointer to a fresh OILBitmap, or NULL if failed. This OILBitmap has
00812                 Attach called on and will stay around after the RR is long gone. Returns
00813                 NULL if something bad happened. The OilBitmap is attached as a tempory bitmap
00814                 so if you want it to hang around as a permanent bmp, then don't forget to
00815                 do something about it.
00816     Purpose:    So that the caller may do what he likes with the bitmap.
00817 
00818 ********************************************************************************************/
00819 OILBitmap *GRenderBitmap::ExtractBitmap(LPLOGPALETTE pPalette)
00820 {
00821     if (pBitmapInfo && pBits)
00822     {
00823         LPBITMAPINFO lpConvInfo;    
00824         LPBYTE lpConvBits;  
00825 
00826         BOOL DeletePalette = FALSE;
00827 
00828         if(!pPalette)
00829         {
00830             pPalette = GetConversionPalette();
00831             if (pPalette && pPalette != pConvPalette)
00832                 DeletePalette = TRUE;
00833         }
00834 
00835         BOOL ok = DoOutputBitmapConversion(&lpConvInfo, &lpConvBits, pPalette);
00836         ERROR3IF(!ok, "Output conversion failed in GRenderBitmap::ExtractBitmap");
00837         if (!ok) 
00838         {
00839             if(DeletePalette)
00840                 CCFree(pPalette);
00841             return NULL;
00842         }
00843 
00844         CWxBitmap *OILBM = new CWxBitmap( lpConvInfo, lpConvBits );
00845         if (OILBM)
00846         {
00847             // Setup the Oil bitmap's pallete
00848             RGBQUAD* pOilPalette = OILBM->BMInfo->bmiColors;
00849             PALETTEENTRY* pPaletteEntry = pPalette->palPalEntry; 
00850 
00851             // Copy the palette entries over, we cannot copy a structure at a time because 
00852             // the bytes are in different orders
00853             for (DWORD i=0; i< OILBM->BMInfo->bmiHeader.biClrUsed; i++)
00854             {
00855                 pOilPalette[i].rgbBlue = pPaletteEntry[i].peBlue;
00856                 pOilPalette[i].rgbGreen = pPaletteEntry[i].peGreen;
00857                 pOilPalette[i].rgbRed = pPaletteEntry[i].peRed;
00858                 pOilPalette[i].rgbReserved = pPaletteEntry[i].peFlags;
00859             }
00860 
00861             if (lpConvBits == pBits)
00862             {
00863                 // ensure empty offscreen stack
00864 //#ifdef _DEBUG
00865 //              DumpCaptureStack();
00866 //#endif
00867                 ENSURE(MasterCaptureIsCurrent(), "Extract bitmap whilst rendering offscreen not finished!");
00868 
00869                 // bytes owned by CWxBitmap now - zero them so we don't free them up
00870                 SetBitmapPointers(NULL, NULL);
00871             }
00872 
00873             if (lpConvBits == lpOutputBits)
00874             {
00875                 // bytes owned by CWxBitmap now - zero them so we don't free them up
00876                 lpOutputInfo = NULL;
00877                 lpOutputBits = NULL;
00878             }
00879 
00880             if(DeletePalette)
00881                 CCFree(pPalette);
00882 
00883             return OILBM;
00884         }
00885 
00886         if(DeletePalette)
00887             CCFree(pPalette);
00888     }
00889 
00890     return NULL;
00891 }
00892 
00893 /********************************************************************************************
00894 
00895 >   OILBitmap *GRenderBitmap::ExtractBitmapCopy(LPLOGPALETTE pPalette = NULL, 
00896                                                 LPBITMAPINFO pMaskInfo = NULL, LPBYTE pMaskData = NULL,
00897                                                 INT32 MaskColour = -1,
00898                                                 BOOL LookForDuplicates = FALSE)
00899 
00900     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00901     Created:    28/5/96
00902     Inputs:     pPalette
00903                 pMaskInfo
00904                 pMaskData
00905                 MaskColour
00906                 LookForDuplicates   - if True then see if this bitmap is a duplicate of an existing
00907                                     one in the system
00908     Returns:    A pointer to a fresh OILBitmap, or NULL if failed. This OILBitmap has
00909                 Attach called on and will stay around after the RR is long gone. Returns
00910                 NULL if something bad happened. The OilBitmap is attached as a tempory bitmap
00911                 so if you want it to hang around as a permanent bmp, then don't forget to
00912                 do something about it.
00913 
00914                 The bitmap extracted is a COPY of the Regions bitmap data, which is left
00915                 untouched.
00916 
00917     Purpose:    So that the caller may do what he likes with the bitmap.
00918 
00919 ********************************************************************************************/
00920 OILBitmap *GRenderBitmap::ExtractBitmapCopy(LPLOGPALETTE pPalette, 
00921                                             LPBITMAPINFO pMaskInfo, LPBYTE pMaskData, 
00922                                             INT32 MaskColour, BOOL LookForDuplicates)
00923 {
00924     ERROR3IF(MaskColour==-2,"Someone`s using a MaskColour of -2!!! Please Correct!");
00925     BOOL bBrowserPalette = FALSE;
00926     
00927     if(!pPalette)
00928         bBrowserPalette = TRUE;
00929 
00930     if (pBitmapInfo && pBits)
00931     {
00932         LPBITMAPINFO    lpCopyInfo = NULL;
00933         LPBYTE          lpCopyBits = NULL;
00934         LPBITMAPINFO    lpConvInfo = NULL;  
00935         LPBYTE          lpConvBits = NULL;  
00936 
00937         BOOL DeletePalette = FALSE;
00938 
00939         if (!pPalette)
00940         {
00941             pPalette = GetConversionPalette();
00942             DeletePalette =  (pPalette && pPalette != pConvPalette);
00943         }
00944 
00945         if (pPalette && MaskColour >= 0 && MaskColour < pPalette->palNumEntries)
00946         {
00947             pPalette->palPalEntry[MaskColour].peRed     = 255;
00948             pPalette->palPalEntry[MaskColour].peGreen   = 255;
00949             pPalette->palPalEntry[MaskColour].peBlue    = 255;
00950             pPalette->palPalEntry[MaskColour].peFlags   = 255;
00951         }
00952 
00953         BOOL ok = DoOutputBitmapConversion(&lpConvInfo, &lpConvBits, pPalette);
00954         ERROR3IF(!ok, "Output conversion failed in GRenderBitmap::ExtractBitmap");
00955         if (!ok)
00956         {
00957             if (DeletePalette)
00958                 CCFree(pPalette);
00959             return NULL;
00960         }
00961 
00962         if (lpConvBits == pBits)
00963         {
00964             BOOL CopyOK = DIBUtil::CopyBitmap(pBitmapInfo, pBits, &lpCopyInfo, &lpCopyBits);
00965 
00966             if (!CopyOK)
00967             {
00968                 ERROR3("Failed to copy bitmap in ExtractBitmapCopy");
00969                 if (DeletePalette)
00970                     CCFree(pPalette);
00971                 return NULL;
00972             }
00973         }
00974         else
00975         {
00976             lpCopyInfo = lpConvInfo;
00977             lpCopyBits = lpConvBits;
00978         }
00979 
00980         if (pMaskInfo && pMaskData && MaskColour>=0)
00981         {
00982             // We've been given a mask for the bitmap ...
00983             if (!DIBUtil::MakeTransparentBitmap(lpCopyInfo, lpCopyBits, pMaskInfo, pMaskData, MaskColour))
00984             {
00985                 ERROR3("Failed to apply mask in GRenderBitmap::ExtractBitmapCopy");
00986                 if (DeletePalette)
00987                     CCFree(pPalette);
00988                 FreeDIB(lpCopyInfo, lpCopyBits);
00989                 return NULL;
00990             }
00991         }
00992 
00993         CWxBitmap *OILBM = new CWxBitmap( lpCopyInfo, lpCopyBits );
00994         if (OILBM)
00995         {
00996             //  Make sure that the bitmap has a width and height which are an integral
00997             //  number of pixels.
00998             INT32 width  = (INT32)(( OILBM->BMInfo->bmiHeader.biWidth ) * 72000 / 96.0);
00999             INT32 height = (INT32)(( OILBM->BMInfo->bmiHeader.biHeight ) * 72000 / 96.0);
01000             OILBM->SetRecommendedWidth( width );
01001             OILBM->SetRecommendedHeight( height );
01002 
01003             // Setup the Oil bitmap's pallete
01004             RGBQUAD* pOilPalette = OILBM->BMInfo->bmiColors;
01005             // Only change the palette if there is on already present
01006             // REMEMBER bitmaps with more than 8bpp generally do not have palettes
01007             if (pPalette != NULL)
01008             {
01009                 // This will be the optimised palette
01010                 INT32 ColoursInPal = pPalette->palNumEntries;
01011                 // The optimised palette will NOT contain the transparent colour
01012                 // Therefore, if we have a transparent colour then increment our count
01013                 if (MaskColour >= 0)
01014                 {
01015                     // We have to ensure that the number of colours we are requesting will
01016                     // be enough to contain the transparent colour index.
01017                     if (MaskColour > ColoursInPal)
01018                     {
01019                         // Not enough entries in out palette
01020                         // So expand it to include the mask colour
01021                         ColoursInPal = MaskColour + 1;
01022                     }
01023                     else
01024                         ColoursInPal++;
01025                 }
01026 
01027                 // The bitmap header will contain the colour depth number of colours
01028                 INT32 MaxColours = OILBM->BMInfo->bmiHeader.biClrUsed;
01029                 // Ensure that we have not gone over this limit
01030                 if (ColoursInPal > MaxColours)
01031                     ColoursInPal = MaxColours;
01032 
01033                 // Copy the palette entries over, we cannot copy a structure at a time because 
01034                 // the bytes are in different orders
01035                 PALETTEENTRY* pPaletteEntry = pPalette->palPalEntry;
01036                 for (INT32 i = 0; i < MaxColours; i++)
01037                 {
01038                     if (i == MaskColour)
01039                     {
01040                         // Force the masked colour to White, so it looks right
01041                         // even if we can't render it with transparency
01042                         pOilPalette[i].rgbBlue  = 255;
01043                         pOilPalette[i].rgbGreen = 255;
01044                         pOilPalette[i].rgbRed   = 255;
01045                         pOilPalette[i].rgbReserved = 255;
01046                     }
01047                     else if (i > ColoursInPal)
01048                     {
01049                         // Force any unused colours to be black
01050                         pOilPalette[i].rgbBlue  = 0;
01051                         pOilPalette[i].rgbGreen = 0;
01052                         pOilPalette[i].rgbRed   = 0;
01053                         pOilPalette[i].rgbReserved = 0;
01054                     }
01055                     else
01056                     {
01057                         pOilPalette[i].rgbBlue  = pPaletteEntry[i].peBlue;
01058                         pOilPalette[i].rgbGreen = pPaletteEntry[i].peGreen;
01059                         pOilPalette[i].rgbRed   = pPaletteEntry[i].peRed;
01060                         pOilPalette[i].rgbReserved = 0;
01061                     }
01062                 }
01063 
01064                 // Only set up the required number of palette entries
01065                 OILBM->BMInfo->bmiHeader.biClrUsed = ColoursInPal;
01066             } 
01067 
01068             if (lpCopyBits == pBits)
01069             {
01070                 // bytes owned by CWxBitmap now - zero them so we don't free them up
01071                 SetBitmapPointers(NULL, NULL);
01072 
01073                 // ensure empty offscreen stack
01074                 ENSURE(MasterCaptureIsCurrent(), "Extract bitmap whilst rendering offscreen not finished!");
01075             }
01076 
01077             if (lpCopyBits == lpOutputBits)
01078             {
01079                 // bytes owned by CWxBitmap now - zero them so we don't free them up
01080                 lpOutputInfo = NULL;
01081                 lpOutputBits = NULL;
01082             }
01083 
01084             if (LookForDuplicates)
01085             {
01086                 // This check was not here before 25/4/97
01087                 // Check to see if this bitmap exists in the global bitmap list
01088                 // This will actually check the bitmap itself to see if it is the same
01089                 // rather than doing a simple and explicit pointer check.
01090                 GlobalBitmapList * pBmpList = GetApplication()->GetGlobalBitmapList();
01091                 OILBitmap* pExistingBmp = NULL;
01092                 if (pBmpList)
01093                     pExistingBmp = pBmpList->FindDuplicateBitmap(OILBM);
01094                 if (pExistingBmp)
01095                 {
01096                     TRACEUSER( "Neville", _T("This bitmap already exists.  Re-using existing OILBitmap.\n"));
01097                     // There's already an existing OIL bitmap we can use,
01098                     // so we'll make a new kernel bitmap out of it ...
01099                     if (DeletePalette)
01100                         CCFree(pPalette);
01101                     delete OILBM;
01102                     return pExistingBmp;
01103                 }
01104             }
01105             if (DeletePalette)
01106                 CCFree(pPalette);
01107 
01108             return OILBitmap::Attach(OILBM, FALSE);
01109         }
01110 
01111         if(DeletePalette)
01112             CCFree(pPalette);
01113     }
01114 
01115     return NULL;
01116 }
01117 
01118 /********************************************************************************************
01119 
01120 >   BOOL GRenderBitmap::GetBitmapData(LPBITMAPINFO* pBitmapInfo, LPBYTE* pBitmapData, BOOL Convert)
01121 
01122     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01123     Created:    28/5/96
01124     Returns:    -
01125     Purpose:    -
01126 
01127 ********************************************************************************************/
01128 
01129 BOOL GRenderBitmap::GetBitmapData(LPBITMAPINFO* pBmpInfo, LPBYTE* pBmpData, BOOL Convert)
01130 {
01131     ERROR3IF(pBmpInfo == NULL, "NULL info pointer passed to GetBitmapData");
01132     if (pBmpInfo == NULL)
01133         return FALSE;
01134 
01135     ERROR3IF(pBmpData == NULL, "NULL data pointer passed to GetBitmapData");
01136     if (pBmpData == NULL)
01137         return FALSE;
01138 
01139     if (!Convert)
01140     {
01141         *pBmpInfo = pBitmapInfo;
01142         *pBmpData = pBits;
01143         
01144         if(m_bEnableConversion && m_DoCompression)
01145         {
01146             UINT32 Width = pBitmapInfo->bmiHeader.biWidth;
01147             UINT32 Height = pBitmapInfo->bmiHeader.biHeight;
01148             BYTE* lpOutput = *pBmpData;
01149 
01150             DIBConvert* Converter = DIBConvert::Create( 32, 32, Width, NULL, 0 );
01151 
01152             if(Converter != NULL)
01153             {
01154                 Converter->Convert(pBits, lpOutput, Height);
01155                 delete Converter;
01156                 Converter = NULL;
01157 
01158                 // Force the bitmap to be reinitialised when StartRender is next called
01159                 ForceInitBmpBits = TRUE;
01160 
01161                 ENSURE(GetMasterCapture()==NULL || MasterCaptureIsCurrent(), "Bitmap converted in-place while captures are running\n");
01162             }
01163         }
01164 
01165         return TRUE;
01166     }
01167 
01168     LPBITMAPINFO lpConvInfo=NULL;   
01169     LPBYTE lpConvBits=NULL; 
01170 
01171     LPLOGPALETTE pPalette = GetConversionPalette();
01172 
01173     BOOL ok = DoOutputBitmapConversion(&lpConvInfo, &lpConvBits, pPalette);
01174     ERROR3IF(!ok, "Output conversion failed in GRenderBitmap::GetBitmapData");
01175 
01176     *pBmpInfo = lpConvInfo;
01177     *pBmpData = lpConvBits;
01178 
01179     if (pPalette != pConvPalette)
01180         CCFree(pPalette);
01181 
01182     return ok;
01183 }
01184 
01185 /********************************************************************************************
01186 
01187 >   BOOL GRenderBitmap::DoOutputBitmapConversion(LPBITMAPINFO* lpConvInfo, LPBYTE* lpConvBits, LPLOGPALETTE pPalette)
01188 
01189     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01190     Created:    28/5/96
01191     Returns:    -
01192     Purpose:    -
01193 
01194 ********************************************************************************************/
01195 
01196 BOOL GRenderBitmap::DoOutputBitmapConversion(LPBITMAPINFO* lpConvInfo, LPBYTE* lpConvBits, LPLOGPALETTE pPalette)
01197 {
01198 #if !defined(EXCLUDE_FROM_RALPH)
01199     ERROR3IF(lpConvInfo == NULL, "NULL info pointer passed to GRenderBitmap::DoOutputBitmapConversion");
01200     if (lpConvInfo == NULL)
01201         return FALSE;
01202 
01203     ERROR3IF(lpConvBits == NULL, "NULL data pointer passed to GRenderBitmap::DoOutputBitmapConversion");
01204     if (lpConvBits == NULL)
01205         return FALSE;
01206 
01207     if (uOutputDepth == uBitmapDepth)
01208     {
01209         // No conversion is needed !!
01210         *lpConvInfo = pBitmapInfo;
01211         *lpConvBits = pBits;
01212 
01213         if(m_bEnableConversion && m_DoCompression)
01214         {
01215             UINT32 Width = pBitmapInfo->bmiHeader.biWidth;
01216             UINT32 Height = pBitmapInfo->bmiHeader.biHeight;
01217             BYTE* lpOutput = pBits;
01218 
01219             DIBConvert* Converter = DIBConvert::Create( 32, 32, Width, NULL, 0 );
01220 
01221             if(Converter != NULL)
01222             {
01223                 Converter->Convert(pBits, lpOutput, Height);
01224                 delete Converter;
01225                 Converter = NULL;
01226 
01227                 // Force the bitmap to be reinitialised when StartRender is next called
01228                 ForceInitBmpBits = TRUE;
01229 
01230                 ENSURE(GetMasterCapture()==NULL || MasterCaptureIsCurrent(), "Bitmap converted in-place while captures are running\n");
01231             }
01232         }
01233 
01234         return TRUE;
01235     }
01236 
01237     // Blank the pointer in case of an error
01238     *lpConvInfo = NULL;
01239     *lpConvBits = NULL;
01240 
01241     // We must need to do some Bitmap conversion then ....
01242     UINT32 Width = pBitmapInfo->bmiHeader.biWidth;
01243     UINT32 Height = pBitmapInfo->bmiHeader.biHeight;
01244 
01245     // Make a converter object
01246     DIBConvert* Converter = DIBConvert::Create( uBitmapDepth, uOutputDepth, Width, pPalette, DitherType );
01247     ERROR3IF(Converter == NULL, "Failed to create DIBConvert object in GRenderBitmap::DoOutputBitmapConversion");
01248     if (Converter == NULL)
01249         return FALSE;
01250 
01251     if (lpOutputInfo != NULL || lpOutputBits != NULL)
01252     {
01253         // Free the existing bitmap data
01254         FreeDIB(lpOutputInfo, lpOutputBits);
01255 
01256         lpOutputInfo = NULL;
01257         lpOutputBits = NULL;
01258     }
01259 
01260     // Allocate some memory for the converted bitmap
01261     lpOutputInfo = AllocDIB(Width, Height, uOutputDepth, &lpOutputBits);
01262     ERROR3IF(lpOutputInfo == NULL, "Failed to allocate conversion info in GRenderBitmap::DoOutputBitmapConversion");
01263     ERROR3IF(lpOutputBits == NULL, "Failed to allocate conversion data in GRenderBitmap::DoOutputBitmapConversion");
01264     if (lpOutputInfo == NULL || lpOutputBits == NULL)
01265         return FALSE;
01266 
01267     // Do the conversion
01268     BOOL ok = Converter->Convert(pBits, lpOutputBits, Height);
01269     delete Converter;
01270 
01271     if (ok)
01272     {
01273         *lpConvInfo = lpOutputInfo;
01274         *lpConvBits = lpOutputBits;
01275     }
01276 
01277     return ok;
01278 #else
01279     return FALSE;
01280 #endif
01281 }
01282 
01283 /********************************************************************************************
01284 
01285 >   LPLOGPALETTE GRenderBitmap::GetConversionPalette()
01286 
01287     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01288     Created:    13/6/96
01289     Returns:    -
01290     Purpose:    -
01291 
01292 ********************************************************************************************/
01293 
01294 LPLOGPALETTE GRenderBitmap::GetConversionPalette()
01295 {
01296 #if !defined(EXCLUDE_FROM_RALPH)
01297     if (uOutputDepth>8)
01298         return NULL;    // Must be 8bpp or less
01299 
01300     if (pConvPalette)
01301         return pConvPalette;    // Use specified palette if one exists
01302 
01303     //ASSERT(FALSE); // we should have a palette!! sjk SMFIX
01304     // most times we should have a palette but for now animated gifs like to use this code so we will leave it for now
01305 
01306     LPLOGPALETTE pPalette;
01307     size_t TotalPal;
01308 
01309     switch (uOutputDepth)
01310     {
01311         case 8:
01312             // Get the standard 256 colour palette
01313             TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 256 );
01314             pPalette = (LPLOGPALETTE)CCMalloc( TotalPal );
01315             if (pPalette != NULL)
01316             {
01317                 LPLOGPALETTE pRecPalette = GetErrorDiffPalette();
01318                 if (pRecPalette)
01319                 {
01320                     memcpy(pPalette, pRecPalette, TotalPal);
01321                 }
01322                 else
01323                 {
01324                     CCFree(pPalette);
01325                     return NULL;
01326                 }
01327             }
01328             break;
01329 
01330         case 4:
01331             TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 16 );
01332             pPalette = (LPLOGPALETTE)CCMalloc( TotalPal );
01333             if (pPalette != NULL)
01334             {
01335                 // Make a standard 16 colour palette
01336                 OutputDIB::Fix16ColourPalette(pPalette);
01337             }
01338             break;
01339 
01340         case 1:
01341             TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 2 );
01342             pPalette = (LPLOGPALETTE)CCMalloc( TotalPal );
01343             if (pPalette != NULL)
01344             {
01345                 // Make a simple black and white palette
01346                 OutputDIB::FixBlackAndWhitePalette(pPalette);
01347             }
01348             break;
01349 
01350         default:
01351             ERROR3("Bad colour depth in GRenderBitmap::GetConversionPalette");
01352             pPalette = NULL;
01353             break;
01354     }
01355 
01356     return pPalette;
01357 #else
01358     return NULL;
01359 #endif
01360 }
01361 
01362 
01363 
01364 /********************************************************************************************
01365 
01366 >   void GRenderBitmap::UseGreyscaleContextDangerous(void)
01367 
01368     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01369     Created:    5/2/97
01370 
01371     Purpose:    DANGEROUS! Don't use this unless you really know what you're doing
01372 
01373                 Replaces the static GRenderRegion::GD context with a new Greyscale
01374                 paletted one for generating 8bpp greyscale images with. This has two
01375                 purposes -
01376                     1. to allow creation of 8bpp greyscale images without having to
01377                        allocate a 32bp bitmap or anything
01378                     2. to allow a GRenderRegion-derived render region to be used to
01379                        render inside the rendering loop of another GRenderRegion.
01380 
01381                 This is currently used by the airbrush path stroking code to draw
01382                 transparency information into an 8bpp greyscale bitmap, on the fly,
01383                 during normal GDraw rendering. If you want to do something similar,
01384                 take a look at that code, because great care must be taken when using
01385                 one GRndRgn inside the other to make sure no corruption occurs.
01386 
01387                 There is only one symptom of getting it wrong: a nasty access violation.
01388 
01389                 Before calling StartRender on your new GRenderBitmap, call this function
01390                 to install the new context. Once finished, you must restore the normal
01391                 GRenderRegion state by calling StopUsingGreyscaleContextDangerous()
01392 
01393 ********************************************************************************************/
01394 
01395 void GRenderBitmap::UseGreyscaleContextDangerous(void)
01396 {
01397     TRACEUSER( "Gerry", _T("GRenderBitmap::UseGreyscaleContextDangerous\n"));
01398     ERROR3IF(pPreviousGDrawContext != NULL, "UseGreyscaleContextDangerous called while context in use");
01399     if (pPreviousGDrawContext == NULL)
01400     {
01401         if (pGreyscaleContext == NULL)
01402         {
01403 PORTNOTE("other","GRenderBitmap::UseGreyscaleContextDangerous - removed progress reporting")
01404 #if !defined(EXCLUDE_FROM_XARALX)
01405             Progress::Start();
01406 #endif
01407 
01408             // Create a new context the first time anyone actually wants one
01409             pGreyscaleContext = new GDrawAsm;
01410 
01411             if (pGreyscaleContext != NULL)
01412             {
01413 //              pGreyscaleContext->Init();
01414                 
01415                 // And initialise the palette - this can unfortunately take a couple of seconds
01416                 DWORD PaletteFlag = 0;
01417                 if (WhichDither == 0 || WhichDither == 3)
01418                     PaletteFlag = 1;
01419 
01420                 if (pGreyscaleContext->SelectPalette(PaletteFlag) != NULL)
01421                     pGreyscaleContext->InitialiseWithPalette(pConvPalette);
01422             }
01423 
01424 #if !defined(EXCLUDE_FROM_XARALX)
01425             Progress::Stop();
01426 #endif
01427         }
01428 
01429         if (pGreyscaleContext != NULL)
01430         {
01431             pPreviousGDrawContext = SetTempDrawContext(pGreyscaleContext);
01432         }
01433     }
01434 }
01435 
01436 
01437 
01438 /********************************************************************************************
01439 
01440 >   void GRenderBitmap::StopUsingGreyscaleContextDangerous(void)
01441 
01442     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01443     Created:    5/2/97
01444 
01445     Purpose:    DANGEROUS! Don't use this unless you really know what you're doing
01446 
01447                 See StartUsingGreyscaleContextDangerous()
01448 
01449 ********************************************************************************************/
01450 
01451 void GRenderBitmap::StopUsingGreyscaleContextDangerous(void)
01452 {
01453     TRACEUSER( "Gerry", _T("GRenderBitmap::StopUsingGreyscaleContextDangerous\n"));
01454     ERROR3IF(pPreviousGDrawContext == NULL, "UseGreyscaleContextDangerous called while context not in use");
01455     if (pPreviousGDrawContext != NULL)
01456     {
01457         if (SetTempDrawContext(pPreviousGDrawContext) != pGreyscaleContext)
01458         {
01459             ERROR3("Not pGreyscaleContext when restoring");
01460         }
01461         pPreviousGDrawContext = NULL;
01462     }
01463 }
01464 
01465 
01466 
01467 /********************************************************************************************
01468 
01469 >   static void GRenderBitmap::Deinit(void)
01470 
01471     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01472     Created:    5/2/97
01473 
01474     Purpose:    De-initialises the GRenderBitmap class.
01475                 Mainly used to stop memory leaks after someone has been using the
01476                 nasty greyscale context bodge (See StartUsingGreyscaleContextDangerous())
01477 
01478 ********************************************************************************************/
01479 
01480 void GRenderBitmap::Deinit(void)
01481 {
01482     ERROR3IF(GD != NULL && GD == pGreyscaleContext, "GRenderBitmap greyscale context still in use");
01483 
01484     if (pGreyscaleContext != NULL)
01485     {
01486         delete pGreyscaleContext;
01487         pGreyscaleContext = NULL;
01488     }
01489 }
01490 
01491 
01492 
01493 
01494 
01495 
01496 
01497 
01498 
01499 #if !defined(EXCLUDE_FROM_RALPH)
01500 
01501 /********************************************************************************************
01502 
01503     GRenderOptPalette ... a special Render Region for generating an optimised palette for
01504                           use during export 
01505 
01506 ********************************************************************************************/
01507 
01508 
01509 /********************************************************************************************
01510 
01511 >   GRenderOptPalette::GRenderOptPalette(DocRect ClipRegion, Matrix ConvertMatrix, FIXED16 ViewScale, UINT32 Depth, double dpi, BOOL Use8bpp)
01512 
01513     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01514     Created:    29/5/96
01515     Inputs:     -
01516     Outputs:    -
01517     Returns:    -
01518     Purpose:    GRenderOptPalette constructor.
01519     Errors:     -
01520     SeeAlso:    GRenderBitmap::GRenderBitmap
01521 
01522 ********************************************************************************************/
01523 GRenderOptPalette::GRenderOptPalette(DocRect ClipRegion, Matrix ConvertMatrix, FIXED16 ViewScale, UINT32 Depth, double dpi, BOOL Use8bpp)
01524     : GRenderBitmap( ClipRegion, ConvertMatrix, ViewScale, Depth, dpi)
01525 {
01526     ERROR3IF(Depth != 32, "Bad Depth for GRenderOptPalette, must be 32bpp");
01527 
01528     UseSpecial8bpp = Use8bpp;
01529 
01530     m_pExactPalette = NULL;
01531 
01532     if (Depth == 32)
01533     {
01534         if (UseSpecial8bpp)
01535         {
01536             Stats = CCMalloc(DIBUtil::GetOptimal8bppPaletteWorkspaceSize() * 4);
01537             if (Stats)
01538                 DIBUtil::Optimal8bppPaletteInitialise((INT32*)Stats);
01539         }
01540         else
01541         {
01542             Stats = CCMalloc(DIBUtil::GetOptimalPaletteWorkspaceSize());
01543             if (Stats)
01544                 DIBUtil::OptimalPaletteInitialise(Stats);
01545 
01546         }
01547         if( !UseOldPalette )
01548         {
01549             const size_t TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 256 );
01550             m_pExactPalette = (LPLOGPALETTE)CCMalloc( TotalPal );
01551             if( m_pExactPalette )
01552                 DIBUtil::ExactPaletteInitialise( m_pExactPalette );
01553         }
01554     }
01555 
01556     m_bTooManyColours = FALSE;
01557 
01558     //  Re-initialise
01559     DoGDrawConversion = TRUE;
01560 }
01561 
01562 /********************************************************************************************
01563 
01564 >   GRenderOptPalette::~GRenderOptPalette()
01565 
01566     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01567     Created:    29/5/96
01568     Inputs:     -
01569     Outputs:    -
01570     Returns:    -
01571     Purpose:    GRenderOptPalette destructor
01572     Errors:     -
01573 
01574 ********************************************************************************************/
01575 
01576 GRenderOptPalette::~GRenderOptPalette()
01577 {
01578     if (Stats)
01579         CCFree(Stats);
01580     // GAT
01581     if (m_pExactPalette)
01582         CCFree(m_pExactPalette) ;
01583 }
01584 
01585 /********************************************************************************************
01586 
01587 >   BOOL GRenderOptPalette::GetNextBand()
01588 
01589     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01590     Created:    29/5/96
01591     Inputs:     -
01592     Outputs:    -
01593     Returns:    -
01594     Purpose:    Passes this band to Gavin's palette optimisation routine, before we move
01595                 onto the next band
01596     Errors:     -
01597 
01598 ********************************************************************************************/
01599 
01600 BOOL GRenderOptPalette::GetNextBand()
01601 {
01602     // Before we move onto the next band, we'll pass the current strip to Gavin's
01603     // palette optimising code
01604     if (Stats)
01605     {
01606         INT32 Width = pBitmapInfo->bmiHeader.biWidth;
01607         INT32 Height = pBitmapInfo->bmiHeader.biHeight;
01608 
01609         INT32 BmpSize = Width * Height;
01610 
01611         //  Calculate the number of colours used by this strip of the bitmap.
01612         //  But only if we have not gone over 256 colours yet
01613         // GAT
01614         if( !m_bTooManyColours && !UseOldPalette )
01615         {
01616             BOOL bResult = DIBUtil::CalculateNumberOfColoursInBitmap( m_pExactPalette, ( RGBQUAD* )pBits, BmpSize );
01617             if( !bResult )
01618             {
01619                 m_bTooManyColours = TRUE;
01620                 DoGDrawConversion = FALSE;
01621             }
01622         }
01623 
01624         BOOL ok;
01625         if (UseSpecial8bpp)
01626             ok = DIBUtil::GenOptimal8bppPaletteStats( (INT32*)Stats, (RGBQUAD*)pBits, BmpSize );
01627         else
01628             ok = DIBUtil::GenOptimalPaletteStats( Stats, (RGBQUAD*)pBits, BmpSize );
01629 
01630         ERROR3IF(!ok, "GenOptimalPaletteStats failed");
01631     }
01632 
01633     return GRenderBitmap::GetNextBand();                                        
01634 }
01635 
01636 /********************************************************************************************
01637 
01638 >   LPLOGPALETTE GRenderOptPalette::GetOptimisedPalette(UINT32 PaletteSize, UINT32 NumColours, UINT32 ReservedColours = 0, BOOL SnapToBrowserPalette = FALSE)
01639 
01640     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> (modified by MarkN)
01641     Created:    29/5/96
01642     Inputs:     PaletteSize     = Max number of entries that the palette can hold (should be 2, 16 or 256)
01643                 NumColours      = Number of colours to put in the palette
01644                 ReservedColours = , number of colours to reserve (eg. for transparency)
01645                 SnapToBrowserPalette = TRUE if palette should be snapped to the browser palett
01646     Outputs:    -
01647     Returns:    A pointer to the optimised palette, or NULL if failed
01648                 
01649                 The reserved colours will appear as follows ...
01650                 1bpp, at end of the palette,
01651                 4bpp, at the start of the palette,
01652                 8bpp, at the 11 entry in the palette (10 windows colours are always at the start).
01653 
01654                 WEBSTER Changes (markn 16/1/97):
01655                 This function has been modified so that you can specify the number colours you want in the
01656                 palette
01657                 
01658                 WEBSTER v2 changes (markn 22/7/97)
01659 
01660     Purpose:    Generates an optimised palette from the Statistics generated from each band
01661                 rendered so far
01662     Errors:     -
01663 
01664 ********************************************************************************************/
01665 
01666 LPLOGPALETTE GRenderOptPalette::GetOptimisedPalette(UINT32 PaletteSize, UINT32 NumColours, UINT32 ReservedColours, BOOL SnapToBrowserPalette)
01667 {
01668     ERROR3IF(!(PaletteSize==2 || PaletteSize==16 || PaletteSize==256), "Bad palette size passed to GRenderOptPalette::GetOptimisedPalette");
01669     ERROR3IF(ReservedColours > PaletteSize, "Too many colours reserved in GRenderOptPalette::GetOptimisedPalette");
01670 
01671     LPLOGPALETTE pPalette = NULL;
01672 
01673     if (Stats)
01674     {
01675         const size_t TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * PaletteSize );
01676         pPalette = (LPLOGPALETTE)CCMalloc( TotalPal );
01677         if (pPalette)
01678         {
01679             // Initialise the palette with zeros
01680             memset(pPalette, 0, TotalPal);
01681 
01682             pPalette->palVersion    = 0x300;
01683             pPalette->palNumEntries = PaletteSize;
01684 
01685             if (NumColours > PaletteSize)
01686                 NumColours = PaletteSize;
01687 
01688             if (ReservedColours < NumColours)
01689             {
01690                 BOOL ok = TRUE;
01691                 // GAT
01692                 //  If the bitmap has less than 256 colours, then we want to bypass the 
01693                 //  optimisation code, and just use the exact palette.
01694 PORTNOTE("BmpPrevDlg", "Rampant use of BmapPrevDlg removed (please don't re-instate directly - the value should be a param or member of this class)")
01695 #ifndef EXCLUDE_FROM_XARALX
01696                 if( !m_bTooManyColours && m_pExactPalette && !UseOldPalette 
01697                     && m_pExactPalette->palNumEntries < BmapPrevDlg::m_NumOfColoursUserAskedFor ) // and we want this many colours
01698 #else
01699                 if( !m_bTooManyColours && m_pExactPalette && !UseOldPalette ) // and we want this many colours
01700 #endif
01701                 {
01702                     //  Transfer the exact palette into the variable we want, and then clear up the memory.
01703                     INT32 blackEntry = 10;
01704                     pPalette->palNumEntries = m_pExactPalette->palNumEntries;
01705                     INT32 i = 0;
01706                     for( i = 0; i < m_pExactPalette->palNumEntries; i++ )
01707                     {
01708                         pPalette->palPalEntry[i].peRed   = m_pExactPalette->palPalEntry[i].peRed;
01709                         pPalette->palPalEntry[i].peGreen = m_pExactPalette->palPalEntry[i].peGreen;
01710                         pPalette->palPalEntry[i].peBlue  = m_pExactPalette->palPalEntry[i].peBlue;
01711 
01712                         if (pPalette->palPalEntry[i].peRed == 255 &&
01713                             pPalette->palPalEntry[i].peGreen == 255 &&
01714                             pPalette->palPalEntry[i].peBlue == 255 )
01715                             blackEntry = i;
01716                     }
01717                     if (blackEntry != 10 && ReservedColours == 1)
01718                     {
01719                         // swap the black entry for number 10 as this is the transparent entry for some odd reason
01720                         pPalette->palPalEntry[blackEntry].peRed = pPalette->palPalEntry[10].peRed;
01721                         pPalette->palPalEntry[blackEntry].peGreen = pPalette->palPalEntry[10].peGreen;
01722                         pPalette->palPalEntry[blackEntry].peBlue = pPalette->palPalEntry[10].peBlue;
01723 
01724                         pPalette->palPalEntry[10].peRed = 255;
01725                         pPalette->palPalEntry[10].peGreen = 255;
01726                         pPalette->palPalEntry[10].peBlue = 255;
01727                     }
01728                     for( ; i<0x100 ; i++ )
01729                     {
01730                         pPalette->palPalEntry[i].peRed   =
01731                         pPalette->palPalEntry[i].peGreen =
01732                         pPalette->palPalEntry[i].peBlue  = 0 ;
01733                     }
01734 
01735 //                  BmapPrevDlg::m_bNeedPaletteUpdated = TRUE;
01736 PORTNOTE("BmpPrevDlg", "Use of BmapPrevDlg removed")
01737 #ifndef EXCLUDE_FROM_XARALX
01738                     BmapPrevDlg::m_bUseExistingPalette = FALSE;
01739 #endif
01740                 }
01741                 else if (UseSpecial8bpp)
01742                 {
01743                     if (PaletteSize != 256)
01744                     {
01745                         ERROR3("Palette size is wrong for an 8bpp bitmap");
01746                         CCFree( pPalette );
01747                         return NULL;
01748                     }
01749 
01750                     // There has to be at least 20 colours in the palette to accomodate the system colours
01751                     if (NumColours < 20)
01752                         NumColours = 20;
01753 
01754                     // Gavin adds 16 system colours, then later we remove these and add the full set of 20 system colours
01755                     // Therefore, get Gavin to generate 4 fewer colours so we end up with the correct number of
01756                     // colours in the palette.
01757                     NumColours -= 4;
01758 
01759                     // We can only generate a maximum of 252 colours (i.e. (256-20)+16 = 252)
01760                     if (NumColours > 252)
01761                         NumColours = 252;
01762 
01763                     // Leave room for the reserved colours
01764                     NumColours -= ReservedColours;
01765 
01766                     ok = DIBUtil::GenOptimal8bppPalette((INT32*) Stats, pPalette, NumColours);
01767                 }
01768                 else
01769                 {
01770                     // Leave room for the reserved colours
01771                     NumColours -= ReservedColours;
01772 
01773                     ok = DIBUtil::GenOptimalPalette( Stats, pPalette, (NumColours==1) ? 2 : NumColours );
01774                 }
01775                 // GAT
01776                 if( m_pExactPalette )
01777                 {
01778                     //  Get some memory back.
01779                     CCFree( m_pExactPalette );
01780                     m_pExactPalette = NULL;
01781                 }
01782             
01783                 // WEBSTER - markn - 22/7/97
01784                 if (ok && SnapToBrowserPalette)
01785                 {
01786                     PaletteManager::SnapToBrowserPalette(pPalette);
01787                 }
01788 
01789                 if (ok)
01790                 {
01791                     // Now we need to shift the colours about a bit ....
01792                     switch (PaletteSize)
01793                     {
01794                         INT32 index;
01795 
01796                         case 2:
01797                             if (NumColours == 1)
01798                             {
01799                                 // 1 colour needs some special treatment
01800                                 if (pPalette->palPalEntry[1].peRed   == 0xFF &&
01801                                     pPalette->palPalEntry[1].peGreen == 0xFF &&
01802                                     pPalette->palPalEntry[1].peBlue  == 0xFF)
01803                                 {
01804                                     // First entry is white
01805                                     pPalette->palPalEntry[1] = pPalette->palPalEntry[0];
01806                                     pPalette->palPalEntry[1].peFlags = 0;
01807 
01808 
01809                                     pPalette->palPalEntry[0].peRed   = 255;
01810                                     pPalette->palPalEntry[0].peGreen = 255;
01811                                     pPalette->palPalEntry[0].peBlue  = 255;
01812                                     pPalette->palPalEntry[0].peFlags = 255;     // This makes Gavin ignore this
01813                                                                                 // colour when converting the bitmap
01814                                 }
01815                                 else if (pPalette->palPalEntry[0].peRed   == 0xFF &&
01816                                          pPalette->palPalEntry[0].peGreen == 0xFF &&
01817                                          pPalette->palPalEntry[0].peBlue  == 0xFF)
01818                                 {
01819                                     // Second entry is white
01820                                     pPalette->palPalEntry[0].peFlags = 255;     // This makes Gavin ignore this
01821                                                                                 // colour when converting the bitmap
01822                                 }
01823                                 else
01824                                 {
01825                                     // Neither entry is white !
01826                                     pPalette->palPalEntry[0].peRed   = 255;
01827                                     pPalette->palPalEntry[0].peGreen = 255;
01828                                     pPalette->palPalEntry[0].peBlue  = 255;
01829                                     pPalette->palPalEntry[0].peFlags = 255;     // This makes Gavin ignore this
01830                                                                                 // colour when converting the bitmap
01831                                 }
01832                                 
01833                                 pPalette->palNumEntries = 2;
01834                             }
01835                             else
01836                                 pPalette->palNumEntries += ReservedColours;
01837                             break;
01838 
01839                         case 16:
01840                             // Shift the palette entries down, so the reserved colours are at the start
01841                             for (index = NumColours - 1; index >= 0; index--)
01842                             {
01843                                 pPalette->palPalEntry[index + ReservedColours] = pPalette->palPalEntry[index];
01844                             }
01845 
01846                             // Blank the reserved colours to white
01847                             for (index = 0; index < INT32(ReservedColours); index++)
01848                             {
01849                                 pPalette->palPalEntry[index].peRed   = 255;
01850                                 pPalette->palPalEntry[index].peGreen = 255;
01851                                 pPalette->palPalEntry[index].peBlue  = 255;
01852                                 pPalette->palPalEntry[index].peFlags = 255;     // This makes Gavin ignore this
01853                                                                                 // colour when converting the bitmap
01854                             }
01855 
01856                             pPalette->palNumEntries += ReservedColours;
01857                             break;
01858 
01859                         case 256:
01860                             #ifdef _BATCHING
01861                             {
01862                                     for (UINT32 index = 0;index < NumColours;index++)
01863                                     {
01864                                         BYTE R = pPalette->palPalEntry[index].peRed;
01865                                         BYTE G = pPalette->palPalEntry[index].peGreen;
01866                                         BYTE B = pPalette->palPalEntry[index].peBlue;
01867                                         if (R == 254 && G == 254 && B == 254)
01868                                         {
01869                                             pPalette->palPalEntry[index].peRed = 255;
01870                                             pPalette->palPalEntry[index].peGreen = 255;
01871                                             pPalette->palPalEntry[index].peBlue = 255;
01872                                         }                                           
01873                                     }
01874                             }
01875                             #endif
01876                             
01877                             if (UseSpecial8bpp && !( !m_bTooManyColours && !UseOldPalette ) )
01878                             {
01879                                 LPLOGPALETTE pWinPalette;
01880 
01881                                 // Now we move the colours.
01882                                 UINT32 CurStart = 16;
01883                                 UINT32 NewStart = 10 + ReservedColours;
01884 
01885                                 if (CurStart < NumColours)
01886                                 {
01887                                     BOOL ColoursMoved = FALSE;
01888 
01889                                     UINT32 NumColsToMove = NumColours - CurStart;
01890                                     ERROR3IF((NumColsToMove+CurStart) > 256,"No room for system colours");
01891                                     ERROR3IF((NumColsToMove+NewStart) > 256,"No room for system colours");
01892                                     
01893                                     if (NewStart < CurStart)
01894                                     {
01895                                         // Move the non-system colours down
01896                                         for (index = 0; index < INT32(NumColsToMove); index++)
01897                                             pPalette->palPalEntry[index + NewStart] = pPalette->palPalEntry[index + CurStart];
01898 
01899                                         // Blank out unused colours that are not system colours
01900                                         for (index = NumColsToMove+NewStart;index < 246;index++)
01901                                         {
01902                                             pPalette->palPalEntry[index].peRed   = 0;
01903                                             pPalette->palPalEntry[index].peGreen = 0;
01904                                             pPalette->palPalEntry[index].peBlue  = 0;
01905                                         }
01906 
01907                                         ColoursMoved = TRUE;
01908                                     }
01909 
01910                                     ERROR3IF(!ColoursMoved,"Rewrite code to accomodate system colours");
01911                                 }
01912 
01913                                 ERROR3IF(CurStart > NumColours,"Not enough room for system colours");
01914 
01915                                 // Now fill in the rest of the palette with the 20 system colours
01916                                 // (10 at the start, and 10 at the end)
01917                                 pWinPalette = GetErrorDiffPalette();
01918 
01919                                 for (index = 0; index < 10; index++)
01920                                 {
01921                                     pPalette->palPalEntry[index] = pWinPalette->palPalEntry[index];
01922                                 }
01923 
01924                                 for (index = 246; index < 256; index++)
01925                                 {
01926                                     pPalette->palPalEntry[index] = pWinPalette->palPalEntry[index];
01927                                 }
01928                             
01929                                 // Blank the reserved colours to white
01930                                 for (index = 10; index < INT32(10 + ReservedColours); index++)
01931                                 {
01932                                     pPalette->palPalEntry[index].peRed   = 255;
01933                                     pPalette->palPalEntry[index].peGreen = 255;
01934                                     pPalette->palPalEntry[index].peBlue  = 255;
01935                                     pPalette->palPalEntry[index].peFlags = 255;     // This makes Gavin ignore this
01936                                                                                     // colour when converting the bitmap
01937                                 }
01938                             }
01939                             else
01940                             {
01941                                 // WEBSTER - markn 15/2/97
01942                                 // If there's a reserved colour (i.e. creating a transparent bitmap)
01943                                 // make sure Gavin doen't use it
01944                                 // To do this, shift all the colours up one place, and flag the reserved colour
01945                                 // (hard wired to 10 for some reason unknown to myself) so Gavin ignores it
01946                                 if (ReservedColours == 1)
01947                                 {
01948                                     for (index = 255;index > 10;index--)
01949                                         pPalette->palPalEntry[index] = pPalette->palPalEntry[index-1];
01950 
01951                                     pPalette->palPalEntry[10].peRed   = 255;
01952                                     pPalette->palPalEntry[10].peGreen = 255;
01953                                     pPalette->palPalEntry[10].peBlue  = 255;
01954                                     pPalette->palPalEntry[10].peFlags = 255;        // This makes Gavin ignore this
01955                                 }
01956 
01957                                 ERROR3IF(ReservedColours > 1,"This code won't work with more than one reserved colour");
01958 
01959                                 // As this code is assuming that the transparent colour index is 10,
01960                                 // if the user has chosen less than 10 colours, we need to ensure that
01961                                 // the palette actually includes the transparent colour index. Otherwise,
01962                                 // the GIF export code will assume it can output the requested colours using
01963                                 // the minimum bpp. E.g. user request 2 colours, output will be 1 bpp and
01964                                 // so the 10 will cause problems.
01965                                 // This fixing of the number of entries is actually done in ExtractBitmapCopy
01966                             }
01967                             break;
01968                         default:
01969                             ERROR3("Bad palette size in GRenderOptPalette::GetOptimisedPalette");
01970                     }
01971                 }
01972                 else
01973                 {
01974                     ERROR3("Failed to generate optimised palette");
01975                     CCFree( pPalette );
01976                     pPalette = NULL;
01977                 }
01978             }
01979         }
01980 
01981         // Reinitialise the Stats
01982         if (UseSpecial8bpp)
01983             DIBUtil::Optimal8bppPaletteInitialise((INT32*)Stats);
01984         else
01985             DIBUtil::OptimalPaletteInitialise(Stats);
01986     }
01987 
01988     return pPalette;
01989 }
01990 #endif

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