grndbrsh.cpp

Go to the documentation of this file.
00001 // $Id: grndbrsh.cpp 1755 2006-09-16 12:00:36Z 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 //GRenderBrush - implementation of the render region used for 
00100 // drawing brushes
00101 
00102 
00103 
00104 #include "camtypes.h"
00105 #include "grndbrsh.h"
00106 #include "grnddib.h"
00107 #include "grndrgn.h"
00108 //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 #include "osrndrgn.h"
00110 //#include "gdrawasm.h"
00111 #include "palman.h"
00112 //#include "view.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00114 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00115 #include "progress.h"
00116 #include "freehand.h"
00117 #include "freeinfo.h"
00118 //#include "freehres.h"
00119 #include  "offscrn.h"
00120 //#include "wbitmap.h"
00121 #include "oilruler.h"
00122 
00123 static RealLogPalette StandardPalette = 
00124 {
00125     0x300,
00126     256
00127 };
00128 
00129 static BYTE NoTransTable[256];                      // default translation table
00130 
00131 static BOOL ClippedPathIsValid;
00132 
00133 
00134 //#include "defcons.tab"
00135 
00136 // TODOG: Nasty local preference...
00137 static INT32 LargeGradTables = 0;
00138       
00139 // setting this to non-zero controls fresh bitmap initialisation
00140 #define FILL_BITMAP 0
00141 
00142 CC_IMPLEMENT_DYNAMIC( GRenderBrush, GRenderDIB )
00143 
00144 #define new CAM_DEBUG_NEW
00145 
00146 /********************************************************************************************
00147 
00148 >   GRenderBrush::GRenderBrush(DocRect ClipRegion, Matrix ConvertMatrix, FIXED16 ViewScale, UINT32 Depth, double dpi)
00149 
00150     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00151     Created:    20/12/99
00152     Inputs:     -
00153     Outputs:    -
00154     Returns:    -
00155     Purpose:    GRenderBrush constructor. Doesn't do anything actually, just calls base class.
00156                 INT32 dpi changed to double dpi (12/12/95) to improve the range of values allowed
00157                 at the < 1000dpi settings that we will be using.
00158     Errors:     -
00159     SeeAlso:    GRenderRegion::GRenderRegion
00160 
00161 ********************************************************************************************/
00162 
00163 GRenderBrush::GRenderBrush(DocRect ClipRegion, Matrix ConvertMatrix, FIXED16 ViewScale, UINT32 Depth, double dpi)
00164     : GRenderDIB( ClipRegion, ConvertMatrix, ViewScale, Depth, dpi)
00165 {
00166     lpPreConvertBrushBitmapInfo  = NULL;
00167     lpPostConvertBrushBitmapInfo = NULL;
00168     lpPreConvertBrushBits        = NULL;
00169     lpPostConvertBrushBits       = NULL;
00170     lpBrushBitmapInfo            = NULL;
00171     lpBrushBits                  = NULL;
00172     m_pPalette                   = NULL;
00173 
00174 //#ifdef NEWFASTBRUSHES
00175     m_pView = NULL;
00176     m_pCCamView = NULL;
00177 PORTNOTE("other", "Disable HDC stuff")
00178 #ifndef EXCLUDE_FROM_XARALX
00179     m_pDevContext = NULL;
00180     m_DeviceHdc = NULL;
00181 #endif
00182 //#endif
00183 }
00184 
00185 
00186 
00187 /********************************************************************************************
00188 
00189 >   GRenderBrush::~GRenderBrush()
00190 
00191     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00192     Created:    20/12/99
00193     Inputs:     -
00194     Outputs:    -
00195     Returns:    -
00196     Purpose:    GRenderBrush destructor. Frees up the bitmaps.
00197     Errors:     -
00198 
00199 ********************************************************************************************/
00200 
00201 GRenderBrush::~GRenderBrush()
00202 {   
00203     if (lpPreConvertBrushBitmapInfo != NULL && lpPreConvertBrushBits != NULL)
00204         FreeLPBits(lpPreConvertBrushBitmapInfo, lpPreConvertBrushBits);
00205 
00206     
00207     if (lpPostConvertBrushBitmapInfo != NULL && lpPostConvertBrushBits != NULL)
00208         FreeLPBits(lpPostConvertBrushBitmapInfo, lpPostConvertBrushBits);
00209 
00210 
00211     if (lpBrushBitmapInfo != NULL && lpBrushBits != NULL)
00212         FreeLPBits(lpBrushBitmapInfo, lpBrushBits);
00213 
00214     if (pBits != NULL && pBitmapInfo != NULL)
00215     {
00216         FreeLPBits( pBitmapInfo, pBits );
00217         SetBitmapPointers(NULL, NULL);
00218     }
00219     TRACEUSER( "Gavin", _T("GRenderBrush::~GRenderBrush - RenderFlags.Rendering = FALSE;\n"));
00220     RenderFlags.Rendering = FALSE;
00221     // will call GRenderDIBs destructor here
00222 }
00223 
00224 /********************************************************************************************
00225 
00226 >   void GRenderBrush::DrawToScreenNow()
00227 
00228     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00229     Created:    29/10/99
00230     Inputs:     
00231     Outputs:    
00232     Purpose:    This is a bit of a bodge function so that we could get the brush to draw 
00233                 itself to the screen ASAP.  It bypasses all the regular rendering rubbish 
00234                 and gets straight down to blitting.  
00235                 
00236 
00237 ********************************************************************************************/
00238 
00239 void GRenderBrush::DrawToScreenNow()
00240 {
00241     // this fn. basically blits to the screen, so we need to know, where on the source bitmap
00242     // we take our data, where on the destination bitmap we put it, and what size chunk we move
00243     
00244     INT32 DestX = WRect.GetLeft();
00245     INT32 DestY = WRect.GetTop();
00246     INT32 ViewWidth = WRect.GetWidth();
00247     INT32 ViewHeight= WRect.GetHeight();
00248     INT32 Width = 0;
00249     INT32 Height = 0;
00250     INT32 SourceX = WRect.GetLeft();
00251     INT32 SourceY = WRect.GetTop();
00252     
00253     // if ChangedBBox is set then we don't have to blit so much
00254     RECT UsedRect;
00255             
00256     if (GetDrawContext()->GetChangedBBox( &UsedRect ))
00257     {
00258         if ((UsedRect.right < UsedRect.left) ||
00259             (UsedRect.bottom< UsedRect.top ))
00260         {
00261             // Changed box is illegal so exit
00262             return;
00263         }
00264         else
00265         {
00266             View*   pView = NULL;
00267             CCamView* pCCamView = NULL;
00268 PORTNOTE("other", "Disable HDC stuff")
00269 #ifndef EXCLUDE_FROM_XARALX
00270             CDC* pDevContext = NULL;
00271             HDC DeviceHdc = NULL;
00272 #endif          
00273             // find out about our device 
00274             if (m_pView)
00275                 pView = m_pView;
00276             else
00277                 m_pView = View::GetCurrent();
00278 
00279             if (m_pCCamView)
00280                 pCCamView = m_pCCamView;
00281             else
00282                 pCCamView = pView->GetConnectionToOilView();
00283 
00284 PORTNOTE("other", "Disable HDC stuff")
00285 #ifndef EXCLUDE_FROM_XARALX
00286             if (m_pDevContext)
00287                 pDevContext = m_pDevContext;
00288             else
00289                 pDevContext = ((ScreenCamView*)pCCamView)->GetRenderDC();
00290 
00291             if (m_DeviceHdc)
00292                 DeviceHdc = m_DeviceHdc;
00293             else
00294                 DeviceHdc = pDevContext->GetSafeHdc();
00295 #endif
00296 
00297             if (ScreenDepth < 24)
00298             {
00299                 INT32 OldHeight = -1;
00300                 OldHeight = lpPreConvertBrushBitmapInfo->bmiHeader.biHeight;
00301         
00302                 Width = UsedRect.right - UsedRect.left;
00303                 Height = UsedRect.bottom - UsedRect.top;
00304                 
00305                 if (!ClipBrushBitmaps(&UsedRect, &Height))
00306                     return;
00307                 SourceX = UsedRect.left;
00308                 DestX = UsedRect.left; 
00309                 DestY = UsedRect.top; 
00310 
00311                 // bit of a hack because DIBs are stored upside down
00312                 SourceY = ViewHeight - UsedRect.bottom;
00313         
00314                 if (Height > 0)
00315                 {
00316                     // copy from the big bitmap to the small brush bitmap
00317                     if (!DIBUtil::CopyBitmapSection(pBitmapInfo, pBits, 
00318                                 lpPreConvertBrushBitmapInfo, lpPreConvertBrushBits,
00319                                 SourceY, SourceX))
00320                     {
00321                         ERROR3("Failed to copy bitmap section");
00322                         return;
00323                     }
00324                     
00325                     // convert it to screen depth
00326                     ConvertBrushBitmap();
00327                 
00328                     if (ScreenDepth == 8)
00329                         SetPaletteEntries(lpPostConvertBrushBitmapInfo, RenderDC);
00330 
00331                     
00332                     // blit the post-converted bitmap
00333                     INT32 res = SetDIBitsToDevice( DeviceHdc, /*RenderDC->m_hDC,*/ //hDCScreen,
00334                                                 DestX , DestY,
00335                                                 Width,
00336                                                 Height,
00337                                                 0, 0,               // lower left of DIB (upside down)
00338                                                 0, Height,                      // actual bitmap height in entirety
00339                                                 lpPostConvertBrushBits,
00340                                                 lpPostConvertBrushBitmapInfo,
00341                                                 DIB_RGB_COLORS);
00342                                                                 
00343                     /*
00344                     TestConvertBitmap();
00345                     INT32 res = SetDIBitsToDevice( RenderDC->m_hDC,
00346                                             0, ViewHeight,
00347                                             ViewWidth,
00348                                             ViewHeight,
00349                                             0, 0,               // lower left of DIB (upside down)
00350                                             0, ViewHeight,                      // actual bitmap height in entirety
00351                                             lpTestBits,
00352                                             lpTestInfo,
00353                                             DIB_RGB_COLORS);
00354                     */
00355                     if (!res)
00356                     {
00357                         TRACEUSER( "Diccon", _T("SetDIB Failed.  DestY = %d, Height = %d\n"), DestY, Height);
00358                         //ERROR3("SetDIB failed in GRenderRegion::DrawToScreenNow");
00359                         DWORD error = GetLastError();
00360                         TRACEUSER( "Diccon", _T("Failed to set Bits in DrawToScreen Now, Error %d\n"), error);
00361                     }
00362                 }
00363                 else
00364                     TRACEUSER( "Diccon", _T("SetDIB Failed.  DestY = %d, Height = %d\n"), DestY, Height);
00365                 // restore the old height
00366                 //if (OldHeight != -1)
00367                 lpPreConvertBrushBitmapInfo->bmiHeader.biHeight = OldHeight;
00368                 lpPostConvertBrushBitmapInfo->bmiHeader.biHeight = OldHeight;
00369                 return;
00370             }
00371             else
00372             {
00373                 //we don't need to convert, just call the win32 function
00374                 SourceX += UsedRect.left;
00375                 DestX += UsedRect.left;
00376                 SourceY += UsedRect.top;
00377                 DestY += UsedRect.top;
00378 
00379                 Width = UsedRect.right - UsedRect.left;
00380                 Height = UsedRect.bottom - UsedRect.top;
00381         
00382                 DWORD *rgb = (DWORD *)lpBitmapInfo->bmiColors ;
00383                 *rgb++ = 0x00ff0000 ;
00384                 *rgb++ = 0x0000ff00 ;
00385                 *rgb++ = 0x000000ff ;
00386             
00387                 CanDoDeepDIBs = TRUE;
00388                 const UINT32 TotalHeight = (UINT32)lpBitmapInfo->bmiHeader.biHeight;        // height of complete DIB
00389 
00390             
00391                 const INT32 DIBSourceY = TotalHeight - (Height + SourceY);
00392         
00393                 INT32 res = SetDIBitsToDevice(   DeviceHdc, 
00394                                                 DestX, DestY,
00395                                                 
00396                                                 Width,
00397                                                 Height,
00398                                                 SourceX, DIBSourceY,                // lower left of DIB (upside down)
00399                                                 0, TotalHeight,                     // actual bitmap height in entirety
00400                                                 lpBits,
00401                                                 lpBitmapInfo,
00402                                                 DIB_RGB_COLORS);
00403                 
00404                 if (res == 0)
00405                 {
00406                         TRACEUSER( "Diccon", _T("SetDIB Failed.  DestY = %d, Height = %d\n"), DestY, Height);
00407                         //ERROR3("SetDIB failed in GRenderRegion::DrawToScreenNow");
00408                         DWORD error = GetLastError();
00409                         TRACEUSER( "Diccon", _T("Failed to set Bits in DrawToScreen Now, Error %d\n"), error);
00410                 }
00411 #if 0
00412                 static DWORD startCount = 0;
00413                 static INT32 fps = 0;
00414                 if (startCount != 0)
00415                 {
00416                     if ((GetTickCount () - startCount) <= 100)
00417                     {
00418                         fps++;
00419                     }
00420                     else
00421                     {
00422                         TRACEUSER( "ChrisS", _T("%i, "), fps);
00423                         //TextOut (DeviceHdc, 0, 0, data, camStrlen (data));
00424                         startCount = 0;
00425                         fps = 0;
00426                     }
00427                 }
00428                 else
00429                 {
00430                     startCount = GetTickCount ();
00431                 }
00432                 
00433                 /*RECT bounds;
00434                 bounds.left = DestX;
00435                 bounds.top = DestY;
00436                 bounds.right = DestX + Width;
00437                 bounds.bottom = DestY + Height;
00438 
00439                 FrameRect (DeviceHdc, &bounds, (HBRUSH) GetStockObject (BLACK_BRUSH));*/
00440 #endif
00441 
00442             //  PlotBitmap( RenderDC->m_hDC, DIB_RGB_COLORS, lpBitmapInfo, lpBits, DestX, DestY,
00443             //              Width, Height, hPalette, SourceX, SourceY );
00444                 
00445             }
00446         //  DeleteDC(hDCScreen);
00447         }
00448     }   
00449 
00450 }
00451 
00452 
00453 /********************************************************************************************
00454 
00455 >   BOOL GRenderBrush::InitialiseBrushBitmaps(DocRect BrushRect)
00456 
00457     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00458     Created:    29/10/99
00459     Inputs:     BrushRect - the size of the brush
00460     Outputs:    
00461     Returnd:    TRUE if successful, FALSE otherwise
00462     Purpose:    Public interface to the initialisation function, you only need to pass in the
00463                 size of the brush and the rest is taken care of for you
00464 
00465 ********************************************************************************************/
00466 
00467 BOOL GRenderBrush::InitialiseBrushBitmaps(DocRect BrushRect)
00468 {
00469     if (BrushRect.IsEmpty())
00470     {
00471         ERROR3("Rect is empty");
00472         return FALSE;
00473     }
00474 
00475     RECT WinRect  = OSRenderRegion::DocRectToWin(RenderMatrix, BrushRect, PixelsPerInch);
00476     INT32 Height =  WinRect.bottom - WinRect.top;
00477     INT32 Width = WinRect.right - WinRect.left;
00478     INT32 RenderDepth = 32;
00479     INT32 DeviceDepth = ScreenDepth;
00480 
00481     return InitialiseBrushBitmaps(Width, Height, RenderDepth, DeviceDepth);
00482 }
00483 
00484 
00485 
00486 /********************************************************************************************
00487 
00488 >   BOOL GRenderBrush::InitialiseBrushBitmaps(INT32 Width, INT32 Height, INT32 RenderDepth, 
00489                                                 INT32 DeviceDepth)
00490 
00491     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00492     Created:    29/10/99
00493     Inputs:     Width  = width of the brush object in pixels
00494                 Height - height of the brush object in pixels
00495                 RenderDepth - required BPP of the bitmap (no reason for this to be < 32)
00496                 DeviceDepth - BPP of the device we are drawing to
00497     Outputs:    
00498     Returns:    TRUE if successful, FALSE if we fail (most likely memory)
00499     Purpose:    allocates bitmaps of the correct size, depth etc. 
00500 
00501 ********************************************************************************************/
00502 
00503 
00504 BOOL GRenderBrush::InitialiseBrushBitmaps(INT32 Width, INT32 Height, INT32 RenderDepth, INT32 DeviceDepth)
00505 {
00506     // quick check
00507     if (Width <=0 || Height <= 0)
00508     {
00509         ERROR3("illegal height or width value");
00510         return FALSE;
00511     }
00512 
00513 //  TRACE( _T("Initialising brush bitmaps\n"));
00514 
00515     // if the bitmaps already exist then delete them
00516     if ((lpPreConvertBrushBits != NULL) && (lpPreConvertBrushBitmapInfo != NULL))
00517         FreeLPBits(lpPreConvertBrushBitmapInfo, lpPreConvertBrushBits);
00518 
00519     
00520     if ((lpPostConvertBrushBits != NULL) && (lpPostConvertBrushBitmapInfo != NULL))
00521         FreeLPBits(lpPostConvertBrushBitmapInfo, lpPostConvertBrushBits); 
00522 
00523     // get the pre-conversion bitmap
00524     lpPreConvertBrushBitmapInfo = GetLPBits(Width, Height, RenderDepth, &lpPreConvertBrushBits);
00525 
00526     if (lpPreConvertBrushBitmapInfo == NULL)
00527     {
00528         ERROR3("Unable to allocate pre-convert bitmap");
00529         return FALSE;
00530     }
00531 //  TRACEUSER( "Diccon", _T("Allocated bitmapinfo: 0x%x, bitmap: 0x%x\n"),lpPreConvertBrushBitmapInfo, lpPreConvertBrushBits);
00532     // get the post-conversion bitmap
00533     lpPostConvertBrushBitmapInfo = GetLPBits(Width, Height, DeviceDepth, &lpPostConvertBrushBits);
00534 
00535     if (lpPostConvertBrushBitmapInfo == NULL)
00536     {
00537         ERROR3("Unable to allocate post-convert bitmap");
00538         return FALSE;
00539     }
00540 //  TRACEUSER( "Diccon", _T("Allocated bitmapinfo: 0x%x, bitmap: 0x%x\n"),lpPostConvertBrushBitmapInfo, lpPostConvertBrushBits);
00541 
00542     // we're not using the brush bitmap any more
00543 /*  lpBrushBitmapInfo = GetLPBits(Width, Height, RenderDepth, &lpBrushBits);
00544     if (lpBrushBitmapInfo == NULL)
00545     {
00546         ERROR3("Unable to allocate post-convert bitmap");
00547         return FALSE;
00548     }
00549 */  
00550     // get the palette
00551     LPRGBQUAD pSourcePalette = &(lpBitmapInfo->bmiColors[0]);
00552     LPRGBQUAD pDestPalette   = &(lpPreConvertBrushBitmapInfo->bmiColors[0]);
00553 
00554     if (!DIBUtil::CopyPalette(pSourcePalette, pDestPalette, lpBitmapInfo->bmiHeader.biClrUsed))
00555     {
00556         ERROR3("Failed to copy palette");
00557         FreeLPBits(lpPreConvertBrushBitmapInfo, lpPreConvertBrushBits);
00558         FreeLPBits(lpPostConvertBrushBitmapInfo, lpPostConvertBrushBits);
00559         return FALSE;
00560     }
00561     
00562     return TRUE;
00563 }
00564 
00565 
00566 /********************************************************************************************
00567 
00568 >   BOOL GRenderBrush::ClipBrushBitmaps(RECT* pUsedRect, INT32* pHeight)
00569 
00570     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00571     Created:    29/10/99
00572     Inputs:     pUsedRect - the screen RECT that we are about to blit
00573 
00574     Outputs:    pHeight - pointer to an INT32 representing the new height of the bitmap, or rather
00575                 the maximum height that we will blit.
00576     Returns:    TRUE if successful, FALSE if input params are wrong
00577     Purpose:    When we come to blit at the edge of the view we will end up access violating 
00578                 if we simply proceed regardless.  This function checks to see how close we are
00579                 to the edge and 'pretends' that the bitmap is only big enough to go up up to the
00580                 edge and not beyond.
00581 ********************************************************************************************/
00582 
00583 BOOL GRenderBrush::ClipBrushBitmaps(RECT* pUsedRect, INT32* pHeight)
00584 {
00585     // first get the size of the big bitmap 
00586     INT32 ViewWidth = WRect.right - WRect.left;
00587     INT32 ViewHeight= WRect.bottom - WRect.top;
00588 
00589 
00590     // if we've gone off the screen then just return now
00591     if (pUsedRect->top >= ViewHeight || pUsedRect->bottom <= 0
00592         || pUsedRect->left >= ViewWidth || pUsedRect->right <= 0)
00593         return FALSE;
00594 
00595     INT32 TopAdjust = 0;
00596     INT32 BottomAdjust = 0;
00597     // otherwise clip the offscreen area
00598     if (pUsedRect->bottom > ViewHeight)
00599     {
00600         BottomAdjust = pUsedRect->bottom - ViewHeight;
00601         pUsedRect->bottom = ViewHeight;
00602     }
00603 
00604     if (pUsedRect->top <  0)
00605     {
00606         TopAdjust = pUsedRect->top;
00607         pUsedRect->top = 0;
00608     }
00609         
00610     if (pUsedRect->right > ViewWidth)
00611         pUsedRect->right = ViewWidth;
00612     if ( pUsedRect->left < 0)
00613         pUsedRect->left = 0;
00614 
00615     INT32 SourceY = ViewHeight - pUsedRect->bottom;
00616 //  TRACEUSER( "Diccon", _T("Top = %d, SourceY = %d\n"), pUsedRect->top, SourceY);
00617     // going off the top of the screen is a bit of a special case for some reason
00618     if (SourceY + *pHeight >= ViewHeight)
00619     {
00620         //TRACEUSER( "Diccon", _T("SourceY  = %d, Height = %d\n"), SourceY, Height);
00621         // Adjust the height of the bitmaps, we need to do the post-convert one as well
00622         // or else the convert will fail
00623         INT32 Adjuster = (ViewHeight - (SourceY+*pHeight));
00624         TRACEUSER( "Diccon", _T("Adjust = %d\n"), Adjuster);
00625         *pHeight += Adjuster;
00626         lpPreConvertBrushBitmapInfo->bmiHeader.biHeight = *pHeight;
00627         lpPostConvertBrushBitmapInfo->bmiHeader.biHeight = *pHeight;
00628     //  TRACEUSER( "Diccon", _T("Height = %d\n"), *pHeight);
00629         //TRACEUSER( "Diccon", _T("SourceY = %d\n"), SourceY);      
00630     }
00631     else if (TopAdjust != 0)
00632     {
00633         *pHeight -= TopAdjust;
00634         lpPreConvertBrushBitmapInfo->bmiHeader.biHeight = *pHeight;
00635         lpPostConvertBrushBitmapInfo->bmiHeader.biHeight = *pHeight;
00636     }
00637     else if (BottomAdjust != 0)
00638     {
00639         *pHeight -= BottomAdjust;
00640         lpPreConvertBrushBitmapInfo->bmiHeader.biHeight = *pHeight;
00641         lpPostConvertBrushBitmapInfo->bmiHeader.biHeight = *pHeight;
00642     }
00643     return TRUE;
00644 }
00645 
00646 
00647 
00648 /********************************************************************************************
00649 
00650 >   BOOL GRenderBrush::PlotBrushIntoBigBitmap(DocRect BrushRect)
00651 
00652     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00653     Created:    29/10/99
00654     Inputs:     BrushRect - the location in the view where we wish to plot the brush
00655     Outputs:    
00656     Returnd:    TRUE if successful, FALSE otherwise
00657     Purpose:    Plots the brush bitmap into the view bitmap, just like rendering really 
00658                 but quicker.
00659 
00660 ********************************************************************************************/
00661 
00662 
00663 BOOL GRenderBrush::PlotBrushIntoBigBitmap(DocRect BrushRect)
00664 {
00665     if (BrushRect.IsEmpty())
00666     {
00667         ERROR3("Brush rect is empty");
00668         return FALSE;
00669     }
00670 
00671     if (lpBitmapInfo == NULL || lpBits == NULL 
00672         || lpBrushBitmapInfo == NULL || lpBrushBits == NULL)
00673     {
00674         ERROR3("Bitmaps not initialised");
00675         return FALSE;
00676     }
00677 
00678     INT32 PixelSize = CalcPixelWidth();
00679 
00680     // Get the Bitmap width and height in Millipoints
00681     INT32 Width  = lpBrushBitmapInfo->bmiHeader.biWidth  * PixelSize;
00682     INT32 Height = lpBrushBitmapInfo->bmiHeader.biHeight * PixelSize;
00683 
00684     POINT Plot[3]; 
00685     Plot[0].x = BrushRect.lox;           Plot[0].y = BrushRect.loy;
00686     Plot[1].x = BrushRect.lox + Width;   Plot[1].y = BrushRect.loy;
00687     Plot[2].x = BrushRect.lox;           Plot[2].y = BrushRect.loy + Height;
00688 
00689     INT32 Style = 1;
00690     LPRGBQUAD pRGB = &(lpBitmapInfo->bmiColors[0]);
00691     if (!GetDrawContext()->PlotBitmap(&(lpBrushBitmapInfo->bmiHeader), lpBrushBits, 
00692                                     Style, Plot, pRGB, NULL, NULL, NULL,
00693                                     NoTransTable))
00694     {
00695         ERROR3("Failed to plot bitmap");
00696         return FALSE;
00697     }
00698     
00699     return TRUE;
00700 }
00701 
00702 
00703 
00704 /********************************************************************************************
00705 
00706 >   BOOL GRenderBrush::ConvertBrushBitmap()
00707 
00708     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00709     Created:    29/10/99
00710     Inputs:     
00711     Outputs:    
00712     Returns:    TRUE if successful, FALSE otherwise
00713     Purpose:    Takes the contents of lppreconvertbrushbits which will be 32BPP, and calls GDraw to
00714                 convert the contents and put it into lppostconvertbrushbits which has the same BPP 
00715                 as the screen
00716 ********************************************************************************************/
00717 
00718 
00719 BOOL GRenderBrush::ConvertBrushBitmap()
00720 {
00721     if (lpPreConvertBrushBitmapInfo == NULL || lpPreConvertBrushBits == NULL 
00722         || lpPostConvertBrushBitmapInfo == NULL || lpPostConvertBrushBits == NULL)
00723     {
00724         ERROR3("Bitmaps not initialised");
00725         return FALSE;
00726     }
00727 
00728     GDrawContext *GDC = GetDrawContext();
00729     
00730     INT32 ColourFlag = DIB_RGB_COLORS;
00731 
00732     INT32 result = GDC->ConvertBitmap(&(lpPreConvertBrushBitmapInfo->bmiHeader), lpPreConvertBrushBits,
00733                             &(lpPostConvertBrushBitmapInfo->bmiHeader), lpPostConvertBrushBits, DitherStyle8Bit);
00734 
00735     // 16 bit bmps don't like having their palette entries set.
00736     if (ScreenDepth == 8)
00737         ColourFlag = SetPaletteEntries(lpPostConvertBrushBitmapInfo, RenderDC);
00738     else
00739         ColourFlag = DIB_RGB_COLORS;
00740     if (result == -1)
00741     {
00742         ERROR3("Failed to convert bitmap");
00743         return FALSE;
00744     }
00745     return TRUE;
00746 
00747 }
00748 
00749 BOOL GRenderBrush::TestConvertBitmap()
00750 {
00751     if (lpTestInfo == NULL || lpTestBits == NULL || lpBitmapInfo == NULL || lpBits == NULL)
00752     {
00753         ERROR3("bitmaps not initialised");
00754         return FALSE;
00755     }
00756 
00757 
00758     GDrawContext *GDC = GetDrawContext();
00759     
00760     INT32 ColourFlag = DIB_RGB_COLORS;
00761 
00762     INT32 result = GDC->ConvertBitmap(&(lpBitmapInfo->bmiHeader), lpBits, &(lpTestInfo->bmiHeader), 
00763                                         lpTestBits, DitherStyle8Bit);
00764 
00765 
00766     if (result == -1)
00767     {
00768         ERROR3("Failed to convert bitmap");
00769         return FALSE;
00770     }
00771     return TRUE;
00772 
00773 }
00774 
00775 
00776 
00777 /********************************************************************************************
00778 
00779 >   void GRenderBrush::SetupMainBitmap()
00780 
00781     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00782     Created:    29/10/99
00783     Inputs:     
00784     Outputs:    
00785     Purpose:    Public interface which sets up our main bitmap for GDraw to use.  Note that
00786                 the compression flag must be set to false or else things go wrong.
00787 
00788 ********************************************************************************************/
00789 
00790 
00791 void GRenderBrush::SetupMainBitmap()
00792 {
00793     if (lpBitmapInfo == NULL || lpBits == NULL)
00794     {
00795         ERROR3("Bitmaps are unititialised in GRenderBrush::SetupMainBitmap");
00796         return;
00797     }
00798     // we need to make sure the compression flag is off
00799     lpBitmapInfo->bmiHeader.biCompression = 0;
00800     SetupBitmap(lpBitmapInfo, lpBits);
00801 }
00802 
00803 
00804 
00805 /********************************************************************************************
00806 
00807 >   void GRenderBrush::SetupBitmap(LPBITMAPINFO pBitmapInfo, LPBYTE pBits)
00808 
00809     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00810     Created:    29/10/99
00811     Inputs:     pBitmapInfo - info of the bitmap to be set up
00812                 pBits       - pointer to the bits
00813     Outputs:    
00814     Purpose:    Similar to GRenderRegion;;StartRender, initialises the bitmap for GDraw
00815                 to render into it.  
00816 ********************************************************************************************/
00817 
00818 
00819 void GRenderBrush::SetupBitmap(LPBITMAPINFO pBitmapInfo, LPBYTE pBits)
00820 {
00821     if (pBitmapInfo == NULL || pBits == NULL)
00822     {
00823         ERROR3("invalid parameters passed into GRenderBrush::SetupBitmap");
00824         return;
00825     }
00826 
00827     // Determine the correct hinting value for the current output mode, and call gavin to
00828     // set up his offscreen bitmap.
00829 /*  DWORD GavinHint = DIBUtil::GetGavinBlitFormat(ScreenDepth, BitmapDepth, ScreenHinting);
00830     //TRACEUSER( "Diccon", _T("About to setup bitmap\n"));
00831     GetDrawContext()->SetupBitmapNoInitialise( pBitmapInfo->bmiHeader.biWidth, pBitmapInfo->bmiHeader.biHeight,
00832                         pBitmapInfo->bmiHeader.biBitCount, pBits, GavinHint, m_DoCompression );
00833                         */
00834     GetDrawContext()->SetBitmap( &pBitmapInfo->bmiHeader, pBits );
00835 //  TRACEUSER( "Diccon", _T("Bitmap Setup OK\n"));
00836     if (RenderDC != NULL)
00837     {
00838         if (ScreenDepth == 8)
00839         {
00840             // use frame windows palette if desired
00841             if (PaletteManager::UsePalette())
00842                 hPalette = *(PaletteManager::GetPalette());
00843         }
00844 
00845         if (hPalette != NULL)
00846             hPrevPalette = PaletteManager::StartPaintPalette(RenderDC->m_hDC);
00847 
00848         if (BitmapDepth == 8)
00849         {
00850             // If we are not error diffusing then set the dither style
00851             if ((DitherStyle8Bit != 0) && (DitherStyle8Bit != 3))
00852                 GetDrawContext()->SetDitherStyle((DitherStyle) DitherStyle8Bit);        // Stupid prototype
00853         }
00854 
00855         if (ScreenDepth == 8)
00856         {
00857             // Whether we set a palette or not, we need this call on all 8-bit screens
00858             GRenderRegion::GColInit(RenderDC->m_hDC);
00859         }
00860     }
00861 
00862     // Work out our matrix and set it 
00863     ResetMatrix();
00864 
00865     
00866     Spread* pSpread = Document::GetSelectedSpread();
00867     if (pSpread != NULL)
00868     {
00869         // get the bounding rect of the view and set it as the clip rect
00870         DocView* pDocView = DocView::GetCurrent();
00871         DocRect ViewRect = pDocView->GetDocViewRect(pSpread);
00872         pSpread->DocCoordToSpreadCoord(&ViewRect);
00873 
00874         RECT WinRect  = OSRenderRegion::DocRectToWin(RenderMatrix, ViewRect, PixelsPerInch);    
00875         GetDrawContext()->DeviceClipRectangle(&WinRect);
00876     }
00877     
00878     // setup code borrowed from StartRender
00879 
00880     // set up anti-aliasing & flatness, using the SetQualityLevel function
00881     SetQualityLevel();
00882     GetDrawContext()->SetHintingFlag(TRUE);                                     // Always hint lines!!!
00883 
00884     GetDrawContext()->SetDashAdjustmentFlag(FALSE);
00885 
00886     // work out the brush alignment
00887     // algorithm based on code from OSRenderRegion::InitAttributes
00888     POINT DocOrigin, OSOrigin;
00889     DocOrigin.x = 0;
00890     DocOrigin.y = 0;
00891         
00892     // Then we transform it into OSCoords
00893     GetDrawContext()->TransformPath( &DocOrigin, &OSOrigin, 1, &CurrentGMatrix );
00894 
00895     // Once we've shifted then right by FX, they're in pixel co-ords, which is what
00896     // SetHalftoneOrigin is expecting them to be in
00897     const INT32 BrushX = OSOrigin.x >> FX;
00898     const INT32 BrushY = -(OSOrigin.y >> FX);                   // has to be negated to work
00899 
00900     GetDrawContext()->SetHalftoneOrigin( BrushX, BrushY );
00901     
00902 }
00903 
00904 
00905 BOOL GRenderBrush::MoveWindowToFront()
00906 {
00907     
00908     // move our main frame to the front
00909     CMainFrame* pMainFrame = GetMainFrame();
00910     ERROR2IF(pMainFrame == NULL, FALSE, "Wheres our mainframe gone!!??");
00911     HWND OurHWnd = pMainFrame->GetSafeHwnd();
00912     SetWindowPos(OurHWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
00913 
00914     CWnd* pFirst = pMainFrame->GetWindow(GW_HWNDFIRST);
00915     HWND HWFirst = pFirst->GetSafeHwnd();
00916 
00917     // there may be a window on top of us, check to see.  
00918     // Basically we check downwards from the Desktop windo checking to see if there
00919     // is an on top window, if so we minimize it, unless it is the taskbar
00920     CWnd* pNextWnd = pFirst;
00921     UINT32 Counter = 0;
00922     HWND hTaskBar = FindWindow("Shell_TrayWnd", NULL);
00923             
00924     CWnd* pLast = pNextWnd;
00925     while (pNextWnd != NULL)
00926     {
00927         pLast = NULL;
00928         if (pNextWnd->GetExStyle() & WS_EX_TOPMOST)
00929         {
00930             if (pNextWnd->IsWindowVisible() && (pNextWnd->GetSafeHwnd() != hTaskBar)) 
00931             {
00932                 Counter++;
00933                 pLast = pNextWnd;
00934             }
00935         }
00936         
00937         pNextWnd = pNextWnd->GetNextWindow();
00938     //  if (pLast != NULL)
00939     //      pLast->ShowWindow(SW_MINIMIZE);
00940     }
00941     
00942     pMainFrame->SetActiveWindow();
00943     pMainFrame->UpdateWindow();
00944 //  TRACEUSER( "Diccon", _T("Found %d on top windows\n"), Counter);
00945     if (Counter == 0)
00946         return TRUE;
00947 
00948     return FALSE;
00949 }
00950 
00951 
00952 BOOL GRenderBrush::ResetMatrix()
00953 {
00954     View*   pView = View::GetCurrent();
00955     Spread* pSpread = Document::GetSelectedSpread();
00956     if (pSpread != NULL)
00957     {
00958         Matrix  RenderMat = pView->ConstructRenderingMatrix(pSpread);   
00959         GMATRIX GMat;
00960         GMat = MakeGavinMatrix(RenderMat, CurrentClipRect, PixelsPerInch, FALSE);
00961 
00962         SetGavinMatrix(&GMat);
00963     }
00964 
00965     return TRUE;
00966 }
00967 
00968 /********************************************************************************************
00969 
00970 >   BOOL GRenderBrush::CaptureView(Spread* pSpread)
00971 
00972     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
00973     Created:    29/10/99
00974     Inputs:     pSpread - contains the view we wish to grab
00975     Outputs:    
00976     Purpose:    Captures the screen (or rather the part of the screen that holds the View) as a bitmap 
00977 
00978 ********************************************************************************************/
00979 
00980 BOOL GRenderBrush::CaptureView(Spread* pSpread)
00981 {
00982     ERROR3IF(!MasterCaptureIsCurrent() && GetCaptureDepth()>0, "Can't 'CaptureView' while Captures are running");
00983 
00984 //  TRACEUSER( "Diccon", _T("Entering CaptureView\n"));
00985     // put up an hour glass
00986     String_32 ProgString = "Preparing for brush stroke, please wait..";
00987     Progress Prog(&ProgString, -1, FALSE);
00988     
00989     // make sure we're at the front ( we may still have a window on top though)
00990     BOOL DoCapture = MoveWindowToFront();
00991 
00992     // If we have a bitmap then ditch it
00993     if (lpBitmapInfo!=NULL && lpBits != NULL)
00994     {
00995         FreeLPBits(lpBitmapInfo, lpBits);
00996         lpBitmapInfo = NULL;
00997         lpBits       = NULL;
00998     }
00999 
01000     // get the current screen depth
01001     HDC hDCScreen = CreateDC("DISPLAY", NULL, NULL, NULL);
01002     ScreenDepth = GetDeviceCaps(hDCScreen, BITSPIXEL);
01003     
01004     // if we have an 8-bit screen or there is a window on top of us then
01005     // don't capture the screen, render the view normally.  A bit slower, if the document is complex
01006     if (ScreenDepth == 8 || !DoCapture) 
01007     {
01008         DeleteDC(hDCScreen);
01009         CaptureViewByRendering();
01010     //  TRACEUSER( "Diccon", _T("Rendered View\n"));
01011         return TRUE;
01012     }
01013 
01014     // Get a new one to replace it
01015     lpBitmapInfo = GetLPBits(WRect.right-WRect.left, WRect.bottom-WRect.top,
01016                                 32, &lpBits);
01017 
01018     // See if we got it
01019     if (lpBitmapInfo==NULL)
01020         return FALSE;
01021 
01022 
01023     //  make a compatible DC to put the bitmap in
01024     HDC hDCCompatible = CreateCompatibleDC(hDCScreen);
01025 
01026 
01027     // get the window so we can do client to screen to find out how big
01028     // the view is in pixels
01029     
01030     View* pView = View::GetCurrent();
01031     if (pView == NULL)
01032     {
01033         ERROR3("No view in GRenderBrush::CaptureView");
01034         DeleteDC(hDCScreen);
01035         DeleteDC(hDCCompatible);
01036         return FALSE;
01037     }
01038     CCamView *pRenderWindow = pView->GetConnectionToOilView();
01039     if (pRenderWindow == NULL)
01040     {
01041         ERROR3("No window in GRenderBrush::CaptureView");
01042         DeleteDC(hDCScreen);
01043         DeleteDC(hDCCompatible);
01044         return FALSE;
01045     }
01046 
01047     RECT Rect = CalculateWinRect(RenderMatrix, CurrentClipRect, PixelsPerInch );
01048     pRenderWindow->ClientToScreen( &Rect );
01049 
01050     // get some locals to store the dimensions - remember that DIBs are upside down
01051     INT32 ViewHeight = Rect.bottom - Rect.top ; 
01052     INT32 ViewWidth =  Rect.right - Rect.left;
01053     INT32 ViewTop = Rect.top;
01054     INT32 ViewLeft = Rect.left;
01055 
01056     // if the rulers are on then we must shift in a little bit
01057     DocView* pDocView = DocView::GetCurrent();
01058     
01059     if (pDocView->AreRulersVisible())
01060     {
01061         INT32 RulerSize = OILRuler::GetRenderWidth();
01062         ViewTop += RulerSize+1;
01063         ViewLeft += RulerSize+1;
01064     }
01065 
01066   // allocate the bitmap
01067     HBITMAP hBMScreen = CreateCompatibleBitmap(hDCScreen, ViewWidth, ViewHeight);
01068 
01069     ERROR2IF(hBMScreen == NULL, FALSE, "unable to allocate bitmap for the view");
01070 
01071     // select the bitmap into the DC
01072     if (!SelectObject(hDCCompatible, hBMScreen))
01073     {
01074         ERROR3("Error selecting bitmap into DC");
01075         DeleteDC(hDCScreen);
01076         DeleteDC(hDCCompatible);
01077         DeleteObject(hBMScreen);
01078         return FALSE;
01079     }
01080     
01081     hPrevPalette = PaletteManager::StartPaintPalette(hDCScreen);    
01082     // blit it
01083     /*if (!BitBlt(hDCCompatible, 
01084                 0, 0,
01085                 ViewWidth, ViewHeight,
01086                 hDCScreen,
01087                 ViewLeft , ViewTop,
01088                 SRCCOPY))*/
01089     if (!Blit(hDCCompatible, hDCScreen, ViewHeight, ViewWidth, ViewLeft, ViewTop))
01090     {
01091         ERROR3("Error selecting bitmap into DC");
01092         DeleteDC(hDCScreen);
01093         DeleteDC(hDCCompatible);
01094         DeleteObject(hBMScreen);
01095         return FALSE;
01096     }
01097 
01098 
01099     
01100     // Now we have to convert it to 32bit and use it as our member bitmap
01101     
01102     // first get a pointer to the bitmap bits
01103     INT32   BitmapSize = ViewHeight * ViewWidth * ScreenDepth;
01104     
01105     LPBYTE lpScreenBits = NULL; //(LPBYTE)CCMalloc(BitmapSize);//(LPBYTE)malloc(BitmapSize);
01106     
01107     LPBITMAPINFO lpScreenInfo = GetLPBits(Rect.right-Rect.left, Rect.bottom-Rect.top,
01108                                 ScreenDepth, &lpScreenBits);
01109     if (lpScreenBits == NULL)
01110     {
01111         ERROR3("error getting screen bits");
01112         DeleteDC(hDCScreen);
01113         DeleteDC(hDCCompatible);
01114         DeleteObject(hBMScreen);
01115         return FALSE;
01116     }
01117     
01118     // now setup a bitmapinfo
01119     //LPBITMAPINFO lpScreenInfo = (LPBITMAPINFO)CCMalloc(sizeof(BITMAPINFO));
01120     if (lpScreenInfo == NULL)
01121     {
01122         ERROR3("error getting bitmapinfo");
01123         CCFree((LPVOID)lpScreenBits);
01124         DeleteDC(hDCScreen);
01125         DeleteDC(hDCCompatible);
01126         DeleteObject(hBMScreen);
01127         return FALSE;
01128     }
01129     
01130     INT32 Colours = 0;
01131     
01132     switch (ScreenDepth)
01133     {
01134         case 1:
01135             Colours = 2;
01136             break;
01137         case 4:
01138             Colours = 16;
01139             break;
01140         case 8:
01141             Colours = 256;
01142             break;
01143         case 16:  // for 16 bit and upwards we can pass in zero
01144             Colours = 0;
01145             break;
01146         case 24:
01147             Colours = 0;
01148             break;
01149         case 32:
01150             Colours = 0;
01151             break;
01152         default:
01153             ERROR3("Illegal screen depth");
01154             break;
01155     }
01156     
01157 
01158     lpScreenInfo->bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
01159     lpScreenInfo->bmiHeader.biWidth         = ViewWidth;
01160     lpScreenInfo->bmiHeader.biHeight        = ViewHeight;
01161     lpScreenInfo->bmiHeader.biPlanes        = 1;
01162     lpScreenInfo->bmiHeader.biBitCount      = ScreenDepth;
01163     lpScreenInfo->bmiHeader.biCompression   = BI_RGB;
01164     lpScreenInfo->bmiHeader.biXPelsPerMeter = 3780;             // Default to 96 dpi
01165     lpScreenInfo->bmiHeader.biYPelsPerMeter = 3780;
01166     lpScreenInfo->bmiHeader.biClrUsed       = Colours;
01167     lpScreenInfo->bmiHeader.biClrImportant  = 0;
01168     lpScreenInfo->bmiHeader.biSizeImage     = BitmapSize;
01169     
01170     
01171     
01172 
01173     // now get the DIBits
01174      INT32 num =  (GetDIBits(hDCCompatible, hBMScreen,
01175                     0, ViewHeight, 
01176                     lpScreenBits, lpScreenInfo,
01177                     DIB_RGB_COLORS)); 
01178     //if (!GetBits(hDCCompatible, hBMScreen, ViewHeight, lpScreenBits, lpScreenInfo))
01179     if (num ==0 )
01180     {
01181         ERROR3("Failed to get bitmap bits");
01182         DeleteDC(hDCScreen);
01183         DeleteDC(hDCCompatible);
01184         DeleteObject(hBMScreen);
01185         delete lpScreenInfo;
01186         CCFree((LPVOID)lpScreenBits);
01187         return FALSE;
01188     }
01189 
01190     // quick sanity check
01191     if (lpBitmapInfo == NULL)
01192         ERROR3("What the *?!& is going on with my bitmaps!?");
01193 
01194     GDrawContext *GDC = GetDrawContext();
01195     // convert it to 32bit, using the already allocated bitmap and bitmapinfo
01196     INT32 result = 0;
01197     if (ScreenDepth == 8)
01198     {
01199         SetPaletteEntries(lpScreenInfo);
01200         
01201         /*result = DIBUtil::Convert8to32(lpScreenInfo, lpScreenBits, lpScreenInfo->bmiColors,
01202                               lpBitmapInfo, lpBits);
01203         
01204         INT32 result = GDC->ConvertBitmap(&(lpBitmapInfo->bmiHeader), lpBits,
01205                                 &(lpScreenInfo->bmiHeader), lpScreenBits, DitherStyle8Bit);
01206         
01207          */
01208         /*
01209         GDC->SetChangedBBox(&Rect);
01210         BitmapDepth = 8;
01211         DisplayBits();
01212         BitmapDepth = 32;
01213         */
01214     /*  INT32 res = SetDIBitsToDevice( hDCScreen,
01215                                     0, Rect.top,
01216                                     ViewWidth,
01217                                     ViewHeight,
01218                                     0, 0,               // lower left of DIB (upside down)
01219                                     0, ViewHeight,                      // actual bitmap height in entirety
01220                                     lpScreenBits,
01221                                     lpScreenInfo,
01222                                     DIB_RGB_COLORS);
01223     */  
01224         result = DIBUtil::Convert8to32(lpScreenInfo, lpScreenBits, lpScreenInfo->bmiColors,
01225                               lpBitmapInfo, lpBits);
01226     
01227 
01228         
01229     
01230     }
01231     if (ScreenDepth == 16)
01232     {
01233         RGBQUAD* pPalette = lpScreenInfo->bmiColors;
01234         result = Convert16to32(lpScreenInfo, lpScreenBits, pPalette,
01235                               lpBitmapInfo, lpBits);
01236         SetupMainBitmap();
01237     
01238         /* Test code for figuring out the bitmap shearing problem
01239         GDrawContext *GDC = GetDrawContext();
01240         
01241         INT32 ColourFlag = DIB_RGB_COLORS;
01242 
01243         INT32 result = GDC->ConvertBitmap(&(lpBitmapInfo->bmiHeader), lpBits,
01244                                 &(lpScreenInfo->bmiHeader), lpScreenBits, DitherStyle8Bit);
01245         
01246         PatBlt( hDCScreen, 0, Rect.top, ViewWidth, ViewHeight, BLACKNESS );
01247         // blit the post-converted bitmap
01248         INT32 res = SetDIBitsToDevice( hDCScreen,
01249                                     0, Rect.top,
01250                                     ViewWidth,
01251                                     ViewHeight,
01252                                     0, 0,               // lower left of DIB (upside down)
01253                                     0, ViewHeight,                      // actual bitmap height in entirety
01254                                     lpScreenBits,
01255                                     lpScreenInfo,
01256                                     DIB_RGB_COLORS);
01257         TRACEUSER( "Diccon", _T("Blitted post-converted bitmap\n")); */
01258     }
01259     if (ScreenDepth == 24)
01260     {
01261         result = GDC->ConvertBitmap(&(lpScreenInfo->bmiHeader), lpScreenBits,
01262                             &(lpBitmapInfo->bmiHeader), lpBits, DitherStyle8Bit);
01263     }
01264     if (ScreenDepth == 32)
01265     {
01266         // blit the post-converted bitmap
01267     /*  INT32 res = SetDIBitsToDevice( hDCScreen,
01268                                     0, Rect.top,
01269                                     ViewWidth,
01270                                     ViewHeight,
01271                                     0, 0,               // lower left of DIB (upside down)
01272                                     0, ViewHeight,                      // actual bitmap height in entirety
01273                                     lpScreenBits,
01274                                     lpScreenInfo,
01275                                     DIB_RGB_COLORS);
01276         */
01277         FreeLPBits(lpBitmapInfo, lpBits);
01278         lpBitmapInfo = lpScreenInfo;
01279         lpBits       = lpScreenBits;
01280         lpScreenInfo = NULL;
01281         lpScreenBits = NULL;
01282 
01283     }
01284 
01285     // Update the master capture
01286     Capture* pMasterCapture = GetMasterCapture();
01287     pMasterCapture->lpBitmapInfo = lpBitmapInfo;
01288     pMasterCapture->lpBits = lpBits;
01289 
01290     // free up all that lovely memory and stuff
01291     DeleteDC(hDCScreen);
01292     DeleteDC(hDCCompatible);
01293     DeleteObject(hBMScreen);
01294     if (lpScreenBits != NULL)
01295         FreeLPBits(lpScreenInfo, lpScreenBits);
01296     lpScreenInfo    = NULL;
01297     lpScreenBits    = NULL;
01298     if (hPrevPalette)
01299             PaletteManager::StopPaintPalette(hDCScreen, hPrevPalette);
01300     if (result == -1)
01301     {
01302         ERROR3("Failed to convert bitmap");
01303         return FALSE;
01304     }
01305     else    
01306         return TRUE;
01307 }
01308 
01309 // these fns.just perform their win32 namesakes, moved out of the main fn. so 
01310 // that they could be profiled
01311 BOOL GRenderBrush::GetBits(HDC hMemDC, HBITMAP hBitmap, INT32 Height, LPBYTE lpbits, LPBITMAPINFO lpInfo)
01312 {
01313 // now get the DIBits
01314     INT32 num =  (GetDIBits(hMemDC, hBitmap,
01315                     0, Height, 
01316                     lpBits, lpInfo,
01317                     DIB_RGB_COLORS));   
01318     return (num != 0);
01319 }
01320 
01321 BOOL GRenderBrush::Blit(HDC DestDC, HDC SourceDC, INT32 Height, INT32 Width, INT32 Left, INT32 Top)
01322 {
01323     if (BitBlt(DestDC, 
01324                 0, 0,
01325                 Width, Height,
01326                 SourceDC,
01327                 Left , Top,
01328                 SRCCOPY))
01329         return TRUE;
01330     else
01331         return FALSE;
01332     
01333 }
01334 
01335 
01336 
01337 /********************************************************************************************
01338 
01339 >   BOOL GRenderBrush::CaptureViewByRendering()
01340 
01341     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01342     Created:    2/6/94
01343     Inputs:     -
01344     Outputs:    -
01345     Returns:    TRUE if successful, FALSE otherwise
01346     Purpose:    Renders the view into this render region
01347     
01348     Notes:  Due to the ongoing palette problems capturing the view from the screen in 8-bit mode
01349             this will serve to capture the background for the time being. Obviously it is not ideal
01350             as rendering the view can be very slow.
01351 
01352 
01353 ********************************************************************************************/
01354 
01355 BOOL GRenderBrush::CaptureViewByRendering()
01356 {
01357     // first things first, we need the view, docview and spread
01358     DocView* pDocView = DocView::GetCurrent();
01359     View* pView = View::GetCurrent();
01360     Spread* pSpread = Document::GetSelectedSpread();
01361     Document* pDoc = Document::GetCurrent();
01362     if (pSpread == NULL || pDocView == NULL || pView == NULL || pDoc == NULL)
01363     {
01364         ERROR3("Invalid entry conditions to GRenderBrush::CaptureViewByRendering");
01365         return FALSE;
01366     }
01367 
01368     ERROR3IF(!MasterCaptureIsCurrent() && GetCaptureDepth()>0, "Can't 'CaptureView' while Captures are running");
01369 
01370     // Convert our window rect to doccoords because the concurrent render needs it  
01371 
01372     WinRect WinRect(WRect.left, WRect.top, WRect.right, WRect.bottom);
01373     OilRect ORect = WinRect.ToOil(pView);
01374     
01375     DocRect ViewRect = ORect.ToDoc(pSpread, pView);
01376     
01377     pSpread->DocCoordToSpreadCoord(&ViewRect);
01378     
01379     
01380     // Setup a concurrent renderer.
01381     ConcurrentRenderer* pRendWrap = NULL;
01382 
01383     // The last argument to this call is a little odd, basically for some reason under a
01384     // 16bpp display the background paper is rendered incorrectly if our bitmap
01385     // gets initialised in GRenderRegion::InitBmpBits.  Therefore we ask for it to 
01386     // not be transparent, (although it is actually transparent, being 32 bit).
01387     pRendWrap = GRenderRegionWrapper::GetConcurrentRenderer(this,
01388                                                             1.0,
01389                                                             ViewRect,
01390                                                             32,
01391                                                             FALSE);
01392     if (pRendWrap == NULL)
01393         return FALSE;
01394 
01395     GRenderRegion* pOffscreenRR = pRendWrap->GetRenderRegion();
01396     
01397     // we're saving the context for paranoia's sake, and 'cos it doesn't hurt.
01398     pOffscreenRR->SaveContext();
01399 
01400     // ConcurrentRenderer created, now we need to render the entire view into it
01401     pDocView->RenderEntireView(pOffscreenRR, pSpread);
01402 
01403     // restore the context.
01404     pOffscreenRR->RestoreContext();
01405 
01406 
01407     // extract the bitmap from the offscreen RR before the RR is closed down, 
01408     // this is somewhat labourious
01409     KernelBitmap *  pBitmap = pRendWrap->GetKernelBitmap();
01410 
01411     if (pBitmap == NULL)
01412     {
01413         ERROR3("Bitmap is NULL in GRenderBrush::CaptureViewByRendering");
01414         delete pOffscreenRR;
01415         return FALSE;
01416     }
01417     WinBitmap* pWinBitmap = (WinBitmap*)pBitmap->GetActualBitmap();
01418     if (pWinBitmap == NULL)
01419     {
01420         ERROR3("Bitmap is NULL in GRenderBrush::CaptureViewByRendering");
01421         delete pOffscreenRR;
01422         delete pBitmap;
01423         return FALSE;
01424     }
01425     LPBYTE pBits = NULL; //(LPBYTE)pWinBitmap->GetBitmapBits();
01426     LPBITMAPINFO pBitmapInfo = NULL; //pWinBitmap->GetBitmapInfo();
01427     pWinBitmap->ExtractBitsAndInfo(&pBits, &pBitmapInfo);
01428 
01429     if (pBits == NULL || pBitmapInfo == NULL)
01430     {
01431         ERROR3("Bitmap is NULL in GRenderBrush::CaptureViewByRendering");
01432         delete pOffscreenRR;
01433         delete pBitmap;
01434         delete pWinBitmap;
01435         return FALSE;
01436     }   
01437 
01438     // now delete our existing bitmap and assign the new on
01439     if (lpBitmapInfo!=NULL && lpBits != NULL)
01440     {
01441         FreeLPBits(lpBitmapInfo, lpBits);
01442         lpBitmapInfo = NULL;
01443         lpBits       = NULL;
01444     }
01445     lpBits = pBits;
01446     lpBitmapInfo = pBitmapInfo;
01447 
01448     // Update the master capture
01449     Capture* pMasterCapture = GetMasterCapture();
01450     pMasterCapture->lpBitmapInfo = lpBitmapInfo;
01451     pMasterCapture->lpBits = lpBits;
01452 
01453     // delete our bitmap container
01454     delete pBitmap;
01455 
01456     // restore gdraw 
01457     pRendWrap->RestorePreviousRendererState();
01458     
01459 
01460     return TRUE;
01461 }
01462 
01463 /********************************************************************************************
01464 
01465 >   void GRenderBrush::FreeLPBits( LPBITMAPINFO lpBMI, LPBYTE lpB )
01466 
01467     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
01468     Created:    2/6/94
01469     Inputs:     Bitmap characteristics.
01470     Outputs:    -
01471     Returns:    -
01472     Purpose:    Frees up a bitmap allocated with GetLPBits.
01473     Errors:     -
01474     SeeAlso:    GRenderDIB::FreeLPBits
01475 
01476 ********************************************************************************************/
01477 
01478 void GRenderBrush::FreeLPBits( LPBITMAPINFO lpBMI, LPBYTE lpB )
01479 {
01480     // If we are banded, then free the memory from the limited heap
01481     FreeDIB(lpBMI, lpB, NULL, FALSE);
01482 }
01483 
01484 
01485 /********************************************************************************************
01486 
01487 >   static BOOL DIBUtil::Convert8to32(LPBITMAPINFO pSourceInfo, LPBYTE pSourceBits, LPQUAD pPalette
01488                                       LPBITMAPINFO *pDestInfo, LPBYTE *pDestBits)
01489 
01490     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01491     Created:    14/2/2000
01492     Inputs:     pSourceInfo     - A information header for the bitmap to be copied
01493                 pSourceBits     - the actual bits for the bitmap to be copied
01494                 pPalette        - pointer to the palette 
01495                 pDestInfo       - pointer to an ALLOCATED bitmapinfo structure 
01496                 pDestBits       - pointer to an ALLOCATED 32bit bitmap
01497 
01498     Outputs:    pDestInfo       - pointer to the copied information block
01499                 pDestBits       - pointer ot the copied bits data
01500                 
01501     
01502     Returns:    True if copied ok, false otherwise
01503     Purpose:    Generates a 32bit form of the input 8bit bitmap, note that the destination 
01504                 bitmapinfo and bitmap must be allocated prior to this function
01505 
01506 ********************************************************************************************/
01507 
01508 #define EXPAND(x)   ( (x<<3) | (x>>2) )
01509 
01510 BOOL GRenderBrush::Convert16to32(LPBITMAPINFO pSourceInfo, LPBYTE pSourceBits, RGBQUAD* pPalette,
01511                                       LPBITMAPINFO pDestInfo, LPBYTE pDestBits)
01512 {
01513     ERROR2IF(pSourceBits == NULL, FALSE, "NULL source bitmap");
01514     ERROR2IF(pSourceInfo == NULL, FALSE, "NULL source info");
01515     ERROR2IF(pDestInfo == NULL, FALSE, "NULL destination info");
01516     ERROR2IF(pDestBits == NULL, FALSE, "Null destination bitmap");
01517     
01518     // most info will be the same so memcpy is the quickest way
01519     //memcpy(pSourceInfo, pDestInfo, sizeof(BITMAPINFO));
01520 
01521     // these will all be the same
01522     pDestInfo->bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
01523     pDestInfo->bmiHeader.biWidth         = pSourceInfo->bmiHeader.biWidth;
01524     pDestInfo->bmiHeader.biHeight        = pSourceInfo->bmiHeader.biHeight;
01525     pDestInfo->bmiHeader.biPlanes        = pSourceInfo->bmiHeader.biPlanes;
01526     pDestInfo->bmiHeader.biCompression   = pSourceInfo->bmiHeader.biCompression;
01527     pDestInfo->bmiHeader.biXPelsPerMeter = pSourceInfo->bmiHeader.biXPelsPerMeter;
01528     pDestInfo->bmiHeader.biYPelsPerMeter = pSourceInfo->bmiHeader.biYPelsPerMeter;
01529     pDestInfo->bmiHeader.biClrImportant  = 0;
01530 
01531     // get the size of the new bitmap
01532     INT32 size = pDestInfo->bmiHeader.biWidth *  pDestInfo->bmiHeader.biHeight * 4;
01533     
01534     //these will be different from source
01535     pDestInfo->bmiHeader.biBitCount         = 32;
01536     pDestInfo->bmiHeader.biSizeImage        = size;
01537     pDestInfo->bmiHeader.biClrUsed          = 0;
01538 
01539 
01540     // convert from 16 bit to 32 bit
01541     INT32 bmpsize = pSourceInfo->bmiHeader.biWidth * pSourceInfo->bmiHeader.biHeight;
01542     
01543     // we need some padding just in case we are not DWORD aligned
01544     INT32 padding = pSourceInfo->bmiHeader.biWidth % 2;
01545     if (padding)
01546         padding = 2 - padding;
01547 
01548 
01549     LPBYTE pSourceEnd = pSourceBits;
01550     LPBYTE pDestEnd = pDestBits;
01551 
01552     for (INT32 j = 0; j < bmpsize; j++)
01553     {
01554         pSourceEnd++;
01555         pDestEnd++;
01556     }
01557 
01558     LPWORD pSource = (LPWORD)pSourceBits;
01559     LPBYTE pDest = pDestBits;
01560     for (INT32 i = 0; i < bmpsize; i ++)
01561     {
01562         if (i && i % pSourceInfo->bmiHeader.biWidth == 0)
01563             pSource += padding;
01564         
01565         const WORD Data = *pSource;
01566         
01567         const BYTE Blue = Data & 0x1F;
01568         *pDest++ = EXPAND(Blue);
01569 
01570         const BYTE Green = (Data>>5) & 0x1F;
01571         *pDest++ = EXPAND(Green);
01572 
01573         const BYTE Red = (Data>>10) & 0x1F;
01574         *pDest++ = EXPAND(Red);
01575 
01576         *pDest = 0;
01577         pDest++;
01578     
01579     //  *pSource +=1;
01580         pSource++;
01581         
01582         
01583     
01584     }
01585     return TRUE;
01586 
01587 }
01588 
01589 /********************************************************************************************
01590 
01591 >   void GRenderBrush::SetChangedBBox(DocRect Rect)
01592 
01593     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01594     Created:    29/10/99
01595     Inputs:     Rect - the area to specify as changed
01596     Outputs:    
01597     Purpose:    For some reason when drawing brush steps into a render region there was a problem
01598                 with having the bbox set itself, so this is a way to do it manually
01599                 
01600 
01601 ********************************************************************************************/
01602 
01603 
01604 void GRenderBrush::SetChangedBBox(DocRect Rect)
01605 {
01606     RECT WinRect  = OSRenderRegion::DocRectToWin(RenderMatrix, Rect, PixelsPerInch);
01607     GetDrawContext()->SetChangedBBox(&WinRect);
01608 }
01609 
01610 

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