outptdib.cpp

Go to the documentation of this file.
00001 // $Id: outptdib.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 /*
00100 */
00101 
00102 #include "camtypes.h"
00103 //#include "outptdib.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00104 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00105 //#include "dibutil.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 //#include "andy.h"
00109 //#include "dibconv.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 #include "progress.h"       // For hourglass stuff
00111 #include "bmapprev.h"
00112 
00113 #define new CAM_DEBUG_NEW
00114 
00115 // Declare the statics that are required as we are using a call back function
00116 LPBITMAPINFO        OutputDIB::lpBitmap;                // copy of header + palette, can be NULL
00117 LPBITMAPINFOHEADER  OutputDIB::lpBitmapInfo;            // copy of header, can be NULL
00118 BITMAPINFOHEADER    OutputDIB::BitmapInfo;              // copy of file header (includes output depth,
00119                                                         // width & height)
00120 // for debug purposes
00121 INT32               OutputDIB::HeightWritten    = 0L;   // count of the height of the export
00122 INT32               OutputDIB::HeightWanted     = 0L;   // the actual height of the export required
00123 
00124 LPBYTE              OutputDIB::ExportBuffer     = NULL; // pointer to output buffer, can be NULL
00125 DIBConvert          *OutputDIB::DoExportConvert;        // the convert DIB
00126 FNPTR_SCANLINE      OutputDIB::ExportConvertFn  = NULL; // the convert function
00127 size_t              OutputDIB::ExportSourceWidth = 0;   // width of the source DIB
00128 size_t              OutputDIB::ExportDestWidth  = 0;    // width of the destination DIB
00129 LPBYTE              OutputDIB::ExportData       = NULL; // pointer to the export data 
00130 INT32               OutputDIB::CurrentYPos      = 0;    // current line number
00131 size_t              OutputDIB::ExportChunkHeight = 0;   // Chunk height in use          
00132 
00133 BOOL                OutputDIB::OutputForward    = FALSE;// start from bottom or top of DIB
00134 UINT32              OutputDIB::CurrentStripSize = 0;    // current size of the strip being rendered
00135 
00136 BOOL                OutputDIB::IsFirstStrip     = TRUE;
00137 
00138 /********************************************************************************************
00139 >   OutputDIB::OutputDIB()
00140 
00141     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00142     Created:    4/8/94
00143     Purpose:    Default constructor for the class. Just sets up the pointers to our buffers
00144                 that may be used to be null so that the TidyUp function can do its job.
00145     SeeAlso:    OutputDIB::TidyUp
00146 
00147 ********************************************************************************************/
00148 OutputDIB::OutputDIB()
00149 {
00150     OutputFile = NULL;
00151     lpBitmap = NULL;
00152     ExportBuffer = NULL;
00153     DoExportConvert = NULL;
00154     OutputForward = FALSE;
00155     CurrentStripSize = 0;
00156     IsFirstStrip = TRUE;
00157     OutputPalette = NULL;
00158 }
00159 
00160 
00161 /********************************************************************************************
00162 
00163 >   void OutputDIB::PokePaletteEntry(LPLOGPALETTE Palette, INT32 index, BYTE red, BYTE green, BYTE blue)
00164 
00165     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00166     Created:    3/4/95
00167     Inputs:     Palette     palette to write to.
00168                 index       address of variable holding palette entry to write to
00169                 red         red value to enter into palette entry 
00170                 green       green value to enter into palette entry 
00171                 blue        blue value to enter into palette entry
00172     Outputs:    index incremented by one 
00173     Returns:    -
00174     Purpose:    Puts the required value of rgb into the specified palette entry.
00175     SeeAlso:    OutputDIB::StartFile;
00176 
00177 ********************************************************************************************/
00178 void OutputDIB::PokePaletteEntry(LPLOGPALETTE Palette, INT32 *index, BYTE red, BYTE green, BYTE blue)
00179 {
00180     Palette->palPalEntry[*index].peRed = red;   
00181     Palette->palPalEntry[*index].peGreen = green;   
00182     Palette->palPalEntry[*index].peBlue = blue; 
00183     Palette->palPalEntry[*index].peFlags = 0;
00184     // increment the counter and return it
00185     (*index) ++;    
00186 }
00187 
00188 
00189 /******************************************************************************************
00190 
00191 >   void OutputDIB::AlterExportPalette( LPLOGPALETTE pPalette )
00192 
00193     Author:     Alex_Price (Xara Group Ltd) <camelotdev@xara.com>
00194 
00195     Created:    20/07/99
00196 
00197     Inputs:     pPalette - Palette information that we want to copy from
00198 
00199     Returns:    -
00200 
00201     Purpose:    Copies information from the palette object passed in to OutputPalette.
00202                 This is used when the user has changed a colour using the bitmap
00203                 preview dialog's palette control
00204 
00205 ******************************************************************************************/
00206 
00207 void OutputDIB::AlterExportPalette( LPLOGPALETTE pPalette )
00208 {
00209     if (pPalette == NULL)
00210         return;
00211 /*
00212     // actually it appears it is safe to let this be filled in later if we havent got
00213     // an output palette yet
00214 
00215     // if we dont have an output palette we may as well create one now
00216     if (OutputPalette==NULL)
00217     {
00218         const size_t TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 256 );
00219         OutputPalette = (LPLOGPALETTE)CCMalloc( TotalPal );
00220         OutputPalette->palNumEntries = 256;
00221     }
00222 */  if (OutputPalette==NULL)
00223         return;
00224 
00225     INT32 PreviousNoOfEntries = OutputPalette->palNumEntries;
00226 
00227     INT32 Colours = OutputPalette->palNumEntries;
00228     for( INT32 j=0;j<Colours;j++)
00229     {
00230         // Set all the colours to 'non-renderable' first
00231         OutputPalette->palPalEntry[j].peFlags = 255;
00232     }
00233 
00234     Colours = pPalette->palNumEntries;
00235 
00236     INT32 i = 0;
00237     for(; i < Colours; i++ )
00238     {
00239         //  Copy the colour over to the correct place in OutputPalette
00240         OutputPalette->palPalEntry[i].peRed     = pPalette->palPalEntry[i].peRed;
00241         OutputPalette->palPalEntry[i].peGreen   = pPalette->palPalEntry[i].peGreen;
00242         OutputPalette->palPalEntry[i].peBlue    = pPalette->palPalEntry[i].peBlue;
00243 
00244         //  Indicate that we want to use the colour in rendering the image
00245         OutputPalette->palPalEntry[i].peFlags = pPalette->palPalEntry[i].peFlags;
00246     }
00247 
00248     for(; i < PreviousNoOfEntries; i++ )
00249     {
00250         //  excess colours are black
00251         OutputPalette->palPalEntry[i].peRed     = 0;
00252         OutputPalette->palPalEntry[i].peGreen   = 0;
00253         OutputPalette->palPalEntry[i].peBlue    = 0;
00254 
00255         //  Indicate that we dont want to use the colour in rendering the image
00256         OutputPalette->palPalEntry[i].peFlags = 255;
00257     }
00258 }
00259     
00260 /******************************************************************************************
00261 
00262 >   LPBITMAPINFO OutputDIB::GetDestBitmapInfo ( void )
00263 
00264     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00265     Created:    29/6/00
00266     Inputs:     pPalette - Palette information that we want to copy from
00267     Returns:    NULL
00268     Purpose:    Stub function to complete inheritance hierarchy.
00269 
00270 ******************************************************************************************/
00271 
00272 LPBITMAPINFO OutputDIB::GetDestBitmapInfo ( void )
00273 {
00274     // This function should never be called, so return NULL.
00275     return NULL;
00276 }
00277 
00278 /******************************************************************************************
00279 
00280 >   LPBYTE OutputDIB::GetDestBitmapBits ( void )
00281 
00282     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00283     Created:    29/6/00
00284     Inputs:     pPalette - Palette information that we want to copy from
00285     Returns:    NULL
00286     Purpose:    Stub function to complete inheritance hierarchy.
00287 
00288 ******************************************************************************************/
00289 
00290 LPBYTE OutputDIB::GetDestBitmapBits ( void )
00291 {
00292     // This function should never be called, so return NULL.
00293     return NULL;
00294 }
00295 
00296 /********************************************************************************************
00297 
00298 >   void OutputDIB::FixBlackAndWhitePalette(LPLOGPALETTE Palette)
00299 
00300     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00301     Created:    5/4/95
00302     Inputs:     Palette     palette to write to.
00303     Outputs:    -
00304     Returns:    -
00305     Purpose:    Corrects the first two palette entries to be a correct Gavin black and white
00306                 palette.
00307     SeeAlso:    OutputDIB::StartFile; OutputDIB::StartExport;
00308 
00309 ********************************************************************************************/
00310 void OutputDIB::FixBlackAndWhitePalette(LPLOGPALETTE Palette)
00311 {
00312     Palette->palNumEntries = 2;
00313 
00314     INT32 i = 0;
00315 PORTNOTE("BmapPrevDlg", "Removed use of bitmap preview dialog");
00316 #ifndef EXCLUDE_FROM_XARALX
00317     if( BmapPrevDlg::GetNumberOfTransparentColours() > 0 )
00318     {
00319         PokePaletteEntry(Palette, &i, 0xff, 0xff, 0xff);
00320         PokePaletteEntry(Palette, &i, 0x00, 0x00, 0x00);
00321     }
00322     else
00323 #endif
00324     {
00325         PokePaletteEntry(Palette, &i, 0x00, 0x00, 0x00);
00326         PokePaletteEntry(Palette, &i, 0xff, 0xff, 0xff);
00327     }
00328 }
00329 
00330 /********************************************************************************************
00331 
00332 >   void OutputDIB::Fix16ColourPalette(LPLOGPALETTE Palette)
00333 
00334     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00335     Created:    5/4/95
00336     Inputs:     Palette     palette to write to.
00337     Outputs:    -
00338     Returns:    -
00339     Purpose:    Corrects the first 16 palette entries to be a correct Gavin 16 colour palette.
00340     SeeAlso:    OutputDIB::StartFile; OutputDIB::StartExport;
00341 
00342 ********************************************************************************************/
00343 void OutputDIB::Fix16ColourPalette(LPLOGPALETTE Palette)
00344 {
00345     Palette->palNumEntries = 16;
00346 
00347     INT32 i = 0;
00348     // Bit more tricky this one, Gavin uses a fixed 16 colour palette           
00349     PokePaletteEntry(Palette, &i, 0x00, 0x00, 0x00); // black
00350     PokePaletteEntry(Palette, &i, 0x80, 0x00, 0x00); // brown
00351     PokePaletteEntry(Palette, &i, 0x00, 0x80, 0x00); // Half green
00352     PokePaletteEntry(Palette, &i, 0x80, 0x80, 0x00); // Half browny (red/green)
00353     PokePaletteEntry(Palette, &i, 0x00, 0x00, 0x80); // Dark blue
00354     PokePaletteEntry(Palette, &i, 0x80, 0x00, 0x80); // Mauve
00355     PokePaletteEntry(Palette, &i, 0x00, 0x80, 0x80); // greeny/blue
00356     PokePaletteEntry(Palette, &i, 0x80, 0x80, 0x80); // mid grey
00357 
00358     PokePaletteEntry(Palette, &i, 0xc0, 0xc0, 0xc0); // light grey
00359     PokePaletteEntry(Palette, &i, 0xff, 0x00, 0x00); // red
00360     PokePaletteEntry(Palette, &i, 0x00, 0xff, 0x00); // green
00361     PokePaletteEntry(Palette, &i, 0xff, 0xff, 0x00); // yellow
00362     PokePaletteEntry(Palette, &i, 0x00, 0x00, 0xff); // blue
00363     PokePaletteEntry(Palette, &i, 0xff, 0x00, 0xff); // magenta
00364     PokePaletteEntry(Palette, &i, 0x00, 0xff, 0xff); // cyan
00365     PokePaletteEntry(Palette, &i, 0xff, 0xff, 0xff); // white
00366 }   
00367 
00368 /********************************************************************************************
00369 
00370 >   BOOL OutputDIB::StartFile( CCLexFile *File, LPBITMAPINFOHEADER lpHeader, LPRGBQUAD Palette,
00371                             UINT32 OutputDepth, DWORD CompressionType,
00372                             UINT32 FinalHeight, INT32 SizeOfExport, BOOL SecondPass = FALSE )
00373 
00374     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00375     Created:    4/8/94
00376     Inputs:     File    opened file we can write to.
00377                 lpHeader        contains width & DPI of source & dest. biHeight & depth ignored.
00378                 Palette         pointer to bmiColor struct, or NULL if not used (can be temporary)
00379                 OutputDepth     depth of bitmap required on disk
00380                 CompressionType BI_RGB only supported (or CC_BMPTYPE for 32-bit with trans)
00381                 FinalHeight     output of entire bitmap on disk
00382                 ExportSize      The set progress bar size 
00383                 SecondPass      Flag for whether it is a second pass export render. (Used by
00384                                 GIF export only at present). Defaults to False.
00385     Returns:    TRUE if worked, FALSE if failed (error will be set accordingly but not reported)
00386     Purpose:    Get ready to write a bmp to disk, maybe in chunks showing a progress bar as we
00387                 write it.
00388                 Currently supports:-
00389                     source depth = 32, destintaiotn depth = 32, 24, 8, 4, 1
00390                     source depth = 8, destintaiotn depth = 8
00391     Errors:     Calls SetError on FALSE returns.
00392     SeeAlso:    OutputDIB::WriteBlock; OutputDIB::TidyUp
00393     SeeAlso:    OutputGIF::StartFile;
00394     Scope:      Public
00395 
00396 ********************************************************************************************/
00397 
00398 BOOL OutputDIB::StartFile( CCLexFile *File, LPBITMAPINFOHEADER lpHeader, LPLOGPALETTE Palette,
00399                            UINT32 OutputDepth, DWORD CompressionType,
00400                            UINT32 FinalHeight, INT32 ExportSize, BOOL SecondPass,
00401                            UINT32 DitherType )
00402 {
00403     // remember input args
00404     OutputFile = File;
00405     StartPos = OutputFile->tell();                      // remember where in the file this starts
00406     BitmapInfo = *lpHeader;                             // take a copy of user's header
00407     OutputPalette = NULL;                               // our form of the palette, if required
00408 
00409     HeightWritten = 0;                                  // our count of the bitmap lines written
00410     CurrentExportSize = ExportSize;                     // size set up for the progress bar
00411     HeightWanted = FinalHeight;                         // the actual height of the export required
00412 
00413     INT32 PalSize = 0;                                  // how many entries in palette
00414 
00415     // Remember which dithering type to use
00416     Dither = DitherType;
00417 
00418     IsFirstStrip = TRUE;
00419 
00420     // Set up the information header for the dib
00421     if ( !SetUpInfoHeader(lpHeader, OutputDepth, CompressionType, FinalHeight, &PalSize) )
00422         return FALSE;                                   // SetError already called 
00423 
00424     // BITMAPFILEHEADER goes first
00425     BITMAPFILEHEADER Header;
00426 
00427     Header.bfType = ('M'<<8) | 'B';
00428     Header.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
00429                     sizeof(RGBQUAD)*PalSize + BitmapInfo.biSizeImage;
00430     Header.bfReserved1 = 0;
00431     Header.bfReserved2 = 0;
00432     Header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
00433                         sizeof(RGBQUAD)*PalSize;
00434 
00435     OutputFile->write( &Header, sizeof(Header) );
00436 
00437 
00438     // then a local BITMAPINFOHEADER
00439 
00440     OutputFile->write( &BitmapInfo, sizeof(BITMAPINFOHEADER) );
00441 
00442     // then the RGBQUAD palette
00443     if (PalSize)
00444     {
00445         ERROR2IF(Palette == NULL,FALSE,"StartFile has a NULL Palette when one is required");
00446         // make a copy of the palette for possible later use
00447         const size_t TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * PalSize );
00448         OutputPalette = (LPLOGPALETTE)CCMalloc( TotalPal );
00449         if (OutputPalette==NULL)
00450             return FALSE;
00451 
00452         // Take a copy of that palette
00453         memcpy( OutputPalette, Palette, TotalPal );
00454 
00455         // write it to disk in RGBQUAD format
00456         RGBQUAD TempRGB;
00457         TempRGB.rgbReserved = 0;
00458         for (INT32 i=0; i<PalSize; i++)
00459         {
00460             TempRGB.rgbRed = OutputPalette->palPalEntry[i].peRed;
00461             TempRGB.rgbGreen = OutputPalette->palPalEntry[i].peGreen;
00462             TempRGB.rgbBlue = OutputPalette->palPalEntry[i].peBlue;
00463             OutputFile->write( &TempRGB, sizeof(RGBQUAD) );
00464         }
00465     }
00466 
00467     return !OutputFile->bad();
00468 }
00469 
00470 /********************************************************************************************
00471 
00472 >   BOOL OutputDIB::StartFile ( LPBITMAPINFOHEADER lpHeader,
00473                                 LPLOGPALETTE Palette,
00474                                 UINT32 OutputDepth,
00475                                 DWORD CompressionType,
00476                                 UINT32 FinalHeight,
00477                                 INT32 ExportSize,
00478                                 UINT32 DitherType )
00479 
00480     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00481     Created:    27/6/00
00482     Inputs:     All are meaningless.
00483     Returns:    FALSE.
00484     Purpose:    Stub function to be inherited over.
00485 
00486 ********************************************************************************************/
00487 
00488 BOOL OutputDIB::StartFile ( LPBITMAPINFOHEADER lpHeader,
00489                             LPLOGPALETTE Palette,
00490                             UINT32 OutputDepth,
00491                             DWORD CompressionType,
00492                             UINT32 FinalHeight,
00493                             INT32 ExportSize,
00494                             UINT32 DitherType )
00495 {
00496     return FALSE;
00497 }
00498 
00499 /********************************************************************************************
00500 
00501 >   BOOL OutputDIB::SetUpInfoHeader(const LPBITMAPINFOHEADER lpHeader, const UINT32 OutputDepth,
00502                                     const DWORD CompressionType, const UINT32 FinalHeight,
00503                                     INT32 * pPalSize)
00504 
00505     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00506     Created:    9/11/94
00507     Inputs:     lpHeader    contains width & DPI of source & dest. biHeight & depth ignored.
00508                 OutputDepth depth of bitmap required on disk
00509                 CompressionType BI_RGB only supported (or CC_BMPTYPE for 32-bit with trans)
00510                 FinalHeight output of entire bitmap on disk
00511     Outputs:    pPalSize    pointer to an integer PalSize variable which is the palette size
00512     Returns:    TRUE if worked, FALSE if failed (error will be set accordingly but not reported)
00513     Purpose:    Set up the information header for the DIB.
00514     Errors:     Calls SetError on FALSE returns.
00515     SeeAlso:    OutputDIB::StartFile; OutputDIB::WriteBlock; OutputDIB::TidyUp
00516     Scope:      Public
00517 
00518 ********************************************************************************************/
00519 
00520 BOOL OutputDIB::SetUpInfoHeader(const LPBITMAPINFOHEADER lpHeader, const UINT32 OutputDepth,
00521                                 const DWORD CompressionType, const UINT32 FinalHeight,
00522                                 INT32 * pPalSize)
00523 {
00524     if (
00525         (CompressionType != BI_RGB) &&                  // uncompressed is OK
00526         (CompressionType != CC_BMPTYPE)                 // so is RGBT
00527        )
00528     {
00529         // cannot do compression yet
00530         Error::SetError( _R(IDE_FORMATNOTSUPPORTED) );
00531         return FALSE;
00532     }
00533 
00534     // Fix up our copy of the header sohat it corresponds to the actual required one
00535     BitmapInfo.biCompression = CompressionType;     // fixup compression type
00536     BitmapInfo.biHeight = FinalHeight;              // fixup height to be true height
00537     BitmapInfo.biBitCount = OutputDepth;
00538 
00539     SourceBitmapDepth = lpHeader->biBitCount;
00540 
00541     const WORD DestDepth = BitmapInfo.biBitCount;
00542     UINT32 LineWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, OutputDepth );
00543 
00544     // source bitmap not necessarily same as required file depth
00545     // make sure we can handle conversion
00546     BOOL FormatOK = FALSE;
00547 
00548     switch (SourceBitmapDepth)
00549     {
00550         case 32:
00551             {
00552                 switch (DestDepth)
00553                 {
00554                     case 32:
00555                         {
00556                             // 32->32 might use our special type CC_BMPTYPE
00557                             FormatOK = TRUE;
00558                         }
00559                         break;
00560                     case 24:
00561                         {
00562                             // 32->24 bit is fine
00563                             if (CompressionType==BI_RGB)
00564                             {
00565                                 // might be BITFIELDs for rendering purposes
00566                                 BitmapInfo.biCompression = BI_RGB;
00567                                 BitmapInfo.biBitCount = 24;
00568                                 FormatOK = TRUE;
00569                             }
00570                         }
00571                         break;
00572                     case 8:
00573                         {
00574                             // 32->8 is OK
00575                             FormatOK = TRUE;
00576                             *pPalSize = 256;
00577                         }
00578                         break;
00579                     case 4:
00580                         {
00581                             // 32->4 is OK
00582                             FormatOK = TRUE;
00583                             *pPalSize = 16;
00584                         }
00585                         break;
00586                     case 1:
00587                         {
00588                             // 32->1 is OK
00589                             FormatOK = TRUE;
00590                             *pPalSize = 2;
00591                         }
00592                         break;
00593                     default:
00594                         // other source formats here
00595                         break;
00596                 }
00597                 
00598             }
00599             break;
00600         case 8:
00601             if (DestDepth==8)
00602             {
00603                 // 8->8 is OK
00604                 FormatOK = TRUE;
00605                 *pPalSize = 256;
00606             }
00607             break;
00608         default:
00609             // other source formats here
00610             break;
00611     }
00612 
00613     if (!FormatOK)
00614     {
00615         Error::SetError( _R(IDE_FORMATNOTSUPPORTED) );
00616         return FALSE;
00617     }
00618 
00619     BitmapInfo.biSizeImage = LineWidth * FinalHeight;
00620 
00621     return TRUE;
00622 }
00623 
00624 /********************************************************************************************
00625 
00626 >   BOOL OutputDIB::WriteBlock( UINT32 YPos, UINT32 Height, LPBYTE BlockStart, UINT32 InputBPP = 32,
00627                             INT32 ProgressOffset = 0)
00628 
00629     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00630     Created:    4/8/94
00631     Inputs:     YPos        pixel co-ord of the chunk of DIB we are about to write out (0=bottom,
00632                             increasing as it goes up).
00633                 Height      height in pixels of this chunk
00634                 BlockStart  the start address of the bytes of this chunk
00635     (optional)  InputBPP    BPP of the input image (assumed 32 by default - 8 also works)
00636                 ProgressOffset  value to add to value passed to ContinueSlowJob (default 0).
00637     Returns:    TRUE if worked, FALSE if failed (error will be set accordingly but not reported)
00638     Purpose:    Writes a chunk of bitmap data to the device.
00639                 Assumes a progress hourglass is required and the caller has started an hourglass
00640                 with a size of 100 and will end it.
00641     Notes:      Originally this routine assumed that it was being given a 32bpp bmp, but using
00642                 the InputBPP param it will now handle 8bpp bmps as well...
00643     Errors:     Calls SetError on FALSE returns.
00644     Scope:      Public
00645 
00646 ********************************************************************************************/
00647 
00648 BOOL OutputDIB::WriteBlock( UINT32 YPos, UINT32 Height, LPBYTE BlockStart, UINT32 InputBPP,
00649                             INT32 ProgressOffset)
00650 {
00651     FNPTR_SCANLINE ConvertFn = NULL;
00652     LPBYTE Buffer = NULL;
00653     size_t BufSize = 0L;
00654     size_t ChunkHeight = 1;
00655     DIBConvert *DoConvert = NULL;
00656 
00657     // Set up the size and other information for the dib block that we require. This is
00658     // dependent on the export depth or bpp required.
00659     if ( !SetUpBlock( &BufSize, &ChunkHeight, &DoConvert, &ConvertFn ) )
00660         return FALSE;           // Error details already set up
00661 
00662     if (BufSize)
00663     {
00664         Buffer = (LPBYTE)CCMalloc( BufSize );
00665         if (Buffer==NULL)
00666             return FALSE;
00667     }
00668 
00669     if ( DoConvert )
00670     {
00671         // use new classes to do it
00672         // 8bpp, 4bpp and 1bpp conversion
00673         INT32 h = Height;
00674         INT32 count = 0;
00675         LPBYTE Data = BlockStart;
00676         const size_t SourceWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, InputBPP ) * ChunkHeight;
00677         const size_t DestWidth   = DIBUtil::ScanlineSize( BitmapInfo.biWidth, BitmapInfo.biBitCount );
00678 
00679         while (h)
00680         {
00681             ENSURE(h >= 0, "bad looping");
00682 
00683             const size_t ThisBit = min( h, (INT32)ChunkHeight );
00684             if (!DoConvert->Convert( Data, Buffer, ThisBit, IsFirstStrip ))
00685                 break;                              // stop if conversion failed
00686 
00687             IsFirstStrip = FALSE;
00688 
00689             OutputFile->write( Buffer, ThisBit * DestWidth );
00690             if (OutputFile->bad())
00691                 break;                              // stop if file errored
00692             Data += SourceWidth;
00693             h -= ThisBit;
00694 
00695             // now update the progress display, started with CurrentExportSize
00696             // CurrentExport size is now the point to go from in the export
00697             count++;
00698             ContinueSlowJob( (INT32)( ProgressOffset + count ));
00699             //ContinueSlowJob( (INT32)(100*count/(Height)) );
00700         }
00701     }
00702     // now the bytes (this is crying out for a virtual function or two)
00703     else if ( ConvertFn && Buffer )
00704     {
00705         // Write via conversion function
00706         // 24 bpp convert
00707         UINT32 h = Height;
00708         INT32 count = 0;
00709         LPBYTE Data = BlockStart;
00710         const size_t SourceWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, InputBPP );
00711 
00712         while (h)
00713         {
00714             ConvertFn( BitmapInfo.biWidth, Data, Buffer );
00715             OutputFile->write( Buffer, BufSize );
00716             if (OutputFile->bad())
00717                 break;                              // stop if file errored
00718             Data += SourceWidth;
00719             h -= ChunkHeight;
00720 
00721             // now update the progress display, started with CurrentExportSize
00722             // ProgressOffset size is now the point to go from in the export
00723             count++;
00724             ContinueSlowJob( (INT32)( ProgressOffset + count ));
00725             //ContinueSlowJob( (INT32)((CurrentExportSize * count)/Height) );
00726         }
00727     }
00728     else
00729     {
00730         // Write it all out in one go
00731         //OutputFile->write( BlockStart, BitmapInfo.biSizeImage );
00732         // Write the actual bytes out to file. Used to do it in one go but we really
00733         // require some progress bar indication so we will do it in chunks.
00734         DWORD BitsSize = BitmapInfo.biSizeImage; 
00735         if (BitsSize > 0)
00736         {
00737             if (BitsSize < 1024)
00738             {
00739                 // File very small or no progress bar required, so load in one go
00740                 OutputFile->write( BlockStart, BitsSize);
00741             }
00742             else
00743             {
00744                 // Load in chunks, for present split into 100 chunks
00745                 DWORD ChunkSize = BitsSize/100;
00746                 DWORD Position = 0;
00747                 LPBYTE pBitInfo = BlockStart;
00748                 
00749                 while (Position < BitsSize)
00750                 {
00751                     if ( (BitsSize - Position) > ChunkSize)
00752                         OutputFile->write( pBitInfo, ChunkSize);
00753                     else
00754                     {
00755                         ChunkSize = BitsSize - Position;
00756                         OutputFile->write( pBitInfo, ChunkSize);
00757                     }
00758                             
00759                     // Increment our counters/pointers
00760                     Position+=ChunkSize;
00761                     pBitInfo+=ChunkSize;
00762                     // Progress bar started with height of bitmap
00763                     ContinueSlowJob( (INT32)(ProgressOffset + (Height * Position)/BitsSize) );
00764                     //ContinueSlowJob( (INT32)((CurrentExportSize * Position)/BitsSize) );
00765                 }
00766             }
00767         }
00768     }
00769 
00770     // If present, get rid of our export function
00771     if (DoConvert)
00772     {
00773         delete DoConvert;
00774         DoConvert = NULL;
00775     }
00776 
00777     CCFree( Buffer );
00778 
00779     HeightWritten += Height;                        // remember we wrote this lot
00780 
00781     return !OutputFile->bad();
00782 }
00783 
00784 /********************************************************************************************
00785 //
00786 // These are the forms used by the Accusoft filters and hence do not write out the data
00787 // themselves but get called back to supply the data.  
00788 //
00789 ********************************************************************************************/
00790 
00791 // The following function is no longer used but retained for informational reasons
00792 #if 0
00793 /********************************************************************************************
00794 
00795 >   BOOL OutputDIB::SetUpExport( CCLexFile *File, LPBITMAPINFOHEADER lpHeader, LPRGBQUAD Palette,
00796                                  UINT32 DitherType, UINT32 OutputDepth, DWORD CompressionType, UINT32 FinalHeight,
00797                                  LPBYTE BlockStart, UINT32 StripSize, INT32 ExportSize, BOOL Forward)
00798 
00799     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00800     Created:    9/11/94
00801     Inputs:     File            opened file we can write to.
00802                 lpHeader        contains width & DPI of source & dest. biHeight & depth ignored.
00803                 Palette         pointer to bmiColor struct, or NULL if not used (can be temporary)
00804                 OutputDepth     depth of bitmap required on disk
00805                 CompressionType BI_RGB only supported (or CC_BMPTYPE for 32-bit with trans)
00806                 FinalHeight     output of entire bitmap on disk
00807                 BlockStart      pointer to the start of the bitmap data
00808                 StripSize       size of the first strip to be rendered
00809                 ExportSize      The set progress bar size 
00810                 Forward         dictates whether we are to write the data out forwards or backwards
00811     Returns:    TRUE if worked, FALSE if failed (error will be set accordingly but not reported)
00812     Purpose:    Same as OutputDIB::StartFile but does not actually write the data to a file
00813                 but instead tries to get ready to write a bmp out to disk via the Accusoft or
00814                 other external filters, maybe in chunks showing a progress bar as we write it.
00815                 Currently supports:-
00816                     source depth = 32, destintaiotn depth = 32, 24, 8, 4, 1
00817                     source depth = 8, destintaiotn depth = 8
00818                 We need to be able to write data from the bottom to the top of the DIB as well
00819                 as from the top to the bottom as it would appear that the Accusoft DLL tries to
00820                 be clever and save DIBs forward and everything else backwards. 
00821     Errors:     Calls SetError on FALSE returns.
00822     SeeAlso:    OutputDIB::StartFile; OutputDIB::WriteBlock; OutputDIB::TidyUp; OutputDIB::GetNextBlock
00823     Scope:      Public
00824 
00825 ********************************************************************************************/
00826 
00827 BOOL OutputDIB::SetUpExport( CCLexFile *File, LPBITMAPINFOHEADER lpHeader, LPLOGPALETTE Palette,
00828                              UINT32 DitherType, UINT32 OutputDepth, DWORD CompressionType, UINT32 FinalHeight,
00829                              LPBYTE BlockStart, UINT32 StripSize, INT32 ExportSize, BOOL Forward )
00830 {
00831     ERROR2IF(File==NULL, FALSE, "OutputDIB::SetUpExport null File specified");
00832     ERROR2IF(lpHeader==NULL, FALSE, "OutputDIB::SetUpExport null lpHeader specified");
00833     ERROR2IF(BlockStart==NULL, FALSE, "OutputDIB::SetUpExport null BlockStart specified");
00834 
00835     // remember input args
00836     OutputFile = File;
00837     StartPos = OutputFile->tell();                      // remember where in the file this starts
00838     BitmapInfo = *lpHeader;                             // take a copy of user's header
00839     OutputPalette = NULL;                               // No palette to start with
00840     HeightWritten = 0;                                  // zero height
00841     OutputForward = Forward;                            // Note the output direction
00842     CurrentStripSize = StripSize;                       // Note size of first strip
00843     CurrentExportSize = ExportSize;                     // size set up for the progress bar
00844     HeightWanted = FinalHeight;                         // the actual height of the export required
00845 
00846     // Remember which dithering type to use
00847     Dither = DitherType;
00848 
00849     IsFirstStrip = TRUE;
00850 
00851     ExportBuffer = NULL;    // Just in case of early random exit set this to NULL
00852 
00853     INT32 PalSize = 0;                                  // how many entries in palette
00854 
00855     // Set up the information header for the dib
00856     if ( !SetUpInfoHeader(lpHeader, OutputDepth, CompressionType, FinalHeight, &PalSize) )
00857         return FALSE;                                   // SetError already called 
00858 
00859     // then the RGBQUAD palette, if required
00860     if (PalSize)
00861     {
00862         ERROR2IF(Palette == NULL,FALSE,"SetUpExport has a NULL Palette when one is required");
00863         // If we are creating a palette then the Accusoft code requires that we specify an
00864         // bitmap info header which is followed immediately in memory by the palette.
00865         // if we just created a Palette then this would not be true so we must create a
00866         // new copy of the Bitmapinfo and then create the palette next.
00867         // This will not work in debug builds due to memory tracking information stored
00868         // in the allocation so we must allocate one big block and do the info header and
00869         // Palette from these.
00870         const size_t TotalHeader = sizeof(BITMAPINFOHEADER); 
00871         const size_t TotalPalSize = (sizeof(RGBQUAD) * PalSize );
00872         lpBitmap = (LPBITMAPINFO)CCMalloc( TotalHeader + TotalPalSize );
00873         if (lpBitmap==NULL)
00874             return FALSE;
00875 
00876         // make a copy of the palette for possible later use
00877         const size_t TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * PalSize );
00878         
00879         OutputPalette = (LPLOGPALETTE)CCMalloc( TotalPal );
00880         if (OutputPalette==NULL)
00881             return FALSE;
00882         memcpy( OutputPalette, Palette, TotalPal );
00883         
00884         // These are all freed in the TidyUp call.
00885 
00886         // Take a copy of the bitmap info header
00887         lpBitmapInfo = &(lpBitmap->bmiHeader);              // pointer to info header
00888         memcpy( lpBitmapInfo, &BitmapInfo, TotalHeader );   // copy header info across
00889 
00890         // Now get a pointer to the palette
00891         LPRGBQUAD lpPalette = NULL;
00892         lpPalette = &(lpBitmap->bmiColors[0]);              // pointer to colours table
00893 
00894         // Now copy the palette across into the bitmap info structure in RGQUAD form
00895         // OutputPalette should be set up by now so use this instead of Palette so if
00896         // we have bodged it, it will be the correct bodged palette that is put into the file
00897         // and not the 256 entry palette that seems to be supplied always.
00898 
00899         //  We might want to use the existing palette - e.g. when we are altering the value
00900         //  of a single colour.
00901             //  Don't want to use the existing palette.
00902         for (INT32 i = 0; i < PalSize; i++)
00903         {
00904             lpPalette->rgbRed   = OutputPalette->palPalEntry[i].peRed;
00905             lpPalette->rgbGreen = OutputPalette->palPalEntry[i].peGreen;
00906             lpPalette->rgbBlue  = OutputPalette->palPalEntry[i].peBlue;
00907             
00908             lpPalette++;
00909         }
00910 
00911     }
00912 
00913     // Now lets grab the memory and then set up the first block of data ready for output
00914     size_t BufSize = 0L;
00915     ExportChunkHeight = 1;
00916 
00917     DoExportConvert = NULL;     // Just in case the SetUpBlock fails 
00918     ExportConvertFn = NULL;     // Just in case the SetUpBlock fails
00919     
00920     // Set up the size and other information for the dib block that we require. This is
00921     // dependent on the export depth or bpp required.
00922     if ( !SetUpBlock( &BufSize, &ExportChunkHeight, &DoExportConvert, &ExportConvertFn ) )
00923         return FALSE;           // Error details already set up
00924 
00925 //TRACEUSER( "Neville", _T("SetUpExport BufSize = %d\n"),BufSize);
00926 //TRACEUSER( "Neville", _T("SetUpExport ExportChunkHeight = %d\n"),ExportChunkHeight);
00927 //TRACEUSER( "Neville", _T("SetUpExport FinalHeight = %d\n"),FinalHeight);
00928 //TRACEUSER( "Neville", _T("SetUpExport CurrentStripSize = %d\n"),CurrentStripSize);
00929 //TRACEUSER( "Neville", _T("SetUpExport DoExportConvert = %d\n"),DoExportConvert);
00930 //TRACEUSER( "Neville", _T("SetUpExport ExportConvertFn = %d\n"),ExportConvertFn);
00931 
00932     // Check for the case where we are exporting a small thin strip which is smaller
00933     // than our normal strip  
00934     if (CurrentStripSize < ExportChunkHeight)
00935     {
00936         ExportChunkHeight = CurrentStripSize;
00937 //TRACEUSER( "Neville", _T("New ExportChunkHeight = %d\n"),ExportChunkHeight);
00938     }
00939 
00940     if (BufSize)
00941     {
00942         ExportBuffer = (LPBYTE)CCMalloc( BufSize );
00943         if (ExportBuffer==NULL)
00944             return FALSE;
00945     }
00946     
00947     // Now get the actual class variables set up ready for this data
00948     SetUpForNextStrip(BlockStart, CurrentStripSize);
00949 
00950     // Now lets start the whole export process off by calling the StartSaveBitmap function
00951     // which will start the actual exporting process off with the supplied information.
00952     // This will then request blocks of data from the DestDIB in its call back routine
00953     // get_dib_data.
00954 
00955     // If we have created a palette then use the special header which has a valid palette
00956     // following immediately after it in memory
00957     LPBITMAPINFOHEADER lpSpBitmapInfo = NULL;
00958     if (PalSize)
00959         lpSpBitmapInfo = lpBitmapInfo;      // Use our specially create header followed by palette
00960     else
00961         lpSpBitmapInfo = &BitmapInfo;       // Use the proper header defined in the class
00962 
00963 #ifndef WEBSTER
00964     //WEBSTER-Martin-07/01/97
00965     // no Accusoft stuff in WEBSTER, and I'm not sure it ever gets used in Camelot any
00966     // more (the DIB bits of Accusoft that is)
00967     // TRACEUSER( "Martin", _T("Not allowed to use Accusoft save bitmap\n"));
00968     if (!AccusoftFilters::StartSaveBitmap(  OutputFile,     // File to use
00969                                             lpSpBitmapInfo, // pointer to info header
00970                                             OutputPalette,  // pointer to the palette
00971                                             OutputDepth,    // actual file depth
00972                                             BI_RGB,         // compression (BI_RGB = none)
00973                                             FinalHeight,    // all of it
00974                                             StripSize,      // size of the strip, might be FinalHeight
00975                                             OutputForward)  // direction we were told on entry
00976        )
00977 #endif //WEBSTER
00978     {
00979         return FALSE;   //always for WEBSTER
00980     }
00981 
00982     return TRUE;
00983 }
00984 #endif
00985 
00986 
00987 /********************************************************************************************
00988 
00989 >   static BOOL OutputDIB::GetNextBlock( UINT32 YPos, UINT32 Height, LPBYTE BlockStart,
00990                                          LPBYTE *Buffer, UINT32 *CurrentBlockSize,
00991                                          INT32 *CurrentStartYPos)
00992 
00993     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00994     Created:    9/11/94
00995     Inputs:     YPos                pixel co-ord of the chunk of DIB we are about to write out 
00996                                     (0 = bottom, increasing as it goes up).
00997                 Height              height in pixels of this chunk
00998                 BlockStart          the start address of the bytes of this chunk
00999     Outputs:    Buffer              pointer to the returned buffer filled up with DIB bytes
01000                 CurrentBlockSize    current size of the block being rendered 
01001                 CurrentStartYPos    current position of the start of this block of data
01002                 WrittenSoFar        the amount of the bitmap written to date
01003     Returns:    TRUE if worked, FALSE if failed (error will be set accordingly but not reported)
01004     Purpose:    Gets the next chunk of bitmap data ready to be written out via the Accusoft or
01005                 other external filters.
01006                 SetUpExport is used to set up everything before this fucntion is called.
01007                 OutputForward determines the direction of export, set up in SetUpExport
01008     Errors:     Calls SetError on FALSE returns.
01009     SeeAlso:    OutputDIB::WriteBlock; OutputDIB::SetUpExport;
01010     Scope:      Public
01011 
01012 ********************************************************************************************/
01013 
01014 BOOL OutputDIB::GetNextBlock( UINT32 YPos, UINT32 Height, LPBYTE BlockStart,
01015                               LPBYTE *Buffer, INT32 *CurrentBlockSize,
01016                               INT32 *CurrentStartYPos, UINT32 *WrittenSoFar)
01017 {
01018     // Get the next block ready for export a line at a time
01019     *Buffer = NULL;             // Just in case of early random exit set this to NULL
01020     *CurrentBlockSize = 0;      // Just in case of early random exit set this to 0
01021 
01022     // Convert the next strip 
01023     if ( DoExportConvert )
01024     {
01025 //TRACEUSER( "Neville", _T("GetNextBlock DoExportConvert\n"));
01026         // 8 bpp, 4bpp and 1bpp export
01027         ERROR2IF(ExportData < BlockStart, FALSE, "GetNextBlock ExportData < BlockStart");
01028         ERROR2IF(Height - CurrentYPos < 0, FALSE, "GetNextBlock Height - CurrentYPos < 0");
01029         // Work out the size of the export chunk left, normally ExportChunkHeight but
01030         // if at the end of export may be a small strip left.
01031         const size_t ThisBit = min( (INT32)(Height - CurrentYPos), (INT32)ExportChunkHeight );
01032         if (!DoExportConvert->Convert( ExportData, ExportBuffer, ThisBit, IsFirstStrip ))
01033             return FALSE;                           // stop if conversion failed
01034 
01035         IsFirstStrip = FALSE;
01036 
01037         // We have in ExportData a size of data block = ThisBit * ExportDestWidth
01038         // On last strip may be less than ExportChunkHeight in depth 
01039         CurrentYPos += ThisBit;                     // Move down by a strips worth
01040 
01041         if (OutputForward)
01042         {
01043             ExportData += ExportSourceWidth;        // Move on by a lines worth
01044         }
01045         else
01046         {
01047             if ((Height - CurrentYPos) < ExportChunkHeight )
01048                 ExportData = BlockStart;                // On last strip so do from start
01049             else
01050                 ExportData -= ExportSourceWidth;        // Move on by a lines worth
01051             if (ExportData < BlockStart)                // Just in case test
01052                 ExportData = BlockStart;                
01053         }
01054 
01055         // Set up return variables
01056         *Buffer = ExportBuffer;                     // return our new buffer to the caller
01057         *CurrentBlockSize = ThisBit;                // return size of this block
01058         *CurrentStartYPos = CurrentYPos;            // return current start of strip
01059         
01060         HeightWritten += ThisBit;                   // remember we wrote this lot
01061     }
01062     // now the bytes (this is crying out for a virtual function or two)
01063     else if ( ExportConvertFn && ExportBuffer )
01064     {
01065         // 24 bpp convert
01066 //TRACEUSER( "Neville", _T("GetNextBlock Do export via convert function\n"));
01067         ERROR2IF(ExportData < BlockStart, FALSE, "GetNextBlock ExportData < BlockStart");
01068         // write data via conversion function
01069         ExportConvertFn( BitmapInfo.biWidth, ExportData, ExportBuffer );
01070 
01071         if (OutputForward)
01072         {
01073             // We have in ExportBuffer an amount of BuffSize worth of data
01074             ExportData += ExportSourceWidth;
01075             CurrentYPos -= ExportChunkHeight;
01076         }
01077         else
01078         {
01079             // We have in ExportBuffer an amount of BuffSize worth of data
01080             ExportData -= ExportSourceWidth;
01081             CurrentYPos += ExportChunkHeight;
01082         }
01083 
01084         // Set up return variables
01085         *Buffer = ExportBuffer;                     // return our new buffer to the caller
01086         *CurrentBlockSize = ExportChunkHeight;      // return size of this block
01087         *CurrentStartYPos = CurrentYPos;            // return current start of strip
01088 
01089         HeightWritten += ExportChunkHeight;         // remember we wrote this lot
01090     
01091     }
01092     else
01093     {
01094 //TRACEUSER( "Neville", _T("GetNextBlock all in one go\n"));
01095         // Write it all out in one go, 32bpp export
01096         // We have in the DIB at BlockStart an amount of BitmapInfo.biSizeImage worth of data
01097         // Set up return variables
01098         *Buffer = BlockStart;                       // return our new buffer to the caller
01099         *CurrentBlockSize = BitmapInfo.biSizeImage; // return size of this block
01100 
01101         HeightWritten += Height;                    // remember we wrote this lot
01102     }
01103 
01104     // Return the amount of data written so far  
01105     *WrittenSoFar = HeightWritten;
01106 
01107     return TRUE;
01108 }
01109 
01110 /********************************************************************************************
01111 
01112     static BOOL OutputDIB::SetUpForNextStrip(LPBYTE StartOfBytes, UINT32 StripHeight)
01113 
01114     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01115     Created:    15/5/95
01116     Inputs:     StartOfBytes    start of the actual bitmap data (bits)
01117                 StripHeight     height of this strip
01118     Outputs:    -
01119     Returns:    TRUE if worked, FALSE if failed
01120     Purpose:    Gets the class variables ready for the first/next strip of the render region
01121                 as we are rendering in strips.
01122     Scope:      Public Static
01123 
01124 ********************************************************************************************/
01125 
01126 BOOL OutputDIB::SetUpForNextStrip(LPBYTE StartOfBytes, UINT32 StripHeight)
01127 {
01128     // We have rendered the next strip into the render region so reset everything back
01129     // to start outputting this strip instead of the old one
01130     CurrentStripSize = StripHeight;
01131 //TRACEUSER( "Neville", _T("OutputDIB::SetUpForNextStrip StripHeight=%d\n"),StripHeight);
01132 //TRACEUSER( "Neville", _T("OutputDIB::SetUpForNextStrip HeightWritten=%d\n"),HeightWritten);
01133      
01134     // Now get the actual data ready
01135     if ( DoExportConvert )
01136     {
01137 //TRACEUSER( "Neville", _T("OutputDIB::SetUpForNextStrip DoExportConvert\n"));
01138         // 8bpp, 4bpp and 1bpp conversion
01139         UINT32 LineWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 32 );
01140         ExportSourceWidth =  LineWidth * ExportChunkHeight;
01141         ExportDestWidth   = DIBUtil::ScanlineSize( BitmapInfo.biWidth, BitmapInfo.biBitCount );
01142 
01143         if (OutputForward)
01144         {
01145             // Set up the pointer to the first block of DIB bytes to export
01146             // In this forward direction it is the start of the first strip of the DIB
01147             ExportData = StartOfBytes;
01148         }
01149         else
01150         {
01151             // Set up the pointer to the first block of DIB bytes to export
01152             // Which is the start of the last strip of the DIB
01153             ExportData = StartOfBytes + ((StripHeight * LineWidth) - ExportSourceWidth);
01154         }
01155     }
01156     // now the bytes (this is crying out for a virtual function or two)
01157     else if ( ExportConvertFn && ExportBuffer )
01158     {
01159 //TRACEUSER( "Neville", _T("OutputDIB::SetUpForNextStrip Do via convert function to ExportBuffer\n"));
01160         // 24 bpp convert
01161         ExportSourceWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 32 );
01162 
01163         if (OutputForward)
01164         {
01165             // Set up the pointer to the first block of DIB bytes to export
01166             // In this forward direction it is the start of the first strip of the DIB
01167             ExportData = StartOfBytes;
01168         }
01169         else
01170         {
01171             // Set up the pointer to the first block of DIB bytes to export
01172             // Which is the start of the last strip of the DIB
01173             ExportData = StartOfBytes + ((StripHeight - 1) * ExportSourceWidth);
01174         }
01175     }
01176     else
01177     {
01178 //TRACEUSER( "Neville", _T("OutputDIB::SetUpForNextStrip Do all in one go\n"));
01179         // We will write it all in one go
01180         ExportData = StartOfBytes;      // pointer to the DIB bytes
01181     }
01182 //TRACEUSER( "Neville", _T("ExportSourceWidth = %d\n"),ExportSourceWidth);
01183 //TRACEUSER( "Neville", _T("ExportDestWidth = %d\n"),ExportDestWidth);
01184 
01185     // Just in case the initial block is smaller than the usual output depth and hence
01186     // we will be trying to export data to before the start of the block. A quick check
01187     // is in order.
01188     if (ExportData < StartOfBytes)              // Just in case 
01189         ExportData = StartOfBytes;              
01190 
01191     // Set up the starting parameters of the export operation.
01192     // Remember we have to export from the end of the DIB up to the start otherwise
01193     // the output will be upside down.
01194     CurrentYPos = 0;                    // size of DIB in scan lines
01195 
01196     return TRUE;
01197 }   
01198 
01199 /********************************************************************************************
01200 
01201 >   BOOL OutputDIB::SetUpBlock( size_t *pBufSize, size_t *pChunkHeight, DIBConvert **pDoConvert,
01202                                 FNPTR_SCANLINE *pConvertFn )
01203 
01204     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01205     Created:    9/11/94
01206     Inputs:
01207     Outputs:    pBufSize    pointer to a size_t which gives the buffer size required for this
01208                             output depth.
01209                 pChunkHeight    pointer to a size_t which gives the size of chunk required for
01210                                 this output depth.
01211                 pDoConvert  pointer to a pointer to a dib convert class for this depth.
01212                 pConvertFn  pointer to a convert function pointer
01213     Returns:    TRUE if worked, FALSE if failed (error will be set accordingly but not reported)
01214     Purpose:    Gets the next chunk of bitmap data ready to be written out via the Accusoft or
01215                 other external filters.
01216     Notes:      This routine will currently handle conversions from 32->32, 32->24, 32->8 and
01217                 now 8->8.
01218     Errors:     Calls SetError on FALSE returns.
01219     Scope:      Public
01220 
01221 ********************************************************************************************/
01222 
01223 BOOL OutputDIB::SetUpBlock( size_t *pBufSize, size_t *pChunkHeight, DIBConvert **pDoConvert,
01224                             FNPTR_SCANLINE *pConvertFn )
01225 {
01226     BOOL Problems = FALSE;
01227 
01228     switch (SourceBitmapDepth)
01229     {
01230         case 32:
01231         {
01232             switch (BitmapInfo.biBitCount)
01233             {
01234                 case 32:
01235                     {
01236                         // real 32-bit BMPs here
01237                         // our 'filter' zeros the transparency bits
01238                         *pConvertFn = DIBUtil::Convert32to32;
01239                         *pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 32 );
01240                     }
01241                     break;
01242                 case 24:
01243                     {
01244                         // convert 32-bit BMPs to 24-bit ones so things can read them
01245                         *pConvertFn = DIBUtil::Convert32to24;                           // 32->24
01246                         *pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 24 );    // size of 24-bit scanline
01247                     }
01248                     break;
01249                 case 8:
01250                     {
01251                         // 32->8 we do in bigger chunks because of dithering
01252                         *pDoConvert = DIBConvert::Create( SourceBitmapDepth, 8, BitmapInfo.biWidth, OutputPalette, Dither );
01253                         if (*pDoConvert==NULL)
01254                         {
01255                             ENSURE(FALSE, "DIBConvert::Create returned NULL");
01256                             return FALSE;
01257                         }
01258                         *pChunkHeight = 16;
01259                         *pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 8 ) * (*pChunkHeight);
01260                     }
01261                     break;
01262                 case 4:
01263                     {
01264                         // 32->4 we do in bigger chunks because of dithering
01265                         *pDoConvert = DIBConvert::Create( SourceBitmapDepth, 4, BitmapInfo.biWidth, OutputPalette, Dither );
01266                         if (*pDoConvert==NULL)
01267                         {
01268                             ENSURE(FALSE, "DIBConvert::Create returned NULL");
01269                             return FALSE;
01270                         }
01271                         *pChunkHeight = 16;
01272                         *pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 4 ) * (*pChunkHeight);
01273                     }
01274                     break;
01275                 case 1:
01276                     {
01277                         // 32->1 we do in bigger chunks because of dithering
01278                         *pDoConvert = DIBConvert::Create( SourceBitmapDepth, 1, BitmapInfo.biWidth, OutputPalette, Dither );
01279                         if (*pDoConvert==NULL)
01280                         {
01281                             ENSURE(FALSE, "DIBConvert::Create returned NULL");
01282                             return FALSE;
01283                         }
01284                         *pChunkHeight = 16;
01285                         *pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 1 ) * (*pChunkHeight);
01286                     }
01287                     break;
01288                 default:
01289                     Problems = TRUE;
01290                     break;
01291             }
01292             break;
01293         }
01294         case 8:
01295             if (BitmapInfo.biBitCount==8)
01296             {
01297                 // real 8-bit BMPs here
01298                 // we basically just do a memory copy from source to dest
01299                 *pConvertFn = DIBUtil::Convert8to8;
01300                 *pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 8 );
01301                 break;
01302 
01303             }
01304             Problems = TRUE;
01305             break;
01306 
01307         default:
01308             Problems = TRUE;
01309             break;
01310     }
01311 
01312     if(Problems)
01313     {
01314         Error::SetError( _R(IDE_FORMATNOTSUPPORTED) );
01315         return FALSE;
01316     }
01317 
01318     return TRUE;
01319 }
01320 
01321 /********************************************************************************************
01322 
01323 >   BOOL OutputDIB::TidyUp()
01324 
01325     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
01326     Created:    4/8/94
01327     Returns:    TRUE if worked, FALSE if failed (error will be set accordingly but not reported)
01328     Purpose:    When everything has been done via WriteBlock, call this to update the header
01329                 etc. The caller is responsible for closing the file. The class CANNOT be used
01330                 for further output until StartFile is called again.
01331     Errors:     Calls SetError on FALSE returns.
01332     Scope:      Public
01333 
01334 ********************************************************************************************/
01335 
01336 BOOL OutputDIB::TidyUp()
01337 {
01338     BOOL Result = TRUE;
01339 
01340     if(OutputFile != NULL)
01341     {
01342         // Check that what we wrote was what was required in terms of number of lines
01343         // used to use BitmapInfo.biHeight but this may now be the height of a strip
01344 #ifdef _BATCHING         
01345         if ( HeightWritten != HeightWanted )
01346         {
01347             TRACEUSER( "Martin", _T("OutputDIB::TidyUp HeightReqd = %d  HeightWritten = %d\n"),
01348                 HeightWanted,HeightWritten);
01349         }
01350 #else   //cos this goes off
01351         ERROR3IF( HeightWritten != HeightWanted, "Wrote wrong amount of bitmap to disk");
01352 #endif
01353 
01354         // could do fixups into the header here etc when using compression
01355         Result = !OutputFile->bad();
01356 
01357         OutputFile = NULL;                              // stop usage until StartFile time
01358 
01359         // If 8, 4, 1bpp export then put back the recommended palette by destructing the
01360         // convert function.
01361         if (DoExportConvert)
01362         {
01363             delete DoExportConvert;
01364             DoExportConvert = NULL;
01365         }   
01366     }
01367 
01368     // Free up the bitmap info if present.
01369     // This contains the info header and palette
01370     if (lpBitmap)
01371     {
01372         CCFree(lpBitmap);
01373         lpBitmap = NULL;
01374     }
01375 
01376     // Free up the output palette buffer if present
01377     if (OutputPalette)
01378     {
01379         CCFree(OutputPalette);
01380         OutputPalette = NULL;
01381     }
01382 
01383     // Free up the export buffer if present
01384     if (ExportBuffer)
01385     {
01386         CCFree(ExportBuffer);
01387         ExportBuffer = NULL;
01388     }
01389 
01390     return Result;
01391 }

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