grndrgn.cpp

Go to the documentation of this file.
00001 // $Id: grndrgn.cpp 1699 2006-08-15 11:43:53Z phil $
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 // GRNDRGN.CPP
00103 //
00104 // Created: 29/6/93 by Will
00105 //
00106 
00107 #include "camtypes.h"
00108 // camconfig.h must be included immediately after camtypes.h
00109 #include "camconfig.h"
00110 
00111 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 
00113 // Includes (alphabetically ordered for convenience)
00114 //#include "andy.h"
00115 //#include "app.h"
00116 //#include "attrmgr.h"
00117 #include "bitmpinf.h"
00118 #include "camelot.h"
00119 //GAT #include "camvw.h"
00120 #include "camview.h"
00121 //#include "ccfile.h"
00122 #include "colormgr.h"
00123 //#include "colplate.h"
00124 //#include "csrstack.h"
00125 
00126 #include "devcolor.h"
00127 //#include "dibconv.h"          // GAT - in camtypes.h [AUTOMATICALLY REMOVED]
00128 //#include "dibutil.h"
00129 //#include "document.h"
00130 //#include "ensure.h"
00131 //#include "errors.h"
00132 #include "f16spec.h"            // for IsMathCoprocInstalled
00133 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00134 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00135 //GAT #include "fonts.h"                // For FixedSystem font from the FontFactory
00136 //#include "fracfill.h"
00137 #include "fuzzclip.h"
00138 
00139 #include "gbrush.h"             // GAT
00140 //#include "gconsts.h"
00141 //#include "gdimagic.h"
00142 #include "XaDraw.h"             // naughty
00143 //GAT #include "gdrawasm.h"
00144 #include "gdrawcon.h"
00145 #include "gradtbl.h"
00146 //GAT #include "grndbmp.h"
00147 //GAT #include "grndbrsh.h"         // so we don't init offscreen rendering for GRenderBrush
00148 
00149 #include "cstroke.h"            // Gavins new GenStroke Functions! MRH 19/5/00
00150 
00151 //#if REAL_DDB
00152 //#include "grndddb.h"
00153 //#endif
00154 
00155 //#include "grnddib.h"
00156 #include "grndprnt.h"
00157 #include "grndrgn.h"
00158 //GAT #include "grndwing.h"
00159 //#include "gversion.h"
00160 
00161 //#include "mainfrm.h"
00162 #include "moldpers.h"
00163 //#include "moldshap.h"
00164 //#include "nodemold.h"
00165 //#include "ops.h"
00166 #include "osrndrgn.h"
00167 #include "palman.h"
00168 //#include "paper.h"
00169 //#include "paths.h"
00170 //#include "pathutil.h"
00171 #include "princomp.h"
00172 #include "printctl.h"
00173 
00174 #include "qualattr.h"
00175 //#include "speedtst.h"
00176 //#include "view.h"
00177 #include "oilbitmap.h"
00178 //#include "ralphdoc.h"
00179 #include "fillramp.h"
00180 #include "bubbleid.h"
00181 #include "grndclik.h"
00182 //#include "mario.h"
00183 #include <math.h>
00184 
00185 // Offscreen rendering system - Ilan
00186 #include "offattr.h"
00187 #include "offscrn.h"
00188 //#include "capturemanager.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00189 
00190 #include "clipattr.h"   // so we know what a ClipRegionAttribute is.
00191 
00192 #include "maskedrr.h"
00193 #include "prdlgctl.h"
00194 
00195 #include "camprofile.h"
00196 #include "fillattr2.h"
00197 
00198 DECLARE_SOURCE("$Revision: 1699 $");
00199 
00200 
00201 // Declare all the classes in this file and ask for memory tracking
00202 CC_IMPLEMENT_DYNAMIC( GRenderRegion, RenderRegion )
00203 CC_IMPLEMENT_DYNCREATE(OpGDraw, Operation)
00204 
00205 #define new CAM_DEBUG_NEW
00206 
00207 // Release version of VC++ 2 does not have all the GDI constants that the old one
00208 // did, so we add the one we need here.
00209 #ifndef DIB_PAL_INDICES
00210 #define DIB_PAL_INDICES (2)
00211 #endif
00212 
00213 // Define these symbols if you want extra debugging help
00214 #ifdef _DEBUG
00215 //  #define DEBUG_ATTACH_CAPTURED_BMP
00216 //  #define DEBUG_ATTACH_RENDERSTATE_BMP
00217 //  #define DEBUG_ATTACH_TCHANGE_BMP
00218 #endif
00219 
00220 
00221 BOOL GRenderRegion::WantDoGDraw = TRUE;             // TRUE if user wants it
00222 UINT32 GRenderRegion::WantGDrawDepth;                   // desired depth of off-screen bitmap
00223 //BOOL GRenderRegion::WantNoPalette;                    // TRUE if palette switching not wanted
00224 //UINT32 GRenderRegion::WantBlitMode;                   // 0=auto, 1=Streth, 2=SetDIB, 3=BitBlt, 4=BadDDB
00225 //BOOL GRenderRegion::WantHighColourDirect;         // TRUE if deep sprite plots directly
00226 //BOOL GRenderRegion::WantDeepGDraw;                    // TRUE for 32-bit DIB plotting to screen
00227 //BOOL GRenderRegion::WantWinG;                     // TRUE for WinG rendering
00228 INT32  GRenderRegion::WhichTransparency = 0;            // type of transparency
00229 
00230 BOOL GRenderRegion::CanDoGDraw;                     // TRUE if it is physically permitted
00231 //BOOL GRenderRegion::CanDoPalIndices;              // TRUE if GDI does DIB_PAL_INDICES
00232 //BOOL GRenderRegion::CanSetPalette;                    // TRUE if screen has palette support
00233 //BOOL GRenderRegion::CanDoDeepDIBs;                    // TRUE if understands 16- and 32-bpp DIBs
00234 
00235 BitmapConvertHint GRenderRegion::ScreenHinting;     // used to hint bitmap conversions
00236 
00237 INT32 GRenderRegion::ScreenDepth;                       // in bits/pixel
00238 INT32 GRenderRegion::ScreenWidth;                       // in pixels
00239 INT32 GRenderRegion::ScreenHeight;                  // in pixels
00240 INT32 GRenderRegion::LogPixelsX;
00241 INT32 GRenderRegion::LogPixelsY;
00242 
00243 GDrawContext *GRenderRegion::pRealGD = NULL;        // ptr to GDraw we want to use
00244 
00245 GDrawContext *GRenderRegion::GD = NULL;             // ptr to GDraw we want to use
00246 
00247 GDrawContext *GRenderRegion::ErrorDiffContext = NULL;   // ptr to GDraw we want to use for error diffusion
00248 
00249 LPRGBQUAD GRenderRegion::Fixed256Palette;           // NULL if not fixed palette (256 cols only)
00250 
00251 //BOOL GRenderRegion::RealFPU;                      // TRUE if real, FALSE if emulated
00252 
00253 //INT32 GRenderRegion::LastPaletteFlag = -1;            // Last value passed to GDraw_SelectPalette
00254 
00255 INT32 GRenderRegion::ViewDither = 2;                    // Dither style used for views
00256 INT32  GRenderRegion::WhichDither = 2;              // which dither mode for 32->8 conversions
00257 
00258 RealLogPalette GRenderRegion::ErrorDiffPalette =    // ptr to GDraw's default palette so we do not
00259 {                                                   // have to call GDrawContext::SelectPalette (with its
00260     0x300,                                          // possibly slow context switch)
00261     256
00262 };
00263 
00264 static RealLogPalette StandardPalette = 
00265 {
00266     0x300,
00267     256
00268 };
00269 
00270 static BYTE NoTransTable[256];                      // default translation table
00271 
00272 static BOOL ClippedPathIsValid;
00273 
00274 enum BlitModeType
00275 {
00276     BLITMODE_STRETCH,
00277     BLITMODE_SETDIBS,
00278     BLITMODE_BITBLT,
00279     BLITMODE_BADDDB
00280 } BlitMode;
00281 
00282 // TODOG: Nasty local preference...
00283 static INT32 LargeGradTables = 0;
00284       
00285 // setting this to non-zero controls fresh bitmap initialisation
00286 #define FILL_BITMAP 0
00287 
00288 
00289 /********************************************************************************************
00290 
00291     Preference: ClickTranspLimit
00292     Section:    Screen
00293     Range:      0 to 255
00294     Purpose:    Determine how transparent rendered pixels may be before click detection
00295                 will ignore them.
00296                 E.g. 230 means pixels must be 90% transparent before they will be ignored
00297 
00298 ********************************************************************************************/
00299 
00300 UINT32 GRenderRegion::ClickTranspLimit = 255;
00301 
00302 
00303 /********************************************************************************************
00304 
00305     Preference: HighQualityAA
00306     Section:    Rendering
00307     Range:      FALSE - normal Anti-aliasing
00308                 TRUE - High quality Anti-aliasing
00309     Purpose:    Determine whether to use GDraw's high quality anti-aliasing mode
00310 
00311 ********************************************************************************************/
00312 
00313 BOOL GRenderRegion::HighQualityAA = FALSE;
00314 
00315 /********************************************************************************************
00316 
00317     Preference: BitmapConversion
00318     Section:    Rendering
00319     Range:      0 - no bitmap conversion (show printer colours will render wrong)
00320                 1 - fast conversion (visible banding in deep bitmaps and cached stuff)
00321                 2 - medium conversion (best setting for general use)
00322                 3 - slow conversion (not yet implemented, most accurate but slow)
00323     Purpose:    Specifies which bitmap conversion algorithm is used by GDraw when rendering 
00324                 bitmaps in show printer colours mode.
00325 
00326 ********************************************************************************************/
00327 
00328 INT32 GRenderRegion::BitmapConversion = 2;
00329 
00330 
00331 /********************************************************************************************
00332 
00333     Preference: RealFPU
00334     Section:    Screen
00335     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00336     Range:      0 or 1
00337     Purpose:    To tell GDraw whether there is a real FPU in the machine, or whether it
00338                 is emulated. It uses less FPU and more integer when this is 0, giving better
00339                 performance on SX machines. Default value to suit hardware.
00340 
00341 ********************************************************************************************/
00342 
00343 
00344 
00345 
00346 /********************************************************************************************
00347 
00348     Preference: UseGdraw
00349     Section:    Debugflags
00350     Range:      TRUE or FALSE
00351     Purpose:    Allows the user to determine whether gdraw is used or not. Default to on.
00352 
00353 ********************************************************************************************/
00354 
00355 /********************************************************************************************
00356 
00357     Preference: GDrawDepth
00358     Section:    Debugflags
00359     Range:      0,1,4,8,16,32 (24 is NOT valid)
00360     Purpose:    Allows the user to determine the depth of the off-screen bitmap used in
00361                 GDraw rendering. Defaults to 0 which means 'same as screen'.
00362 
00363 ********************************************************************************************/
00364 
00365 /********************************************************************************************
00366 
00367     Preference: ShowTransparency
00368     Section:    Debugflags
00369     Range:      TRUE or FALSE
00370     Purpose:    Allows the user to determine whether 32-bit DIBs are used or not, to control
00371                 transparency. Will vanish at some point when this can be determined
00372                 algorithmically. GDrawDepth must be zero for this to work.
00373 
00374 ********************************************************************************************/
00375 
00376 /********************************************************************************************
00377 
00378     Preference: TransparencyType
00379     Section:    Debugflags
00380     Range:      0=none, 1=reflective, 2=subtractive, 3=additive
00381     Purpose:    Allows the user to determine type of transpanrency used.
00382 
00383 ********************************************************************************************/
00384 
00385 /********************************************************************************************
00386 
00387     Preference: TryWinG
00388     Section:    Debugflags
00389     Range:      TRUE or FALSE
00390     Purpose:    Allows the user to use WinG (if available).
00391 
00392 ********************************************************************************************/
00393 
00394 /********************************************************************************************
00395 
00396     Preference: DontUsePalette
00397     Section:    Debugflags
00398     Range:      0 or 1
00399     Purpose:    Allows the user to stop changing the Windows palette. Defaults to 0 which
00400                 means will use palette if available. Setting to 1 allows debugging of code
00401                 as if it was a fixed-palete device (although such devices usually misbehave
00402                 in the GetSystemPaletteUse call among others so the emulation isn't perfect).
00403 
00404 ********************************************************************************************/
00405 
00406 /********************************************************************************************
00407 
00408     Preference: BlitMode
00409     Section:    Debugflags
00410     Range:      0=auto, 1=StretchDIB, 2=SetDibsToDevice, 3=BitBlt
00411     Purpose:    Specified which blit method to use, defaults to 0 which is 1 for Win32s,
00412                 2 for Windows NT. One day might be able to work out best method by trying
00413                 out the video driver. Value of 3 is iffy.
00414 
00415 ********************************************************************************************/
00416 
00417 /********************************************************************************************
00418 
00419     Preference: HighColourDirect
00420     Section:    Debugflags
00421     Range:      0=no, 1=yes
00422     Purpose:    Makes high-colour bitmaps get plotted directly, instead of being converted
00423                 into 256 colours first. Is very much slower than conversion. Defaults to 0.
00424 
00425 ********************************************************************************************/
00426 
00427 
00428 /********************************************************************************************
00429 
00430     Preference: WhichDither
00431     Section:    Debugflags
00432     Range:      0-n (not range checked).
00433     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00434     Purpose:    Determines which of Gavin's dither algorithms are used when converting
00435                 high colour bitmaps down to lower colour ones. Defaults to 2 (greyscale
00436                 corrected), 1=error diffused, 0=ordered dither
00437 
00438 ********************************************************************************************/
00439 
00440 
00441 
00442 
00443 
00445 // in order to help debug this code, we keep a history of calls so we can see what has
00446 // happened. For use only in desperate debug situations.
00447 // 0 means no, 1 means remember, 2 means dump as we go
00448 
00449 #define REMEMBER_GDRAW  0
00450 
00451 #if REMEMBER_GDRAW
00452 
00453 static struct RemRR
00454 {
00455     GRenderRegion *RR;
00456     char *Where;
00457 } RememberList[256];                                        // crude circular list
00458 
00459 static INT32 RememberWhere = 0;
00460 
00461 static void DoRememberMe(GRenderRegion *lpG, char *name)
00462 {
00463     if (
00464         RememberWhere &&
00465         (RememberList[ RememberWhere-1 ].Where == name) &&  // pointer comparison is OK
00466         (RememberList[ RememberWhere-1 ].RR == lpG)
00467        )
00468         // same as last time so ignore
00469         return;
00470 
00471     RememberList[ RememberWhere ].Where = name;
00472     RememberList[ RememberWhere ].RR = lpG;
00473 
00474     RememberWhere++;
00475     if (RememberWhere == 256)
00476         RememberWhere = 0;                                      // wrap past the end
00477 
00478     #if REMEMBER_GDRAW==2
00479     TRACE( _T("%08lx %s\n"), lpG, name );
00480     #endif
00481 }
00482 
00483 static void DoRememberDump(GRenderRegion *lpG)
00484 {
00485     for (INT32 i=0; i<RememberWhere; i++)
00486         TRACE( _T("%08lx %s\n"), RememberList[i].RR, RememberList[i].Where);        
00487 }
00488 
00489 #define RememberMe(name)    DoRememberMe(this, name)
00490 #define RememberDump()      DoRememberDump(this)
00491 
00492 #else
00493 // stub the function calls out
00494 #define RememberMe(name)
00495 #define RememberDump()
00496 
00497 #endif
00498 
00499 /********************************************************************************************
00500 
00501 >   BOOL GRenderRegion::Init( BOOL bFirstTime )
00502 
00503     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00504     Created:    7/12/93
00505     Inputs:     bFirstTime is TRUE if called during startup, or FALSE if called subsequently
00506                 (e.g. when screen mode changes).
00507     Outputs:    -
00508     Returns:    TRUE if worked OK
00509     Purpose:    Determine possibility of using gdraw routines and determine various
00510                 characterisitics of the screen.
00511     Errors:     -
00512     Scope:      Static
00513 
00514 ********************************************************************************************/
00515 
00516 BOOL GRenderRegion::Init( BOOL bFirstTime )
00517 {
00518     BOOL GDrawImpossible = FALSE;
00519 
00520     // Scary critical section stuff
00521 //  CriticalSection::Init();    // Not required for CDraw
00522     
00523     if (bFirstTime)
00524     {
00525         CanDoGDraw = FALSE;
00526 
00527         if (Camelot.DeclareSection( _T("DebugFlags"), 20))
00528         {
00529             Camelot.DeclarePref( NULL, _T("UseGdraw"), &WantDoGDraw, FALSE, TRUE );
00530             Camelot.DeclarePref( NULL, _T("GDrawDepth"), &WantGDrawDepth, 0, 32 );
00531 //          Camelot.DeclarePref( NULL, "DontUsePalette", &WantNoPalette, FALSE, TRUE );
00532 //          Camelot.DeclarePref( NULL, "BlitMode", &WantBlitMode, 0, 4 );
00533 //          Camelot.DeclarePref( NULL, "HighColourDirect", &WantHighColourDirect, 0, 1 );
00534 //          Camelot.DeclarePref( NULL, "TryWinG", &WantWinG, FALSE, TRUE );
00535             Camelot.DeclarePref( NULL, _T("WhichDither"), &WhichDither, 0, 20 );
00536 //          Camelot.DeclarePref( NULL, "LargeGradTables", &LargeGradTables, 0, 1 );
00537 // TransparencyType removed by Gerry (23/8/96) cos its rampant
00538 //          Camelot.DeclarePref( NULL, "TransparencyType", &WhichTransparency, 0, 10 );
00539 //          Camelot.DeclarePref( NULL, "ResizeRegions", &ResizeRegions, FALSE, TRUE );
00540         }
00541 
00542         if (Camelot.DeclareSection( _T("Screen"), 10))
00543         {
00544             Camelot.DeclarePref( NULL, _T("ClickTranspLimit"), &ClickTranspLimit, 0, 255 );
00545             // defaults to hardware value
00546 //          RealFPU = IsMathCoprocInstalled();
00547 //          Camelot.DeclarePref( NULL, "RealFPU", &RealFPU, FALSE, TRUE );
00548             Camelot.DeclarePref(NULL, _T("ViewDither"), &ViewDither, 0, 4);
00549         }
00550 
00551         if (Camelot.DeclareSection(_T("Rendering"), 20))
00552         {
00553             Camelot.DeclarePref( _T("Rendering"), _T("HighQualityAA"), &HighQualityAA, FALSE, TRUE );
00554             Camelot.DeclarePref( _T("Rendering"), _T("BitmapConversion"), &BitmapConversion, 0, 3 );
00555         }
00556 
00557         if (pRealGD == NULL)
00558             pRealGD = new GDrawAsm();                       // get permanent one
00559 
00560         // fill in default translation tables
00561         for (INT32 i=0; i<256; i++)
00562             NoTransTable[i] = i;
00563     }
00564 
00565     // Initialise the palette manager
00566 //  PaletteManager::Init();
00567     
00568     // Initialise the DIBConvert classes (don't care if it fails)
00569     DIBConvert::Init();
00570 
00571     ::wxDisplaySize(&ScreenWidth,&ScreenHeight);
00572     ScreenDepth = ::wxDisplayDepth();
00573     wxScreenDC dc;
00574     wxSize size = OSRenderRegion::GetFixedDCPPI(dc);
00575 PORTNOTE("other","Can't handle different DPIs, using X")
00576     LogPixelsX = size.x;
00577     LogPixelsY = size.y; //size.y;
00578     ERROR3IF(LogPixelsX != LogPixelsY, "Luke says non-square pixels are not supported");
00579 
00580 //  CanSetPalette = FALSE;
00581 
00582     // on startup lets make sure the GDraw version is OK. Must be done before any GDraw calls
00583     if (bFirstTime)
00584     {
00585         if (!pRealGD->Init())                           // checks version etc
00586         {
00587             GDrawImpossible = TRUE;
00588             CanDoGDraw = FALSE;
00589             Error::SetError( _R(IDW_BADGDRAW), NULL, 0 );
00590             InformWarning();                            // tell the user his DLL is wrong
00591             Error::ClearError();                        // else we won't start up
00592         }
00593         GD = pRealGD;
00594     }
00595 /*
00596     switch ( ScreenDepth )
00597     {
00598     case  4 : ScreenHinting = CONVHINT_SCREEN4; break;
00599     case  8 : ScreenHinting = CONVHINT_SCREEN8; break;
00600     case 16 : ScreenHinting = CONVHINT_FINAL16; break;
00601     case 24 : ScreenHinting = CONVHINT_FINAL24; break;
00602     default : ScreenHinting = CONVHINT_NONE;
00603     }
00604 */
00605     // we can set a palette if we are on a 256-colour screen and it says that we can
00606 PORTNOTE("other","GRenderRegion::Init - Removed palette code")
00607 #ifndef EXCLUDE_FROM_XARALX
00608     if (
00609         ScreenDepth==8 &&               // 256 cols only
00610         !WantNoPalette                  // and user hasn't forbidden it
00611        )
00612     {
00613         if (GetDeviceCaps( hdc, RASTERCAPS ) & RC_PALETTE )
00614             CanSetPalette = TRUE;
00615     }
00616 #endif
00617 
00618     ScreenHinting = CONVHINT_NONE;      // safe default value
00619     if ( ScreenDepth<=8 )
00620         ScreenHinting = DIBUtil::CalcConvertHint(ScreenDepth,NULL);
00621     else
00622     {
00623         // work out bitmap hinting by opening tiny window in top left of screen
00624         // It is TOPMOST so that, with luck, nothing will obscure it
00625     //  wxWindow tempWindow(AfxGetApp().GetTopWindow(),-1,wxPoint(0,0),wxSize(0,0),wxNO_BORDER);
00626     //  tempWindow.Show();
00627     //  tempWindow.Raise();
00628     //  wxClientDC tempDC(&tempWindow);
00629     //  ScreenHinting = DIBUtil::CalcConvertHint(ScreenDepth,&tempDC);
00630         wxColour colour;
00631         dc.GetPixel(0,0,&colour);
00632         ScreenHinting = DIBUtil::CalcConvertHint(ScreenDepth,&dc);
00633         dc.SetPen(wxPen(colour));
00634         dc.DrawPoint(0,0);
00635     }
00636 
00637     if (
00638         !GDrawImpossible &&
00639         (
00640             ScreenDepth==1 ||
00641             ScreenDepth==4 ||
00642             ScreenDepth==8 ||                                   // only certain depths allowed
00643             ScreenDepth==16 ||
00644             ScreenDepth==24 ||
00645             ScreenDepth==32
00646         )
00647        )
00648     {
00649         CanDoGDraw = TRUE;
00650 /*
00651         // DIB_PAL_INDICES is not available on Win32s or Chicago
00652         // or on 256 colour fixed palette devices
00653         if (IsWin32s())
00654             CanDoPalIndices = FALSE;
00655         else
00656             CanDoPalIndices = TRUE;
00657 */
00658         EnsurePalette(0);
00659         // set the stack limit to 100k. Assumes stacks go backwards
00660         GD->SetStackSize(100*1024);
00661 
00662         if (ErrorDiffContext == NULL)
00663         {
00664             ErrorDiffContext = new GDrawAsm();          // get permanent one
00665 
00666             if (ErrorDiffContext)
00667                 ErrorDiffContext->Init();
00668         }
00669 
00670 /*      UpdateErrorDiffPalette();
00671 
00672         if (
00673             (ScreenDepth==8) &&
00674             !CanSetPalette
00675            )
00676         {
00677             // if we're a 256 colour fixed palette device then we make up a default RGB table
00678             // and use that
00679             Fixed256Palette = (LPRGBQUAD) CCMalloc( sizeof(RGBQUAD) * 256 );
00680 
00681             const LOGPALETTE* lpPal = GD->SelectPalette( 0 );
00682 
00683             if (Fixed256Palette && lpPal)
00684             {
00685                 for (INT32 i=0; i<256; i++)
00686                 {
00687                     Fixed256Palette[i].rgbRed   = lpPal->palPalEntry[i].peRed;
00688                     Fixed256Palette[i].rgbGreen = lpPal->palPalEntry[i].peGreen;
00689                     Fixed256Palette[i].rgbBlue  = lpPal->palPalEntry[i].peBlue;
00690                     Fixed256Palette[i].rgbReserved = 0;
00691                 }
00692             }
00693 
00694             // DIB_PAL_INDICES makes no sense on these devices
00695             CanDoPalIndices = FALSE;
00696         }
00697 */
00698     }
00699 /*
00700     switch (WantBlitMode)
00701     {
00702         case 4:
00703             #if REAL_DDB
00704             // user wants badDDBs, only allow if possible
00705             if (GRenderDDB::CanDoBadDDBs())
00706             {
00707                 BlitMode = BLITMODE_BADDDB;
00708                 break;
00709             }
00710             #endif
00711             // else fall through to default mode
00712             nobreak;
00713         case 0:
00714             // automatic setting using faster blits on non-NT platforms
00715             if (IsWin32NT())
00716                 BlitMode = BLITMODE_SETDIBS;
00717             else
00718                 BlitMode = ( (ScreenDepth==4) || (ScreenDepth==8) ) ? BLITMODE_BITBLT : BLITMODE_STRETCH;
00719             break;
00720         case 1:
00721             BlitMode = BLITMODE_STRETCH;
00722             break;
00723         case 2:
00724             BlitMode = BLITMODE_SETDIBS;
00725             break;
00726         case 3:
00727             // use DDBs on 16- and 256-colour modes only
00728             BlitMode = ( (ScreenDepth==4) || (ScreenDepth==8) ) ? BLITMODE_BITBLT : BLITMODE_STRETCH;
00729             break;
00730         default:
00731             BlitMode = BLITMODE_STRETCH;                    // safest default value
00732             break;
00733     }
00734 */
00735     // only NT can do BI_BITFIELD, Win32s and Chicago cannot.
00736     // Actually NT isn't guaranteed to support that any more
00737     //CanBiBitfield = IsWin32NT() ? TRUE : FALSE;
00738 
00739     // only NT can do 16- and 32-bit DIBs, Win32s cannot. Chicago might?
00740 //  CanDoDeepDIBs = IsWin32NT() ? TRUE : FALSE;
00741 // Changed by Will, on 14/7/95, as requested by Jason.
00742 // Apparently the PlotDeepDIB routine doesn't dither correctly.
00743 //  CanDoDeepDIBs = FALSE;
00744 
00745 //  #if REAL_DDB && WIN16
00746 //  GRenderDDB::CanDoBadDDBs();
00747 //  #endif
00748 
00749     // init WinG if required. Saves memory if not wanted
00750 //  if (WantWinG)
00751 //      GRenderWinG::Init( bFirstTime );
00752 
00753     if (!Operation::RegisterOpDescriptor(
00754                         0,
00755                         _R(IDS_GDRAW),
00756                         CC_RUNTIME_CLASS(OpGDraw),
00757                         OPTOKEN_GDRAW,
00758                         OpGDraw::GetState,
00759                         0,  // help ID
00760                         _R(IDBBL_GDRAWOP),
00761                         0   // bitmap ID
00762                         ))
00763         return FALSE; 
00764 
00765     if (!GBrush::InitGBrush( bFirstTime ))
00766         return FALSE;
00767 
00768     INT32 Flatness = INT32(MILLIPOINTS_PER_INCH/96 / 2);
00769     GD->SetFlatness( Flatness );
00770 
00771     return TRUE;
00772 }
00773 
00774 /********************************************************************************************
00775 
00776 >   void GRenderRegion::DeInit()
00777 
00778     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00779     Created:    13/4/94
00780     Inputs:     -
00781     Outputs:    -
00782     Returns:    -
00783     Purpose:    Call once during termination to perform any necessary cleanup.
00784     Errors:     -
00785     Scope:      Static
00786 
00787 ********************************************************************************************/
00788 
00789 void GRenderRegion::DeInit()
00790 {
00791 /*  if (Fixed256Palette != NULL)
00792     {
00793         CCFree(Fixed256Palette);
00794         Fixed256Palette = NULL;
00795     }
00796 */
00797     ERROR3IF(GD != pRealGD, "GDraw context not restored in GRenderRegion::DeInit");
00798     
00799     GD = NULL;
00800 
00801     if (pRealGD)
00802     {
00803         delete pRealGD;
00804         pRealGD = NULL;
00805     }
00806 
00807     // Clean up the DIBConvert classes
00808     DIBConvert::DeInit();
00809 
00810     if (ErrorDiffContext != NULL)
00811     {
00812         delete ErrorDiffContext;
00813         ErrorDiffContext = NULL;
00814     }
00815 
00816 //  GRenderWinG::Deinit();
00817 
00818     // Scary critical section stuff
00819 //  CriticalSection::DeInit();  // Not required for CDraw
00820     
00821     // Make sure GBrush doesn't leave any memory leaks lying around
00822     GBrush::DeinitGBrush();
00823 }
00824 
00825 // set this to 1 to leave a border around all GDraw plotting areas
00826 #define DEBUG_BORDER    0
00827 
00828 /********************************************************************************************
00829 
00830 >   GRenderRegion::GRenderRegion(DocRect ClipRect, Matrix ConvertMatrix, FIXED16 ViewScale,
00831                                     UINT32 Depth, double dpi)
00832 
00833     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00834     Created:    11/5/93
00835     Inputs:     ClipRect is a DocRect defining the invalid rectangle to be rendered.
00836                 ConvertMatrix is a Matrix for converting Doc coords to OS coords.
00837                 ViewScale is the scale factor of the view, used to calculate how much to
00838                 flatten paths. Depth is bitmap depth required. dpi is the pixels-per-inch
00839                 which can be zero for screen resolution.
00840     Outputs:    -
00841     Returns:    -
00842     Purpose:    Constructor for a GRenderRegion.
00843                 INT32 dpi changed to double dpi (12/12/95) to improve the range of values allowed
00844                 at the < 1000dpi settings that we will be using.
00845     Errors:     -
00846     SeeAlso:    -
00847 
00848 ********************************************************************************************/
00849 
00850 GRenderRegion::GRenderRegion(DocRect ClipRegion, Matrix ConvertMatrix, FIXED16 ViewScale,
00851                                 UINT32 Depth, double dpi)
00852     : RenderRegion(ClipRegion, ConvertMatrix, ViewScale)
00853 {
00854     pBitmapInfo = NULL;
00855     pBits       = NULL;
00856 #if USE_wxBITMAP
00857     pBitmap     = NULL;
00858     pBitmapData = NULL;
00859 #endif
00860 
00861 //  BitmapSize = 0;
00862     
00863     // If specified dpi is zero then use the calculated screen dpi otherwise use the specified value
00864     if (dpi == 0.0)
00865         PixelsPerInch = (double)LogPixelsX;
00866     else
00867         PixelsPerInch = dpi;
00868     ERROR3IF(PixelsPerInch < 4.0,"GRenderRegion PixelsPerInch < 4 dpi, is this good?");
00869 
00870     hPalette = NULL;
00871     hPrevPalette = NULL;
00872     uBitmapDepth = Depth;
00873 //GAT   FractalBitmap = NULL;
00874     UseSolidColours = FALSE;
00875     LocalBitmap = TRUE;                             // always local bitmap currently
00876     m_bEnableConversion = TRUE;
00877     dScaledPixelWidth = 0.0;
00878 
00879     if (LocalBitmap)
00880     {
00881         WRect = wxRect(0,0,0,0);
00882 
00883         // this ensure triggers up on bitmap export, so it is removed
00884         //ENSURE( (WRect.left>=0) && (WRect.top>=0), "neg wrect");
00885 
00886         #if DEBUG_BORDER
00887         // kludge the rectangle slightly
00888         WRect.left += 2; WRect.width -= 4;
00889         WRect.top += 2; WRect.height -= 4;
00890         #endif
00891     }
00892     else
00893         ENSURE(FALSE, "Non local bitmap error");
00894 
00895     // BG time slice should be 0.5 of a second due to blit overhead
00896     Timeslice = 500;
00897 
00898     // Set default dither type
00899     DitherStyle8Bit = WhichDither;
00900 
00901     m_DoCompression = FALSE;
00902 
00903     m_bForceBitmapSmoothing = FALSE;
00904     m_ForcePrintingCaps = FALSE;
00905 
00906     // Set the render caps up
00907     GetRenderRegionCaps(&Caps);
00908 
00909     // Ilan
00910     IsWrapped = FALSE;
00911 
00912     // Default to not forcing Init (allocation will force it anyway)
00913     ForceInitBmpBits = FALSE;
00914 
00915     RememberMe("Constructor");
00916 }
00917 
00918 
00919 /********************************************************************************************
00920 
00921 >   GRenderRegion::~GRenderRegion()
00922 
00923     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00924     Created:    15/5/93
00925     Inputs:     -
00926     Outputs:    -
00927     Returns:    -
00928     Purpose:    Default Destructor for GRenderRegion Class. Frees up memory.
00929     Errors:     -
00930     SeeAlso:    - GRenderRegion::FreeOffscreenState()
00931 
00932 ********************************************************************************************/
00933 
00934 GRenderRegion::~GRenderRegion()
00935 {
00936 #ifdef RALPH
00937 #ifdef _DEBUG
00938     if(GetCurrentThreadId() == RalphDocument::GetImportingThreadID())
00939     {
00940         TRACE( _T("Whoop Whoop... GRenderRegion::~GRenderRegion called from load thread\n"));
00941         AfxDebugBreak();
00942     }
00943 #endif
00944 #endif
00945 
00946     if (RenderFlags.Rendering)
00947     {
00948         TRACE( _T("StopRender() was not called before destructor\n") );
00949         StopRender();
00950     }
00951 
00952 //GAT   if (FractalBitmap)
00953 //      delete FractalBitmap;
00954     
00955     // manual removal of the contents of our clip-maps.
00956     FreeStoredClipRegions();
00957 
00958     RememberMe("Destructor");
00959 }
00960 
00961 
00962 // Call this inplace of FreeLPBits in any derived classes!!!!
00963 // Used in deconstructors of derived classes and in GetNextBand(), ResetRegion(), ResizeRegion()
00964 void GRenderRegion::FreeOffscreenState()
00965 {
00966     // This function gets called when render regions deconstruct
00967     // It frees memory allocate to offscreen bitmaps as wella s the inital
00968     // bitmap.
00969     // NB this gets called before the attribute context stack is unwound (this happens
00970     // when ~RenderRegion calls CleanUpBeforeDestruct(RenderRegion *pRegion))
00971 
00972     // This function frees handles the freeing of all memory allocted to bitmaps. Includes:-
00973     // 1) offscreen bmp memory  - alloc'd by the Offscreen rendering system, NOT from limited mem
00974     // 2) initial bmp memory    - alloc'd by virtual GetLPBits() in a derived class specific fashion
00975     //                          - (ie either from limited mem manager or normal heap)
00976     //
00977     // It also restores the initial rendering states' wrect, cliprect, and gmatrix variables
00978 
00979     Capture* pCapture = NULL;
00980     while (GetTopCapture())
00981     {
00982         pCapture = GetTopCapture();
00983         m_CaptureStack.Pop();
00984 
00985         // If we've reached the master capture
00986         // reset the rendering variables in case this RenderRegion survives for a while
00987         if (pCapture->IsMaster())
00988             SetRenderToCapture(pCapture, FALSE, FALSE);
00989         else
00990             pCapture->FreeDIB();
00991 
00992         delete pCapture;
00993     }
00994 
00995 #if USE_wxBITMAP
00996     FreeWxBitmap() ;
00997 #else
00998     if ( pBitmapInfo && pBits )
00999     {
01000         FreeLPBits( pBitmapInfo, pBits );
01001         pBitmapInfo = NULL;
01002         pBits = NULL;
01003     }
01004 #endif
01005 }
01006 
01007 BOOL GRenderRegion::CopyRenderInfo( const RenderRegion &Other)
01008 {
01009     RememberMe("CopyRenderInfo");
01010 
01011     if (!RenderRegion::CopyRenderInfo( Other ))
01012         return FALSE;
01013 
01014     ENSURE( Other.IsKindOf( CC_RUNTIME_CLASS(GRenderRegion) ) , "CopyRenderOther wrong class" );
01015 
01016     // safe to cast now
01017     const GRenderRegion *GOther = (GRenderRegion*)&Other;
01018 
01019     // copy most of the member variables
01020     LocalBitmap = GOther->LocalBitmap;
01021     if (LocalBitmap)
01022     {
01023         // leave WRect alone
01024         ScreenRect = wxRect(0,0,0,0);
01025     }
01026     else
01027     {
01028         // (hmm, untested dubious code)
01029         WRect = GOther->WRect;
01030         ScreenRect = GOther->ScreenRect;
01031     }
01032 
01033     PixelsPerInch = GOther->PixelsPerInch;
01034     dScaledPixelWidth = GOther->dScaledPixelWidth;
01035     hPalette = GOther->hPalette;
01036     hPrevPalette = NULL;
01037 
01038     return TRUE;
01039 }
01040 
01041 /********************************************************************************************
01042 >   BOOL GRenderRegion::()
01043     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01044     Created:    19/3/00
01045     Purpose:    Get rid of offscreen state stack so we can restart from scratch
01046     Errors:     -
01047     SeeAlso:    GRenderDIB::ResizeRegion()
01048 ********************************************************************************************/
01049 void GRenderRegion::ResetRegion(DocRect &NewClipRect)
01050 {
01051 #ifdef _DEBUG
01052 //  if(CurrentRenderState)
01053 //      TRACEUSER( "Ilan", _T("RR (0x%x) being reset\n   Context = %s (0x%x)\n   Offscreen stack size = %d\n"), (DWORD)this, CurrentRenderState->Name(),(DWORD)CurrentRenderState, m_OffscreenStateStack.Size());
01054 //      TRACEUSER( "Ilan", _T("RR (0x%x) being reset\n   Context = %s (0x%x)\n   Offscreen stack size = %d\n"), (DWORD)this, CurrentRenderState->Name(),(DWORD)CurrentRenderState, m_CaptureStack.Size());
01055 #endif
01056 
01057     // base class version (called below) needs initial CurrentClipRect to be correct.
01058     // FreeOffscreenState restores RR state as well as freeing offscreen bitmap memory and stacked states
01059     FreeOffscreenState();
01060 
01061     RenderRegion::ResetRegion(NewClipRect);
01062 }
01063 
01064 // NB if you override this ensure that you set lpBitmapInfo->bmiHeader.biCompression
01065 // as it must be correct when GDrawAsm::SetBitmap() is called
01066 void GRenderRegion::InitBmpBits()
01067 {
01068     ENSURE(pBits,"Call to InitBmpBits with null bits pointer!");
01069     if(!pBits)
01070         return;
01071 
01072     LPBITMAPINFOHEADER bh = &pBitmapInfo->bmiHeader;
01073     BYTE* pSetBits = (BYTE*)pBits;
01074 
01075     BOOL UseInternalFormat = FALSE;
01076     if(m_DoCompression)
01077     {
01078         bh->biCompression=0x80000001;       // needs to be set correctly for GetDrawContext()->SetBitmap()
01079         UseInternalFormat = TRUE;
01080     }
01081 
01082     // for offscreen rendering system which doesn't set m_DoCompression properly
01083     if(bh->biCompression==0x80000001)
01084         UseInternalFormat = TRUE;
01085 
01086     // ensure all bitmap memory is initialised (ie don't use the 
01087     // bogus info from the bmp header dimensions)
01088     // NB this assumes that the bmp buff lpBits was allocated using AllocDIB (usually via GetLPBits() fn)
01089     UINT32 BmpSize = GetDIBBitsSize( bh );
01090     UINT32 Index = 0;
01091 
01092     if(bh->biBitCount==32)
01093     {
01094         // 32bpp
01095         if(UseInternalFormat)
01096         {
01097 //          TRACEUSER( "Gerry", _T("Initialising GRR to transparent black\n"));
01098             while(Index < BmpSize)
01099             {
01100                 // initial values for using internal alpha channelled format
01101                 // fully transparent black bacground
01102 
01103                 pSetBits[Index++] = 0x00;
01104                 pSetBits[Index++] = 0x00;
01105                 pSetBits[Index++] = 0x00;
01106                 pSetBits[Index++] = 0xFF;
01107             }
01108         }
01109         else
01110         {
01111 //          TRACEUSER( "Gerry", _T("Initialising GRR to opaque white\n"));
01112             while(Index < BmpSize)
01113             {
01114                 // fully opaque white background
01115                 pSetBits[Index++] = 0xFF;
01116                 pSetBits[Index++] = 0xFF;
01117                 pSetBits[Index++] = 0xFF;
01118                 pSetBits[Index++] = 0x00;
01119             }
01120         }
01121     }
01122     else
01123     {
01124 #if FILL_BITMAP
01125         // this is taken from the previous bmp initialisation code (ie from old StartRender())
01126         memset( pBits, FILL_BITMAP+1, BmpSize );
01127 #else
01128         // this is what I would expect it to be (ie white background)
01129         memset( pBits, 0xFF, BmpSize );
01130 #endif
01131     }
01132 }
01133 
01134 /********************************************************************************************
01135 
01136 >   BOOL GRenderRegion::StartRender()
01137 
01138     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
01139     Created:    7/12/93
01140     Purpose:    Initialises an GRenderRegion for rendering.
01141                 Sets up a bitmap and gmatrix ready for gdraw rendering.
01142     Errors:     -
01143     SeeAlso:    OSRenderRegion::StartRender()
01144 ********************************************************************************************/
01145 BOOL GRenderRegion::StartRender()
01146 {
01147     // Ilan
01148     // The first time StartRender get's called it allocs memory for bitmaps
01149     // However, subsequent calls are made to StartRender during background redrawing, where
01150     // rendering pauses partway through to service other messages, and then resumes later
01151     // In order to pause, StopRender is called to store a pointer to the last node rendered
01152     // and, in the case where we are not busy rendering offscreen, blit the partly completed
01153     // bitmap to screen
01154     // "AllocatedNewBmp" allows us to distinguish between initial calls to StartRender (where
01155     // GetLPBits is called to alloc new bitmaps), and 'restart' calls which don't need to alloc
01156     // any new bmps.
01157     // In the former case the bitmap must be initialised
01158     // In the later case the bitmap must only be re-initialised if m_bDoCompression is set
01159     // as in this case inplace bmp conversion will have occured in the process of transfering 
01160     // the bitmap to the screen (ie during the last StopRender() call)
01161     BOOL AllocatedNewBmp = FALSE;
01162 
01163     RememberMe("StartRender");
01164 
01165     // Call base class first
01166     if (!RenderRegion::StartRender())
01167         return FALSE;
01168 //  RenderMatrix.Dump();
01169 
01170     // Check that Initialise hasn't been called already
01171     ENSURE(RenderFlags.Rendering == FALSE, "Initialise called whilst already rendering");
01172     
01173     // JCF: added this check for retail builds as otherwise this ENSURE goes off after a
01174     // Crash Me Render.
01175     if (RenderFlags.Rendering != false) return FALSE;
01176     
01177     TRACEUSER("Gavin",_T("GRenderRegion::StartRender - RenderFlags.Rendering = TRUE;\n"));
01178     RenderFlags.Rendering = TRUE;
01179 
01180     // lets get the Rect into screen co-ords so we can use our big screen bitmap
01181     // Use a version of OSRenderRegion::DocRectToWin that uses the actual dpi we have stored
01182     // in PixelsPerInch
01183     //RECT Rect = OSRenderRegion::DocRectToWin( RenderMatrix, CurrentClipRect, PixelsPerInch );
01184     // Use a virtual function so that we can now override it in some special case.
01185     // At present, we use this to try and fix pixel problems on bitmap export (GRenderBitmap)
01186     // The e and f components of RenderMatrix may be changed by the call, but only in the bitmap export case
01187     //
01188     // NB PixelsPerInch always set to 96.0 so never accurate unless at 100% zoom?!
01189     wxRect Rect;
01190     if (GetMasterCapture())
01191         Rect = CalculateWinRect(GetMasterCapture()->CaptureMatrix, GetMasterCapture()->CaptureRect, GetMasterCapture()->dPixelsPerInch);
01192     else
01193         Rect = CalculateWinRect(RenderMatrix, CurrentClipRect, PixelsPerInch);
01194 
01195     if (LocalBitmap)
01196     {
01197         ScreenRect = wxRect(0,0,0,0);
01198         // if WRect has changed at all, we're in trouble
01199         const INT32 NewWidth  =  Rect.width;
01200         const INT32 OldWidth  = WRect.width;
01201         const INT32 NewHeight =  Rect.height;
01202         const INT32 OldHeight = WRect.height;
01203 
01204         // Its changed size and/or position, so we'll try and re-size the bitmap
01205         // If this fails, then we'll just re-allocate
01206         // NB GetNextBand() always frees the bitmap memory structs and sets them to NULL
01207         // GRenderDIB::ResizeRegion sets up new bitmap, WRect and CurrentClipRect so doesn't need this
01208         // code
01209         // What would use this code??
01210         // Code used by ExportRender(GRenderOptPalette* pPalRegion) when rendering in strips
01211         if ( pBits!=NULL && pBitmapInfo!=NULL && (NewWidth!=OldWidth || NewHeight!=OldHeight) )
01212         {
01213             // Make sure we are not after an empty one
01214             if (NewWidth == 0 || NewHeight == 0)
01215                 return FALSE;
01216 
01217             // Sanity check
01218             ERROR3IF((NewWidth < 0 || NewHeight < 0),"GRenderRegion::StartRender got a bad rectangle (Width/Height < 0)\n");
01219 
01220             ResetRegion(RegionRect);
01221             if (!RenderRegion::StartRender())
01222                 return FALSE;
01223 
01224             // Get a new bitmap to replace the last one
01225 #if USE_wxBITMAP
01226             pBitmapInfo = AllocWxBitmap(NewWidth,NewHeight,uBitmapDepth);
01227 #else
01228             pBitmapInfo = GetLPBits(NewWidth, NewHeight, uBitmapDepth, &pBits);
01229 #endif
01230             if (pBitmapInfo==NULL)
01231             {
01232                 TRACE( _T("Growing GG failed\n"));
01233                 return FALSE;
01234             }
01235             AllocatedNewBmp = TRUE;
01236             GetMasterCapture()->SetDIB(pBitmapInfo, pBits);
01237         }
01238 
01239         // set new rectangle size
01240         WRect = Rect;
01241     }
01242     else
01243     {
01244         WRect = Rect;
01245         ScreenRect = WRect;
01246         if (RenderView != NULL)
01247         {
01248             CCamView *RenderWindow = RenderView->GetConnectionToOilView();
01249             if ( RenderWindow!=NULL && RenderWindow->GetFrame()!=NULL )
01250             {
01251 //              RenderWindow->ClientToScreen( &ScreenRect );
01252                 wxPoint tl = ScreenRect.GetTopLeft();
01253                 wxPoint br = ScreenRect.GetBottomRight();
01254                 RenderWindow->GetFrame()->ClientToScreen(tl);
01255                 RenderWindow->GetFrame()->ClientToScreen(br);
01256                 ScreenRect = wxRect(tl,br);
01257             }
01258         }
01259         else
01260             ERROR2(FALSE, "No render view in GRenderRegion::StartRender()");
01261 
01262     }
01263 
01264     // Create the default, master capture...
01265     Capture* pNewMasterCapture = NULL;
01266 
01267     if (m_CaptureStack.Empty())
01268     {
01269         ERROR2IF(pBitmapInfo!=NULL, FALSE, "How has this region got a bitmap when the capture stack is empty?");
01270 
01271         pNewMasterCapture = new Capture(this, CAPTUREINFO(ctNESTABLE, cfMASTER | cfPIXWIDTHSCALE), RenderMatrix, CurrentClipRect, PixelsPerInch, CurrentColContext);
01272         if (pNewMasterCapture==NULL) return FALSE;
01273 
01274         m_CaptureStack.Push(pNewMasterCapture);
01275     }
01276 
01277 #ifdef _DEBUG
01278     else
01279     {
01280         // Check capture stack sanity!
01281         Capture* pDebugCapture = GetTopCaptureBitmap();
01282         if (pDebugCapture)
01283         {
01284             ERROR3IF(pDebugCapture->CaptureRect != CurrentClipRect, "Wha?");
01285 //          ERROR3IF(!(pDebugCapture->CaptureMatrix == RenderMatrix), "Wha?");
01286             ERROR3IF(pDebugCapture->dPixelsPerInch != PixelsPerInch, "Wha?");
01287         }
01288     }
01289 #endif
01290 
01291     if (pBitmapInfo==NULL)
01292     {
01293         ERROR2IF(GetMasterCapture()->dPixelsPerInch!=GetPixelsPerInch(), FALSE, "Master capture has different dpi than master bitmap");
01294 
01295         // Get a bitmap
01296 #if USE_wxBITMAP
01297         pBitmapInfo = AllocWxBitmap(WRect.width, WRect.height, uBitmapDepth);
01298 #else
01299         pBitmapInfo = GetLPBits(WRect.width, WRect.height, uBitmapDepth, &pBits);
01300 #endif
01301         if (pBitmapInfo==NULL)
01302         {
01303             ERROR3("Allocating GRenderRegion bitmap failed\n");
01304             return FALSE;
01305         }
01306 
01307         AllocatedNewBmp = TRUE;
01308         GetMasterCapture()->SetDIB(pBitmapInfo, pBits);
01309     }
01310 #ifdef _DEBUG
01311     else
01312     {
01313         // Check capture stack sanity!
01314         ERROR3IF(GetTopCaptureBitmap()==NULL, "There must be at least ONE bitmap capture!");
01315     }
01316 #endif
01317 
01318     // Do the middle bit
01319     if (!StartRenderMiddle())
01320         return FALSE;
01321 
01322     // Determine the correct hinting value for the current output mode, and call gavin to
01323     // set up his offscreen bitmap.
01324 //  DWORD GavinHint = DIBUtil::GetGavinBlitFormat(ScreenDepth, uBitmapDepth, ScreenHinting);
01325 
01326     // If we have just created the master capture then we should initialise the bitmap
01327     if (AllocatedNewBmp || ForceInitBmpBits)
01328     {
01329         InitBmpBits();
01330     }
01331 
01332     // Make sure we don't Init again until something forces it 
01333     ForceInitBmpBits = FALSE;
01334 
01335     // Gerry has re-written this bit so it works properly
01336     // It no longer tries to select a palette when the RenderDC doesn't exist or
01337     // doesn't support a palette
01338     if (RenderDC != NULL)
01339     {
01340 /* GAT  if (ScreenDepth == 8)
01341         {
01342             // use frame windows palette if desired
01343             if (PaletteManager::UsePalette())
01344                 hPalette = *(PaletteManager::GetPalette());
01345         }
01346 */
01347         if (hPalette != NULL)
01348 //          hPrevPalette = PaletteManager::StartPaintPalette(RenderDC->m_hDC);
01349             hPrevPalette = PaletteManager::StartPaintPalette(RenderDC);
01350 
01351         if (uBitmapDepth == 8)
01352         {
01353             // If we are not error diffusing then set the dither style
01354             if ((DitherStyle8Bit != 0) && (DitherStyle8Bit != 3))
01355                 GetDrawContext()->SetDitherStyle((DitherStyle) DitherStyle8Bit);        // Stupid prototype
01356         }
01357 /* GAT  if (ScreenDepth == 8)
01358         {
01359             // Whether we set a palette or not, we need this call on all 8-bit screens
01360             GRenderRegion::GColInit(RenderDC->m_hDC);
01361         }
01362 */  }
01363 
01364     // Start rendering into the current Capture...
01365     // (And always apply the clip region...)
01366     // PROBLEM: Clipping information is lost when background rendering kicks in.
01367     //
01368     // SOLUTION:    (Re)apply the current clipping region whenever the render region
01369     //              starts up (again).        vvvv
01370     SetRenderToCapture(GetTopCaptureBitmap(), TRUE);
01371 
01372     ENSURE(pBitmapInfo && pBits, "No bitmap to render into");
01373 
01374 //  RenderMatrix.Dump();
01375 
01376     return TRUE;
01377 }
01378 
01379 /********************************************************************************************
01380 
01381 >   void GRenderRegion::AllocWxBitmap( UINT32 Width, UINT32 Height, UINT32 Depth )
01382 
01383     Author:     Gavin_Theobald (Xara Group Ltd) <camelotdev@xara.com>
01384     Created:    10/8/2005
01385     Inputs:     Width of bitmap
01386                 Height of bitmap
01387                 Depth of Bitmap
01388     Outputs:    
01389     Returns:    Pointer to BITMAPINFO structure. Returns NULL on failure.
01390     Purpose:    To create bitmap from wxBitmap structure.
01391     SeeAlso:    
01392 
01393 ********************************************************************************************/
01394 
01395 #if USE_wxBITMAP
01396 
01397 LPBITMAPINFO GRenderRegion::AllocWxBitmap( UINT32 Width, UINT32 Height, UINT32 Depth )
01398 {
01399     pBitmap = new wxBitmap(Width,Height,Depth);
01400     pBitmapData = new wxAlphaPixelData(*pBitmap);
01401 
01402     uLineSize = DIBUtil::ScanlineSize(Width,Depth);
01403     INT32 size = uLineSize*Height;
01404     if ( size==0 )
01405         size = 4;                                       // in case of zero w or h
01406 
01407     size_t extras;
01408     INT32 used_cols = 0;
01409     switch (Depth)
01410     {
01411     case  1: extras =   2; used_cols =   2; break;
01412     case  4: extras =  16; used_cols =  16; break;
01413     case  8: extras = 256; used_cols = 256; break;
01414     case 16: extras =   3;                  break;
01415     case 24: extras =   0;                  break;
01416     case 32: extras =   3;                  break;
01417     default:
01418         ENSURE(FALSE, "Bad bitmap depth");
01419         return NULL;
01420     }
01421 
01422     LPBITMAPINFO pInfo;
01423     pInfo = (LPBITMAPINFO)CCMalloc(UINT32(sizeof(BITMAPINFO)+extras*sizeof(COLORREF)));
01424     if ( pInfo==NULL )
01425     {
01426         // Free the memory from the appropriate place
01427         delete pBitmapData;
01428         delete pBitmap;
01429         pBitmapData = NULL;
01430         pBitmap     = NULL;
01431         return NULL;
01432     }
01433 
01434     pBits = (BYTE*)pBitmap->GetRawData(*pBitmapData,Depth);
01435     if ( pBitmapData->GetRowStride()<0 )
01436         pBits += pBitmapData->GetRowStride()*(Height-1);
01437     
01438     pInfo->bmiHeader.biSize             = sizeof(BITMAPINFOHEADER);
01439     pInfo->bmiHeader.biWidth            = Width;
01440     pInfo->bmiHeader.biHeight           = Height;
01441     pInfo->bmiHeader.biPlanes           = 1;
01442     pInfo->bmiHeader.biBitCount         = Depth;
01443     pInfo->bmiHeader.biCompression      = BI_RGB;
01444     pInfo->bmiHeader.biXPelsPerMeter    = 3780;             // Default to 96 dpi
01445     pInfo->bmiHeader.biYPelsPerMeter    = 3780;
01446     pInfo->bmiHeader.biClrUsed          = used_cols;
01447     pInfo->bmiHeader.biClrImportant     = 0;
01448     pInfo->bmiHeader.biSizeImage        = size;
01449 
01450     return pInfo;
01451 }
01452 
01453 #endif
01454 
01455 /********************************************************************************************
01456 
01457 >   void GRenderRegion::FreeWxBitmap()
01458 
01459     Author:     Gavin_Theobald (Xara Group Ltd) <camelotdev@xara.com>
01460     Created:    10/8/2005
01461     Inputs:     Width of bitmap
01462                 Height of bitmap
01463                 Depth of Bitmap
01464     Outputs:    
01465     Returns:    
01466     Purpose:    To free bitmap
01467     SeeAlso:    
01468 
01469 ********************************************************************************************/
01470 
01471 #if USE_wxBITMAP
01472 
01473 void GRenderRegion::FreeWxBitmap()
01474 {
01475     if ( pBits )
01476     {
01477         pBitmap->UngetRawData(*pBitmapData);
01478         delete pBitmap;
01479         delete pBitmapData;
01480         CCFree(pBitmapInfo);
01481         pBitmap     = NULL;
01482         pBits       = NULL;
01483         pBitmapData = NULL;
01484         pBitmapInfo = NULL;
01485     }
01486 }
01487 
01488 #endif
01489 
01490 /********************************************************************************************
01491 
01492 >   virtual WinRect GRenderRegion::CalculateWinRect( const Matrix& RenderMatrix, const DocRect& docrect,
01493                                                      const double dpi)
01494 
01495     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01496     Created:    4/10/96
01497     Inputs:     DocRect is a rectangle on document co-ords.
01498                 dpi is the resolution of the device we are rendering to
01499     Outputs:    RenderMatrix is the rendering matrix, may have e anf f components changed by the call
01500     Returns:    Object containing the new rectangle coordinates.                
01501     Purpose:    To convert a rectangle in Doc coordinates to a rectangle in Win coordinates
01502                 taking account of the destination dpi rather than assuming screen dpi.
01503                 Virtual so that it can be overriden by different render regions if so required.
01504     SeeAlso:    OSRenderRegion::DocRectToWin;
01505 
01506 ********************************************************************************************/
01507 
01508 WinRect GRenderRegion::CalculateWinRect( Matrix& RenderMatrix, const DocRect& docrect,
01509                                          const double dpi)
01510 {
01511     // lets get the Rect into screen co-ords so we can use our big screen bitmap
01512     // Use a version of OSRenderRegion::DocRectToWin that uses the actual dpi we have stored
01513     // in PixelsPerInch
01514     // Ilan
01515     // I need this to use the supplied rectangle - docrect.
01516     // Looks like previous version was a typo so I am changing it here.
01517     // Karim 07/07/2000
01518     // I'm now changing this to actually _use_ the dpi param in its calculations.
01519     // I've checked, and I'm 99.99% certain this doesn't screw up any existing code.
01520     return OSRenderRegion::DocRectToWin( RenderMatrix, docrect, dpi );
01521 //  return OSRenderRegion::DocRectToWin( RenderMatrix, docrect, PixelsPerInch );
01522 //  return OSRenderRegion::DocRectToWin( RenderMatrix, CurrentClipRect, PixelsPerInch );
01523 }
01524 
01525 WinRect GRenderRegion::CalculateWinRect( const DocRect& docrect )
01526 {
01527     return CalculateWinRect(RenderMatrix, docrect, PixelsPerInch );
01528 }
01529 
01530 /********************************************************************************************
01531 
01532 >   BOOL GRenderRegion::StartRenderAfter(GMATRIX *GMat)
01533 
01534     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
01535     Created:    13/6/94
01536     Inputs:     Pointer to a Gavin matrix which can be modified.
01537     Outputs:    -
01538     Returns:    TRUE if worked, FALSE is failed.
01539     Purpose:    A virtual fn in this class which can be overridden if more work on a GMatrix
01540                 is required. Default version returns TRUE.
01541 
01542 ********************************************************************************************/
01543 
01544 BOOL GRenderRegion::StartRenderAfter( GMATRIX *GMat )
01545 {
01546     return TRUE;
01547 }
01548 
01549 /********************************************************************************************
01550 
01551 >   BOOL GRenderRegion::StartRenderMiddle()
01552 
01553     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
01554     Created:    13/6/94
01555     Inputs:     -
01556     Outputs:    -
01557     Returns:    TRUE if worked, FALSE is failed.
01558     Purpose:    A virtual fn in this class which can be overridden if more work on a lpBits
01559                 is required. Default version returns TRUE.
01560 
01561 ********************************************************************************************/
01562 
01563 BOOL GRenderRegion::StartRenderMiddle()
01564 {
01565     return TRUE;
01566 }
01567 
01568 /********************************************************************************************
01569 
01570 >   BOOL GRenderRegion::StopRender()
01571 
01572     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
01573     Created:    7/12/93
01574     Inputs:     RenderState is a Node* pointing at the current rendering node in the tree
01575     Outputs:    -
01576     Returns:    TRUE if something has been rendered since StartRender was called.
01577     Purpose:    Stops the rendering of a GRenderRegion, saving it's current renderstate so
01578                 that rendering can continue where it left off, later on.
01579                 Copies the gdraw internal bitmap to its final resting place (e.g. the screen).
01580                 Also tidies up windows' palette.
01581 
01582     Errors:     -
01583     SeeAlso:    OSRenderRegion::StopRender
01584 
01585 ********************************************************************************************/
01586 
01587 BOOL GRenderRegion::StopRender()
01588 {
01589     RememberMe("StopRender");
01590 
01591     // Remember this now before it gets cleared by SetClean
01592     // or set by the debug code below
01593     BOOL bHaveRendered = HaveRenderedSomething;
01594 
01595 #if 0
01596     if (HaveRenderedSomething)
01597     {
01598         TRACE( _T("GRR#  DebugClipRect = (%d, %d) - (%d, %d)\n"), CurrentClipRect.lo.x, CurrentClipRect.lo.y, CurrentClipRect.hi.x, CurrentClipRect.hi.y);
01599 
01600         DocRect TempRect(CurrentClipRect);
01601         TempRect.Inflate(-GetScaledPixelWidth());
01602         TRACE( _T("GRR#  Filling = (%d, %d) - (%d, %d)\n"), TempRect.lo.x, TempRect.lo.y, TempRect.hi.x, TempRect.hi.y);
01603         Path ClipPath;
01604         ClipPath.Initialise();
01605         ClipPath.CreatePathFromDocRect(&TempRect);
01606 
01607         SaveContext();
01608         SetLineColour(COLOUR_TRANS);
01609         SetFillColour(COLOUR_BLUE);
01610         DrawPath(&ClipPath);
01611         RestoreContext();
01612     }
01613 #endif
01614 #if 0
01615     {
01616         SaveContext();
01617 
01618         SetLineColour(COLOUR_TRANS);
01619         SetFillColour(COLOUR_BLUE);
01620 
01621         DocRect SmallRect(750, 750, 1500, 1500);
01622         Path ThePath;
01623         ThePath.Initialise();
01624         ThePath.CreatePathFromDocRect(&SmallRect);
01625 
01626         DrawPath(&ThePath);
01627         ThePath.Translate(50, 1500);
01628         DrawPath(&ThePath);
01629         ThePath.Translate(50, 1500);
01630         DrawPath(&ThePath);
01631         ThePath.Translate(50, 1500);
01632         DrawPath(&ThePath);
01633         ThePath.Translate(50, 1500);
01634         DrawPath(&ThePath);
01635         ThePath.Translate(50, 1500);
01636         DrawPath(&ThePath);
01637         ThePath.Translate(50, 1500);
01638         DrawPath(&ThePath);
01639         ThePath.Translate(50, 1500);
01640         DrawPath(&ThePath);
01641         ThePath.Translate(50, 1500);
01642         DrawPath(&ThePath);
01643         ThePath.Translate(50, 1500);
01644         DrawPath(&ThePath);
01645         ThePath.Translate(50, 1500);
01646         DrawPath(&ThePath);
01647         ThePath.Translate(50, 1500);
01648         DrawPath(&ThePath);
01649         ThePath.Translate(50, 1500);
01650         DrawPath(&ThePath);
01651         ThePath.Translate(50, 1500);
01652         DrawPath(&ThePath);
01653         ThePath.Translate(50, 1500);
01654         DrawPath(&ThePath);
01655         ThePath.Translate(50, 1500);
01656         DrawPath(&ThePath);
01657 
01658         RestoreContext();
01659     }
01660 #endif
01661     // Check that Initialise was called
01662 //  ENSURE(RenderFlags.Rendering, "DeInitialise called before Initialise");
01663     TRACEUSER("Gavin",_T("GRenderRegion::StopRender - RenderFlags.Rendering = FALSE;\n"));
01664     RenderFlags.Rendering = FALSE;
01665 
01666     // Don't Blit if we are partway through rendering offscreen. The offscreen bitmap must only
01667     // be blitted once it is completed. Offscreen system takes care of resetting the rect which
01668     // GDraw has rendered to (ie ChangedBBox)
01669     if (pBitmapInfo)
01670     {
01671         if (MasterCaptureIsCurrent() && !TopCaptureIsDirect())
01672         {
01673             // if we rendered something then blit, else we don't. This is handy for not
01674             // double-blitting paper areas. Could take it even further to only blit those areas
01675             // of the bitmap which have been written to.
01676 
01677             if (HaveRenderedSomething)
01678             {
01679                 // Show the current rendering state on screen
01680                 // No, just needs a simple blit to screen...
01681                 // This is the commonest, fast case
01682                 DisplayBits();
01683 
01684                 // We have updated the screen, so now we're 'clean'.
01685                 SetClean(TRUE, FALSE);
01686             }
01687         }
01688         else
01689         {
01690             // We were rendering into Capture bitmaps when this Stop request
01691             // occurred so, to show current progress, we must blit the contents
01692             // of the capture stack into a copy of the master bitmap and
01693             // put that on the screen...
01694             //
01695             // Note that we CANNOT alter the master bitmap itself because when
01696             // the captures terminate properly they will again be blitted into
01697             // the master bitmap and so the master bitmap must not contain any
01698             // earlier version of the captures otherwise transparency values
01699             // would be multiplied.
01700             //
01701             if (HaveRenderedSomething)
01702             {
01703                 // Make a temporary bitmap from the current state of things and display that
01704                 DisplayCurrentState();
01705 
01706                 // We have updated the screen, so now we're 'clean'.
01707                 SetClean(TRUE, FALSE);
01708             }
01709         }
01710     }
01711     else
01712     {
01713         if(!IsWrapped)
01714             TRACE( _T("GRenderRegion::StopRender called with no bitmap\n"));
01715     }
01716 
01717     if (hPrevPalette)
01718         PaletteManager::StopPaintPalette(RenderDC, hPrevPalette);
01719 
01720     // Clean out the Fuzzy Rectangles
01721     InnerRect.MakeEmpty();
01722     OuterRect.MakeEmpty();
01723 
01724     // Karim 04/05/2000
01725     // free all of our cached clipping regions.
01726     FreeStoredClipRegions();
01727 
01728     // Reset dither style to ordered dither on 8bpp screens
01729     if (ScreenDepth == 8)
01730         GetDrawContext()->SetDitherStyle(DITHER_GREY_ORDERED);
01731 
01732     return bHaveRendered;
01733 }
01734 
01735 
01736 
01737 
01738 /********************************************************************************************
01739 
01740 >   virtual void GRenderRegion::DisplayCurrentState()
01741 
01742     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
01743     Created:    30/07/2005
01744     Purpose:    Make a temporary bitmap, copy current GRenderRegion bitmap into it
01745                 then render other offscreen state into it before blitting it to screen
01746     Notes:      This routine does a lot of bitmap copying and blitting so it is much
01747                 slower than just blitting the current bitmap to screen!
01748 
01749 ********************************************************************************************/
01750 
01751 void GRenderRegion::DisplayCurrentState()
01752 {
01753     // Create a temporary capture that is a copy of the master capture
01754     // (and get a copy of the bitmap)
01755     Capture* pTempCapture = new Capture(GetMasterCapture(), TRUE);
01756 
01757     if (pTempCapture)
01758     {
01759         // Point rendering at the temp capture bitmap
01760         SetRenderToCapture(pTempCapture);
01761 
01762         // Render the current capture state into the temp bitmap
01763         RenderCurrentCaptureState();
01764 
01765 #ifdef DEBUG_ATTACH_RENDERSTATE_BMP
01766 {
01767 // Create a Kernel bitmap from the bmp data.
01768 WinBitmap* wBitmap          = new WinBitmap(pTempCapture->lpBitmapInfo, pTempCapture->lpBits);
01769 KernelBitmap* OffscreenBitmap   = new KernelBitmap(wBitmap,TRUE);
01770 OffscreenBitmap->AttachDebugCopyToCurrentDocument("Render State Bitmap");
01771 wBitmap->BMBytes = ((WinBitmap*)OILBitmap::Default)->BMBytes;
01772 delete OffscreenBitmap;
01773 }
01774 #endif
01775 
01776         // Show the temp bitmap to the user
01777         DisplayBits(pTempCapture->lpBitmapInfo, pTempCapture->lpBits);
01778 
01779         // Reset rendering back to normal
01780         SetRenderToCapture(GetTopCaptureBitmap());
01781 
01782         // Release the temp bitmap and delete the temp capture
01783         pTempCapture->FreeDIB();
01784         delete pTempCapture;
01785         pTempCapture = NULL;
01786     }
01787     else
01788     {
01789         // Failed to craete temp bitmap
01790         // So just blit what we can...
01791         DisplayBits();
01792     }
01793 }
01794                 
01795                 
01796                 
01797 /********************************************************************************************
01798 
01799 >   virtual void GRenderRegion::SetClean(BOOL bResetChangedBounds, BOOL FillWhite)
01800 
01801     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01802     Created:    28/06/94
01803     Purpose:    Informs the GRenderRegion that it should consider it's bitmap image to
01804                 be clean, i.e. it's an accurate representation of what is on screen
01805                 already, so there is no need to blit it.
01806                 This is used in conjunction with the PaperRenderRegion to avoid
01807                 unnecessary blits.
01808     SeeAlso:    RenderRegion::SetClean; PaperRenderRegion
01809 
01810 ********************************************************************************************/
01811 
01812 void GRenderRegion::SetClean(BOOL bResetChangedBounds, BOOL FillWhite)
01813 {
01814     // Reset our rendering flag...
01815     HaveRenderedSomething = FALSE;
01816     if (bResetChangedBounds)
01817         GetDrawContext()->ClearChangedBBox();
01818 }
01819 
01820 
01821 
01822 /********************************************************************************************
01823 
01824 >   void GRenderRegion::SetImmediateRender(BOOL SetVal)
01825 
01826     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
01827     Created:    13/10/99
01828     Inputs:     Value to set
01829     Outputs:    -
01830     Returns:    -
01831     Purpose:    sets the immediate render flag to the value specified
01832 ********************************************************************************************/
01833 // Moved to header file so that it is inlined automatically
01834 //void GRenderRegion::SetImmediateRender(BOOL SetVal)
01835 //{
01836 //  RenderFlags.bImmediateRender = SetVal;
01837 //}
01838 
01839 
01840 
01841 /********************************************************************************************
01842 
01843 >   BOOL GRenderRegion::StrokePath( const DocCoord *Coords, const PathVerb *Verbs, 
01844                                     UINT32 Count, BOOL DrawArrows = FALSE )
01845 
01846     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
01847     Created:    13/4/94
01848     Inputs:     Coords: list of points to draw
01849                 Verbs: list of path verbs
01850                 Count: number of point
01851                 DrawArrows: whether or not it should attempt to draw arrows on open
01852                             subpaths.
01853     Outputs:    -
01854     Returns:    TRUE if worked, FALSE if failed.
01855     Purpose:    Sits on top of GDraw_StrokePath that calculates Joins, Caps & Width then
01856                 renders via GDraw.
01857                 Does dashed lines too now.
01858                 Also renders ArrowHeads in needed.
01859     Errors:     -
01860     Scope:      Private
01861 
01862 ********************************************************************************************/
01863 
01864 BOOL GRenderRegion::StrokePath( const DocCoord *Coords, const PathVerb *Verbs, UINT32 Count,
01865                                 const DocCoord *UnclippedCoords, const PathVerb *UnclippedVerbs, 
01866                                 UINT32 UnclippedCount,
01867                                 BOOL DrawArrows )
01868 {
01869     CapStyles Caps;
01870     JoinStyles Join;
01871 
01872     switch (RR_STARTCAP())
01873     {
01874         case LineCapRound:
01875             Caps = CAPS_ROUND;
01876             break;
01877         case LineCapSquare:
01878             Caps = CAPS_SQUARE;
01879             break;
01880         case LineCapButt:
01881             Caps = CAPS_BUTT;
01882             break;
01883         default:
01884             ENSURE(FALSE, "Bad startcap");
01885             Caps = CAPS_ROUND;
01886             break;
01887     }
01888     switch (RR_JOINTYPE())
01889     {
01890         case BevelledJoin:
01891             Join = JOIN_BEVEL;
01892             break;
01893         case MitreJoin:
01894             Join = JOIN_MITER;
01895             break;
01896         case RoundJoin:
01897             Join = JOIN_ROUND;
01898             break;
01899         default:
01900             ENSURE(FALSE, "bad jointype");
01901             Join = JOIN_ROUND;
01902             break;
01903     }
01904 
01905     BOOL StrokeOK = TRUE;
01906 
01907     // DMc updates so that arrow heads are drawn on the line not after it
01908     // 25/2/99
01909     // make a copy of the coord array
01910     DocCoord * pCopyCoords = NULL;
01911     if (UnclippedCount != 0)
01912     {
01913         pCopyCoords = (DocCoord *)(CCMalloc(sizeof(DocCoord) * UnclippedCount));
01914 
01915         for (UINT32 i = 0; i < UnclippedCount; i++)
01916         {
01917             pCopyCoords[i].x = UnclippedCoords[i].x;
01918             pCopyCoords[i].y = UnclippedCoords[i].y;
01919         }
01920     }
01921 
01922     BOOL bRenderedArrows = FALSE;
01923 
01924     // DMc update for arrow heads being drawn on the line not after it
01925     // 25/2/99
01926     // Pass the Unclipped coords to the arrow rendering routine.
01927     if (DrawArrows && pCopyCoords)
01928     {
01929         bRenderedArrows = DrawPathArrowHeads((DocCoord*)pCopyCoords, (PathVerb*)UnclippedVerbs, UnclippedCount);
01930     }
01931 
01932     // We won't stroke anything, if the path has been
01933     // fuzzy clipped so much, that there are no points left
01934     if (Count > 1 && pCopyCoords)
01935     {
01936         MILLIPOINT Width = RR_LINEWIDTH();
01937 
01938         if (RenderFlags.HitDetect)
01939         {
01940             // rendering to off-screen bitmaps means minimum 3-pixel wide lines
01941             if (Width < (ScaledPixelWidth*1))
01942                 Width = ScaledPixelWidth*1;
01943         }
01944         else if (RRQuality.GetQuality() == Quality::QualityGuideLayer)
01945         {
01946             SetDashPattern(SD_DASH1);
01947             DocColour* pCol = AttrQuality::GetColour();
01948             if (pCol != NULL)
01949                 SetGCol(*pCol);             
01950             else
01951             {
01952                 DocColour   colorRed(COLOUR_RED);
01953                 SetGCol( colorRed );
01954             }
01955             
01956             Width = ScaledPixelWidth;
01957             DrawArrows = FALSE;
01958         }
01959         else if (RRQuality.GetLineQuality() < Quality::FullLine)
01960         {
01961             // do 0-width lines if line quality is low
01962             Width = 0;
01963             DrawArrows = FALSE;
01964         }
01965         else if (RRQuality.GetAntialiasQuality() < Quality::FullAntialias)
01966         {
01967             // if not anti-aliasing then check for lines thinner than one pixel as Gavin doesn't
01968             // render them very usefully
01969             if (Width < ScaledPixelWidth)
01970                 Width = 0;
01971         }
01972 
01973         DashType* pDashRec = NULL;
01974         DashType GavinDash;
01975 
01976         if ( Width > 0 && 
01977             (RRQuality.GetLineQuality() >= Quality::FullLine) && 
01978              RR_DASHPATTERN().Elements > 0)
01979         {
01980             INT32 Length = RR_DASHPATTERN().Elements;
01981 
01982             // Gavin Dashes are Max of 8 elements
01983             if (Length > 8) Length = 8;
01984 
01985 
01986             // If the flag is set, then we need to scale the dash elements
01987             // according to the linewidth
01988             BOOL DoScale = RR_DASHPATTERN().ScaleWithLineWidth;
01989 
01990             FIXED16 Scale = DoScale ? (double(Width) / double(RR_DASHPATTERN().LineWidth)) : 1;
01991 
01992             GavinDash.Length = Length;
01993             GavinDash.Offset = LongMulFixed16(RR_DASHPATTERN().DashStart, Scale);
01994 
01995             for (INT32 el = 0; el < Length; el++)
01996             {
01997                 // Copy each element into the Gavin Dash, scaling as we go
01998                 GavinDash.Array[el] = LongMulFixed16(RR_DASHPATTERN().ElementData[el], Scale);
01999             }
02000 
02001             pDashRec = &GavinDash;
02002         }
02003 
02004         // DMc update 25/2/99
02005         // previously :
02006         // StrokeOK = GetDrawContext()->StrokePath( (POINT*)Coords, Verbs, Count, FALSE,
02007         //                      Width, Caps, Join, pDashRec );
02008 
02009         if (bRenderedArrows)
02010         {
02011             StrokeOK = GetDrawContext()->StrokePath( (POINT*)pCopyCoords, UnclippedVerbs, UnclippedCount, FALSE,
02012                                     Width, Caps, Join, pDashRec );
02013         }
02014         else
02015         {
02016             StrokeOK = GetDrawContext()->StrokePath( (POINT*)Coords, Verbs, Count, FALSE,
02017                                     Width, Caps, Join, pDashRec );
02018         }
02019     }
02020 
02021     if (pCopyCoords)
02022     {
02023         CCFree(pCopyCoords);
02024         pCopyCoords = NULL;
02025     }
02026 
02027     if (bRenderedArrows)
02028         return TRUE;
02029 
02030     return StrokeOK;
02031 }
02032 
02033 
02034 
02035 
02036 /********************************************************************************************
02037 
02038 >   void GRenderRegion::DrawPathToOutputDevice(Path* PathToDraw)
02039 
02040     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
02041     Created:    7/12/93
02042     Inputs:     PathToDraw is a pointer to a Path object to render
02043     Outputs:    -
02044     Returns:    -
02045     Purpose:    Renders a path object using gavins routines
02046     Errors:     -
02047     SeeAlso:    -
02048 
02049 ********************************************************************************************/
02050 
02051 void GRenderRegion::DrawPathToOutputDevice(Path* PathToDraw, PathShape)
02052 {
02053     // If we are not drawing complex shapes and this shape is, then return
02054 //  if ((!RenderComplexShapes) && (TestForComplexShape(&Caps)))
02055 //      return;
02056 
02057 //  TRACEUSER( "Gerry", _T("GRenderRegion::DrawPathToOutputDevice\n"));
02058 
02059     DWORD Style = 0;
02060     TranspGradTable TranspTable;
02061 
02062     // Something to render later
02063     DocCoord*   Coords;
02064     PathVerb*   Verbs;
02065     UINT32      NumCoords;
02066     DocCoord*   UnclippedCoords;
02067     PathVerb*   UnclippedVerbs;
02068     UINT32      UnclippedNumCoords;
02069 
02070     BOOL ShouldDeleteCoords = FALSE;
02071 
02072     // Keep the unclipped path coords for arrow rendering
02073     UnclippedCoords     = PathToDraw->GetCoordArray();
02074     UnclippedVerbs      = PathToDraw->GetVerbArray();
02075     UnclippedNumCoords  = PathToDraw->GetNumCoords();
02076 
02077     ClippedPathIsValid = TRUE;
02078 
02079     // setup the fuzzy clipping rects.
02080     SetupFuzzyClipRects();
02081 
02082     // try and clip the path before rendering it, for bigger zoom values
02083     if (TryToFuzzyClip(PathToDraw, &Coords, &Verbs, &NumCoords))
02084     {
02085         // This may have clipped out all the points (or left just a moveto),
02086         // and in this case, it may seem pointless to continue.
02087         // but we will carry on, so that ArrowHeads get a chance to render
02088         // using the unclipped path coords.  
02089         // This shouldn't be a problem, so long as anything that uses the clipped
02090         // coords, checks to make sure there are enough (more than 1).
02091 
02092         if (NumCoords < 2)
02093         {
02094             ClippedPathIsValid = FALSE;
02095 //          OutputDebugString("Clipped path is too small\n");
02096         }
02097         else
02098         {
02099 //          char Str[256];
02100 //          _stprintf(Str, "Path clipped. Count=%d, Coords@%x, Verbs@%x\n",NumCoords,Coords,Verbs);
02101 //          OutputDebugString(Str);
02102 /*
02103             for (INT32 i=0; i<(NumCoords-1); i++)
02104             {
02105                 if (Verbs[i] == PT_BEZIERTO)
02106                 {
02107                     if (Coords[i] == Coords[i+3])
02108                     {
02109                         ClippedPathIsValid = FALSE;
02110     //                  OutputDebugString("Clipped path zero length element, Ignoring it.\n");
02111                         NumCoords = 0;
02112                         break;              
02113                     }   
02114                     
02115                     i += 2;
02116                 }
02117                 else
02118                 {
02119                     if (Coords[i] == Coords[i+1])
02120                     {
02121                         ClippedPathIsValid = FALSE;
02122     //                  OutputDebugString("Clipped path zero length element, Ignoring it.\n");
02123                         NumCoords = 0;
02124                         break;              
02125                     }   
02126                 }
02127             }
02128 */
02129         }
02130 
02131         // Yes, we clipped the paths alright
02132         ShouldDeleteCoords = TRUE;
02133     }
02134     else
02135     {
02136         // No Clipping here matey
02137         Coords = PathToDraw->GetCoordArray();
02138         Verbs  = PathToDraw->GetVerbArray();
02139         NumCoords = PathToDraw->GetNumCoords();
02140     }
02141 
02142     enum Quality::Fill FillQuality = RRQuality.GetFillQuality();
02143 
02144     RememberMe("DrawPath");
02145     HaveRenderedSomething = TRUE;
02146 
02147     if ( PathToDraw->IsFilled )
02148     {
02149         BOOL ExtendedFill = FALSE;
02150         FillGeometryAttribute *pFillProvider 
02151             = (FillGeometryAttribute *) CurrentAttrs[ATTR_FILLGEOMETRY].pAttr;
02152 
02153         if ( 
02154             (pFillProvider->GetRuntimeClass() != CC_RUNTIME_CLASS(FlatFillAttribute)) &&
02155             (FillQuality >= Quality::Graduated) 
02156            )
02157             ExtendedFill = TRUE;
02158 
02159         if ( 
02160             (pFillProvider->GetRuntimeClass() == CC_RUNTIME_CLASS(BitmapFillAttribute)) &&
02161             (FillQuality >= Quality::Solid) 
02162            )
02163             ExtendedFill = TRUE;
02164 
02165         if ( 
02166             (pFillProvider->GetRuntimeClass() == CC_RUNTIME_CLASS(FractalFillAttribute)) &&
02167             (FillQuality >= Quality::Solid) 
02168            )
02169             ExtendedFill = TRUE;
02170 
02171         if (ExtendedFill)
02172         {
02173             // VeryMono forces non-extended fill
02174             if (RenderFlags.VeryMono)
02175             {
02176                 // Up until now, we always rendered everything solid black when
02177                 // in 'VeryMono' mode, but now we have 'masked' bitmaps, we
02178                 // need to render them (will all non-masked pixels plotted black)
02179                 if (pFillProvider->GetRuntimeClass() == CC_RUNTIME_CLASS(BitmapFillAttribute))
02180                 {
02181                     // Check for a masked bitmap ....
02182                     KernelBitmap* pBitmap = pFillProvider->GetBitmap();
02183                     INT32 Index = 0;
02184 
02185                     if (pBitmap && (pBitmap->GetTransparencyIndex(&Index) || pBitmap->GetBPP()>=32))
02186                     {
02187                         // It's a masked bitmap, so we'll need to plot all
02188                         // the non-masked pixels as black
02189                         if (!pFillProvider->RenderFill(this, PathToDraw))
02190                             ExtendedFill = FALSE;                           // fail safe
02191                     }
02192                     else
02193                     {
02194                         ExtendedFill = FALSE;   // Not a masked bitmap
02195                     }
02196                 }
02197                 else
02198                 {
02199                     ExtendedFill = FALSE;       // Not a bitmap at all
02200                 }
02201             }
02202             else if (!pFillProvider->RenderFill(this, PathToDraw))
02203             {
02204                 ExtendedFill = FALSE;                                       // fail safe
02205             }
02206         }
02207 
02208         if ( (!ExtendedFill) && 
02209              (FillQuality >= Quality::Solid)
02210            )
02211         {
02212             DocColour FlatColour = RR_FILLCOLOUR();
02213 
02214             if (RenderFlags.VeryMono && 
02215                 pFillProvider->GetRuntimeClass() == CC_RUNTIME_CLASS(BitmapFillAttribute))
02216             {
02217                 // Bitmap fills will return 'No Colour' as their flat colour,
02218                 // but for 'VeryMono' rendering they should be treated as black.
02219                 FlatColour = COLOUR_BLACK;
02220             }
02221 
02222             if (SetFillGCol(FlatColour))
02223             {
02224                 if (!RenderFlags.VeryMono && GetTransparencyFill(&TranspTable, &Style))
02225                 {
02226                     DocColour Col = RR_FILLCOLOUR();
02227                     COLORREF rgb = ConvertColourToTransScreenWord(CurrentColContext, &Col);
02228                     GetDrawContext()->SetTransparency(rgb, (TransparencyEnum)(Style>>8));
02229                 }
02230 
02231                 if (NumCoords > 1)
02232                 {
02233                     GetDrawContext()->FillPath( (POINT*)Coords, Verbs, NumCoords,
02234                                     (RR_WINDINGRULE()==EvenOddWinding) ? 0 : 1);
02235                 }
02236             }
02237         }
02238     }
02239 
02240     if ( PathToDraw->IsStroked )
02241     {
02242         // Should we try and draw some ArrowHeads ?
02243         BOOL DrawArrows = (RRQuality.GetLineQuality() >= Quality::FullLine) &&
02244                           !(RR_STARTARROW().IsNullArrow() && RR_ENDARROW().IsNullArrow()) &&
02245                           ArrowRec::DoesPathNeedArrowHeads(UnclippedCoords, UnclippedVerbs, UnclippedNumCoords);
02246 
02247         if ((FillQuality <= Quality::Bitmaps))
02248         {
02249             // Just do everything in black outlines...
02250             DocColour   colorBlk(COLOUR_BLACK);
02251             if ( SetGCol( colorBlk ) )
02252                 StrokePath( Coords, Verbs, NumCoords, 
02253                             UnclippedCoords, UnclippedVerbs, UnclippedNumCoords, DrawArrows );
02254         }
02255         else if (RenderFlags.VeryMono)
02256         {
02257             // Just do everything in black outlines...
02258             DocColour   colorBlk(COLOUR_BLACK);
02259             if ( !(RR_STROKECOLOUR().IsTransparent()) && SetGCol( colorBlk ) )
02260                 StrokePath( Coords, Verbs, NumCoords, 
02261                             UnclippedCoords, UnclippedVerbs, UnclippedNumCoords, DrawArrows );
02262         }
02263         else if ( SetGCol( RR_STROKECOLOUR() ) )
02264         {
02265                 StrokePath( Coords, Verbs, NumCoords, 
02266                             UnclippedCoords, UnclippedVerbs, UnclippedNumCoords, DrawArrows );
02267         }
02268     }
02269 
02270     // We drew a clipped path, so get rid of the extra clipped coords
02271     if (ShouldDeleteCoords)
02272     {
02273         delete Coords;
02274         delete Verbs;
02275     }
02276 }
02277 
02278 
02279 
02280 /********************************************************************************************
02281 
02282 >   virtual void GRenderRegion::SetClipRegion(ClipRegionAttribute* pClipAttr, BOOL Temp)
02283 
02284     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
02285     Created:    26 April 2000
02286 
02287     Inputs:     pClipAttr       the ClipRegionAttribute to set & push on the attr-stack.
02288                 Temp            whether the attr is temporary or not - ie if you created
02289                                 it on the heap, do you want it automatically deleted when
02290                                 it goes out of scope.
02291 
02292     Outputs:    The attribute stack gets this attr pushed onto it, and the current
02293                 clip region is set accordingly.
02294 
02295     Purpose:    Set the current ClipRegion for this RenderRegion.
02296                 pClipAttr contains a path, and all future rendering will occur *through*
02297                 that clipping path, after it is clipped to any pre-existing clipping region.
02298 
02299     See Also:   RestoreClipRegion(), ClipRegionAttribute.
02300 
02301 ********************************************************************************************/
02302 void GRenderRegion::SetClipRegion(ClipRegionAttribute* pClipAttr, BOOL Temp)
02303 {
02304     RenderRegion::SetClipRegion(pClipAttr, Temp);
02305     ApplyCurrentClipRegion();
02306 }
02307 
02308 
02309 
02310 /********************************************************************************************
02311 
02312 >   virtual void GRenderRegion::RestoreClipRegion(ClipRegionAttribute* pClipAttr, BOOL Temp)
02313 
02314     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
02315     Created:    26 April 2000
02316     Inputs:     pClipAttr       the ClipRegionAttribute to restore over the current
02317                                 attribute.
02318                 Temp            whether the attr is temporary or not - ie if you created
02319                                 it on the heap, do you want it automatically deleted when
02320                                 it goes out of scope.
02321 
02322     Outputs:    The attribute stack gets its top ClipRegionAttribute deleted & replaced
02323                 with this one, with the RR's future clipping-region set accordingly.
02324 
02325     Purpose:    Set the current ClipRegion for this RenderRegion.
02326                 pClipAttr contains a path, and all future rendering will occur *through*
02327                 that clipping path, after it is clipped to any pre-existing clipping region.
02328 
02329     See Also:   SetClipRegion(), ClipRegionAttribute.
02330 
02331 ********************************************************************************************/
02332 void GRenderRegion::RestoreClipRegion(ClipRegionAttribute* pClipAttr, BOOL Temp)
02333 {
02334     // Karim 26/02/2001
02335     // Once a clip-region has been restored, we no longer need to cache its associated
02336     // clipping region, so we'll free it up here.
02337     // We only freeing up the old clip-region if the incoming attr is different
02338     // from the outgoing attr, and if we can successfully remove old clip-region
02339     // from our cache.
02340 
02341 //  REGION*                 pClipRegion         = NULL;
02342     ClipRegionAttribute*    pOutGoingClipAttr   = RR_CLIPREGION();
02343     ClipRegionAttribute*    pInComingClipAttr   = NULL;
02344 
02345     // Actually restore the incoming over the outgoing attribute in our attr-context.
02346     RenderRegion::RestoreClipRegion(pClipAttr, Temp);
02347 
02348     // Free up outgoing clip-region, now it's unneeded.
02349     pInComingClipAttr = RR_CLIPREGION();
02350     if (pInComingClipAttr != pOutGoingClipAttr &&
02351         pOutGoingClipAttr != NULL)
02352     {
02353 //      if (m_ClipRegionMap.Lookup((void*)pOutGoingClipAttr, ((void*&)pClipRegion)))
02354 //      {
02355 //          if (m_ClipRegionMap.RemoveKey((void*)pOutGoingClipAttr))
02356 //          {
02357 //              if (pClipRegion != NULL)
02358 //                  delete [] ((BYTE *)pClipRegion);
02359 //          }
02360 //      }
02361         // Normally GetTopCaptureBitmap must return a valid pointer
02362         // However RestoreClipRegion can be called when RenderRegions are being shut down
02363         Capture* pBitCapture = GetTopCaptureBitmap();
02364         if (pBitCapture)
02365             pBitCapture->RemoveCachedClipRegion(pOutGoingClipAttr);
02366     }
02367 
02368     // Finally, adopt the new clip-attr as our clipping region.
02369     ApplyCurrentClipRegion();
02370 }
02371 
02372 
02373 
02374 /********************************************************************************************
02375 
02376 >   BOOL GRenderRegion::ApplyCurrentClipRegion() const
02377 
02378     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
02379     Created:    14 April 2000
02380     Inputs:     
02381     Outputs:    GDraw should have its clipping region and rectangle set so that rendering
02382                 only occurs within a region specified by the clipping path which the current
02383                 ClipRegionAttribute is carrying.
02384     Returns:    TRUE if successful,
02385                 FALSE otherwise.
02386     Purpose:    Have a look at the current ClipRegionAttribute and make sure
02387                 we set our clipping region accordingly. Details within the method.
02388     Errors:     ERROR3 in DEBUG if we have no valid ptr to a ClipRegionAttribute.
02389     See also:   
02390 
02391 ********************************************************************************************/
02392 BOOL GRenderRegion::ApplyCurrentClipRegion()
02393 {
02394 //  return TRUE;
02395 
02396     // note that we don't bother with any clipping unless we're actually doing something
02397     // useful, eg rendering.
02398     if (!RenderFlags.Rendering)
02399         return FALSE;
02400 
02401     // This is what we do...
02402     //
02403     //  1.  We keep a hash table containing clip regions, with an entry for each unique
02404     //      ClipRegionAttribute, so that we do the time-consuming (I assume!) make-region
02405     //      work as little as possible.
02406     //  2.  If we haven't seen a ClipRegionAttribute before, then we make a region from/for
02407     //      it and stick the association in the table for future look-up
02408     //  3.  We apply the clip region appropriate to the current attribute.
02409     //  4.  We do all the above for device clip rectangles too, which need to be re-applied
02410     //      whenever a new clip region is applied.
02411 
02412     // remember the current clip region, or make a new one for the current clipattr.
02413     BOOL            fSuccess    = FALSE;
02414     const REGION*   pClipRegion = NULL;
02415     ClipRegionAttribute* pClipAttr = RR_CLIPREGION();
02416 
02417     ERROR3IF(pClipAttr == NULL, "Doh! NULL ClipRegionAttribute in render region!");
02418 
02419     // if we don't have a clip-region, do a DeviceClipRectangle() with an 'infinite' rect.
02420     // this will reset GDraw's clip-rectangle to the size of its bitmap, and also
02421     // reset its clip-region to empty.
02422     if (pClipAttr->GetClipPath() == NULL)
02423     {
02424         RECT BigRect;
02425         BigRect.bottom  = BigRect.left  = INT32_MIN;
02426         BigRect.top     = BigRect.right = INT32_MAX;
02427         fSuccess = GetDrawContext()->DeviceClipRectangle(&BigRect);
02428     }
02429 
02430     // try to look up a clip-region for this clip-attr; failing that, create a new one
02431     // and store it.
02432     else
02433     {
02434 //      if (!m_ClipRegionMap.Lookup((void*)pClipAttr, ((void*&)pClipRegion)))
02435 //      {
02436 //          pClipRegion = MakeClipRegionFromClipAttr(pClipAttr);
02437 //          m_ClipRegionMap.SetAt((void*)pClipAttr, ((void*&)pClipRegion));
02438 //      }
02439         pClipRegion = GetTopCaptureBitmap()->GetCachedClipRegion(pClipAttr);
02440         if (pClipRegion==NULL)
02441         {
02442             pClipRegion = MakeClipRegionFromClipAttr(pClipAttr);
02443             GetTopCaptureBitmap()->SetCachedClipRegion(pClipAttr, pClipRegion);
02444         }
02445 
02446         fSuccess = GetDrawContext()->ClipRegion(pClipRegion);
02447     }
02448 
02449     return fSuccess;
02450 }
02451 
02452 
02453 
02454 /********************************************************************************************
02455 
02456 >   BOOL GRenderRegion::RenderGradFillPath(Path *PathToDraw, GradFillAttribute *Fill )
02457 
02458     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
02459     Created:    30/3/94
02460     Inputs:     PathToDraw is a pointer to a Path object to render. Fill is the grad fill
02461                 required.
02462     Outputs:    -
02463     Returns:    TRUE if understood fill type & rendered it, FALSE if not
02464     Purpose:    Fills a grad filled path (linear or radial)
02465     Errors:     -
02466 
02467     Notes:      Added support for square, 3 and 4 colour fills (Gerry 12/8/96)
02468 
02469 ********************************************************************************************/
02470 
02471 BOOL GRenderRegion::RenderGradFillPath(Path *PathToDraw, GradFillAttribute *Fill)
02472 {
02473     DWORD Style = 0;
02474     TranspGradTable TranspTable;
02475 
02476     BOOL SpecialFill = FALSE;
02477 
02478     CCRuntimeClass *FillType = Fill->GetRuntimeClass();
02479 
02480 
02481     if (FillType == CC_RUNTIME_CLASS(RadialFillAttribute))
02482         Style = 1;
02483     else if (FillType == CC_RUNTIME_CLASS(LinearFillAttribute))
02484         Style = 0;
02485     else if (FillType == CC_RUNTIME_CLASS(ConicalFillAttribute))
02486         Style = 2;
02487     else if (FillType == CC_RUNTIME_CLASS(SquareFillAttribute))
02488         Style = 3;
02489     else if (FillType == CC_RUNTIME_CLASS(ThreeColFillAttribute))
02490         SpecialFill = TRUE;
02491     else if (FillType == CC_RUNTIME_CLASS(FourColFillAttribute))
02492         SpecialFill = TRUE;
02493     else
02494     {
02495         ERROR3("Unknown fill type");
02496         return FALSE;                               // unknown fill type
02497     }
02498 
02499     if (uBitmapDepth == 32)
02500     {
02501         // InitTransparencyFill will setup the transparency fill if there is one
02502         if (!GetTransparencyFill(&TranspTable, &Style))
02503             Style |= (WhichTransparency<<8);        // Set the fill type of the transparency
02504     }
02505 
02506     CProfileBiasGain DiagramMapper = Fill->GetProfile ();
02507 
02508     // --- Convert ArtWorks style attribute into Gavin-style
02509     POINT A,B,C,D;
02510 
02511     DocCoord* StartPoint    = Fill->GetStartPoint();
02512     DocCoord* EndPoint      = Fill->GetEndPoint();
02513     DocCoord* EndPoint2     = Fill->GetEndPoint2();
02514     DocCoord* EndPoint3     = Fill->GetEndPoint3();
02515 
02516     A.x = (*StartPoint).x;  A.y = (*StartPoint).y;
02517     B.x = (*EndPoint).x;    B.y = (*EndPoint).y;
02518 
02519     if (EndPoint2 != NULL)
02520     {
02521         C.x = (*EndPoint2).x;   
02522         C.y = (*EndPoint2).y;
02523     }
02524 
02525     if (FillType==CC_RUNTIME_CLASS(LinearFillAttribute))
02526     {
02527         A.x = (*StartPoint).x;  A.y = (*StartPoint).y;
02528         B.x = (*EndPoint2).x;   B.y = (*EndPoint2).y;
02529         C.x = (*EndPoint).x;    C.y = (*EndPoint).y;
02530     }
02531     else if (FillType==CC_RUNTIME_CLASS(ConicalFillAttribute))
02532     {
02533         B.x = A.x - (B.x - A.x);
02534         B.y = A.y - (B.y - A.y);
02535     }
02536 
02537     BOOL Perspective = FALSE;
02538 
02539     // Is it a perspectivised fill ?
02540     if (Fill->IsPerspective())
02541     {
02542         Perspective = TRUE;
02543 
02544         POINT PGram[4];
02545 
02546         // Setup the Perspective control points
02547         if (FillType==CC_RUNTIME_CLASS(LinearFillAttribute))
02548         {
02549             PGram[0].x = (*StartPoint).x;   PGram[0].y = (*StartPoint).y;
02550             PGram[1].x = (*EndPoint2).x;    PGram[1].y = (*EndPoint2).y;
02551             PGram[2].x = (*EndPoint3).x;    PGram[2].y = (*EndPoint3).y;
02552             PGram[3].x = (*EndPoint).x;     PGram[3].y = (*EndPoint).y;
02553         }
02554         else
02555         {
02556             PGram[0].x = A.x;               PGram[0].y = A.y;
02557             PGram[1].x = B.x;               PGram[1].y = B.y;
02558             PGram[2].x = (*EndPoint3).x;    PGram[2].y = (*EndPoint3).y;
02559             PGram[3].x = (*EndPoint2).x;    PGram[3].y = (*EndPoint2).y;
02560         }
02561 
02562         // Are the control points sensible ?
02563 
02564         // Gerry removed the pixel size test cos it makes small repeating fills go spappy
02565         
02566         if (MouldPerspective::WillBeValid(PGram))
02567         {
02568             // We're going to plot a perspective fill,
02569             // so copy the perspective control points
02570             A.x = PGram[0].x;   A.y = PGram[0].y;
02571             B.x = PGram[1].x;   B.y = PGram[1].y;
02572             C.x = PGram[2].x;   C.y = PGram[2].y;
02573             D.x = PGram[3].x;   D.y = PGram[3].y;
02574         }
02575         else
02576         {
02577             // The mould is bad...
02578             Perspective = FALSE;
02579         }
02580     }
02581 
02582     // This needs to be allocated at the same level as the FillPath call below...
02583     GradTable Table(FALSE);
02584 
02585     INT32 Tiling = ((FillMappingAttribute*)CurrentAttrs[ATTR_FILLMAPPING].pAttr)->Repeat;
02586 
02587     if (SpecialFill)
02588     {
02589         // The fill is a fabby new one
02590 
02591         if ((FillType != CC_RUNTIME_CLASS(ThreeColFillAttribute)) &&
02592             (FillType != CC_RUNTIME_CLASS(FourColFillAttribute)))
02593         {
02594             ERROR3("Unknown new fill type");
02595             return FALSE;                               // unknown fill type
02596         }
02597 
02598         // Clear the bottom byte of the style cos it means something new
02599         Style = Style & 0xFFFFFF00;
02600 
02601         // If the transparency type is one of the unimplemented ones then set to zero
02602         if ((Style & 0xFF00) < 0x400)
02603             Style = (Style & 0xFF0000);
02604         
02605         // We wont do anything scary with the colours (separation/correction)
02606         // as this only renders to a GDraw bitmap
02607 
02608         PColourRGBT Result;
02609 
02610         CurrentColContext->ConvertColour(Fill->GetStartColour(), (ColourPacked *) &Result);
02611         COLORREF StartColour = RGB(Result.Red, Result.Green, Result.Blue);
02612 
02613         CurrentColContext->ConvertColour(Fill->GetEndColour(), (ColourPacked *) &Result);
02614         COLORREF EndColour = RGB(Result.Red, Result.Green, Result.Blue);
02615 
02616         CurrentColContext->ConvertColour(Fill->GetEndColour2(), (ColourPacked *) &Result);
02617         COLORREF EndColour2 = RGB(Result.Red, Result.Green, Result.Blue);
02618 
02619         if (FillType == CC_RUNTIME_CLASS(FourColFillAttribute))
02620             CurrentColContext->ConvertColour(Fill->GetEndColour3(), (ColourPacked *) &Result);
02621         COLORREF EndColour3 = RGB(Result.Red, Result.Green, Result.Blue);
02622 
02623         /*CProfileBiasGain DefaultBiasGain;
02624 
02625         if (!(DiagramMapper == DefaultBiasGain))
02626         {
02627             Table.BuildTable(Fill->Colour, Fill->EndColour, GetRenderView(), GetFillEffect(), DiagramMapper, LargeGradTables);
02628             GetDrawContext()->SetGraduation( Style, Table.GetTable(), &A, &B, &C );
02629         }*/
02630 
02631         if (FillType == CC_RUNTIME_CLASS(ThreeColFillAttribute))
02632         {           
02633             // Style & 0xFF = 0 (simple with better colours outside the mesh)
02634             // Style & 0xFF = 2 (tiled)
02635 
02636             if (Tiling == 1)    // If it is a simple fill
02637                 Style |= 0;     // set the style to 0
02638             else
02639                 Style |= 2;     // otherwise set it to 2
02640 
02641             //CProfileBiasGain DefaultBiasGain;         // default
02642                                                         // DiagramMapper is the applied biasgain
02643 
02644             //if (DiagramMapper == DefaultBiasGain)     // if the applied biasgain is the default biasgain
02645             //{
02646                 if (Perspective)
02647                     GetDrawContext()->Set3WayGraduation4(Style, StartColour, EndColour, EndColour2,
02648                                             &A, &B, &C, &D);
02649                 else
02650                     GetDrawContext()->Set3WayGraduation(Style, StartColour, EndColour, EndColour2,
02651                                             &A, &B, &C);
02652             //}
02653             //else
02654             //{
02655             //  Table.BuildTable(Fill->Colour, Fill->EndColour, GetRenderView(), GetFillEffect(), DiagramMapper, LargeGradTables);
02656             //  GetDrawContext()->Set3WayGraduation(Style, StartColour, EndColour, EndColour2,
02657 //                                          &A, &B, &C);
02658             //}
02659         }
02660         else
02661         {
02662             // Style & 0xFF = 1 (for better colours outside the mesh)
02663             // Style & 0xFF = 2 (tiled)
02664 
02665             if (Tiling == 1)    // If it is a simple fill
02666                 Style |= 1;     // set the style to 1
02667             else
02668                 Style |= 2;     // otherwise set it to 2
02669 
02670             // The colours in the following lines are correct!!!
02671             if (Perspective)
02672                 GetDrawContext()->Set4WayGraduation4(Style, StartColour, EndColour, EndColour3, EndColour2,
02673                                         &A, &B, &C, &D);
02674             else
02675                 GetDrawContext()->Set4WayGraduation(Style, StartColour, EndColour, EndColour3, EndColour2,
02676                                         &A, &B, &C);
02677         }
02678     }
02679     else
02680     {
02681 // Mark Howitt, 6/10/97. Enable the repeating fill type operation if selected
02682 #ifdef NEW_FEATURES
02683         if(Tiling == 4) Style |= 0x80;      // Check to see if repeating, if so set it
02684 #endif
02685 
02686         // CGS ....
02687         // We now need to decide exactly who is going to build the table!
02688         // If the fill has the default biasgain, then we will continue to build
02689         // this in the standard fashion (i.e.  let GDraw build it).
02690         // If however it does NOT, then we will build the table ourselves (with respect to
02691         // the applied biasgain) ....
02692         
02693         CProfileBiasGain DefaultBiasGain;           // default
02694                                                     // DiagramMapper is the applied biasgain
02695 
02696         if (DiagramMapper == DefaultBiasGain)       // if the applied biasgain is the default biasgain
02697         {
02698             // get on and use standard rendering stuff ....
02699 
02700             ColourRamp *pColourRamp = Fill->GetColourRamp();
02701             if (pColourRamp)
02702             {
02703                 if (Tiling != 4)
02704                 {
02705                     Table.BuildTable(Fill->Colour, Fill->EndColour, pColourRamp, GetRenderView(), GetFillEffect(), LargeGradTables);
02706                 }
02707                 else
02708                 {
02709                     Table.BuildHighQualityRepeatTable(Fill->Colour, Fill->EndColour, pColourRamp, GetRenderView(), GetFillEffect());
02710                 }
02711             }
02712             else
02713             {
02714                 if (Tiling != 4)
02715                 {
02716                     Table.BuildTable(Fill->Colour, Fill->EndColour, GetRenderView(), GetFillEffect(), LargeGradTables);
02717                 }
02718                 else
02719                 {
02720                     Table.BuildHighQualityRepeatTable(Fill->Colour, Fill->EndColour, NULL, GetRenderView(), GetFillEffect());
02721                 }
02722             }
02723 
02724             if (Perspective)
02725                 GetDrawContext()->SetGraduation4( Style, Table.GetTable(), &A, &B, &C, &D );
02726             else
02727                 GetDrawContext()->SetGraduation( Style, Table.GetTable(), &A, &B, &C );
02728         }
02729         else
02730         {
02731             // use our new rendering stuff that takes account of profiles ....
02732 
02733             if (Tiling != 4)
02734             {
02735                 Table.BuildTable(Fill->Colour, Fill->EndColour, GetRenderView(), GetFillEffect(), DiagramMapper, LargeGradTables);
02736                 GetDrawContext()->SetGraduation( Style, Table.GetTable(), &A, &B, &C );
02737             }
02738             else
02739             {
02740                 Table.BuildHighQualityRepeatTable(Fill->Colour, Fill->EndColour, GetRenderView(), GetFillEffect(), DiagramMapper);
02741                 GetDrawContext()->SetGraduation( Style, Table.GetTable(), &A, &B, &C );
02742             }
02743             GetDrawContext()->SetGraduation( Style, Table.GetTable(), &A, &B, &C );
02744         }
02745     }
02746 
02747     // Now it is time to Draw the path, so we will Fuzzy Clip it just in case it is too big
02748     DocCoord* Coords;
02749     PathVerb* Verbs;
02750     UINT32 TotalCoords;
02751     BOOL ShouldDeleteCoords = FALSE;
02752 
02753     // try and clip the path before rendering it, for bigger zoom values
02754     if (TryToFuzzyClip(PathToDraw, &Coords, &Verbs, &TotalCoords))
02755     {
02756         // Yes, we clipped the paths alright
02757         ShouldDeleteCoords = TRUE;
02758     }
02759     else
02760     {
02761         // No Clipping here matey
02762         Coords = PathToDraw->GetCoordArray();
02763         Verbs  = PathToDraw->GetVerbArray();
02764         TotalCoords = PathToDraw->GetNumCoords();
02765     }
02766 
02767     // Draw the actual path
02768     if (TotalCoords > 1)
02769         GetDrawContext()->FillPath( (POINT*)Coords, Verbs, TotalCoords, (RR_WINDINGRULE()==EvenOddWinding) ? 0 : 1 );
02770 
02771     // Clean up if we need to
02772     if (ShouldDeleteCoords)
02773     {
02774         delete Coords;
02775         delete Verbs;
02776     }
02777 
02778     #if 0
02779     if (0)
02780     {
02781         // debug code - plot the points
02782         GetDrawContext()->SetColour( RGB(0,0,0) );
02783         /*DocCoord*/ POINT Path[5];
02784         BYTE Verbs[] = { PT_MOVETO, PT_LINETO, PT_MOVETO, PT_LINETO, PT_LINETO };
02785         /*DocCoord*/POINT D;
02786         D.x = (A.x+B.x)/2;
02787         D.y = (A.y+B.y)/2;
02788 
02789         Path[0] = A;
02790         Path[1] = B;
02791         Path[2] = A;
02792         Path[3] = C;
02793         Path[4] = D;
02794         GetDrawContext()->StrokePath( (LPPOINT)Path, Verbs, sizeof(Verbs), FALSE, 0, CAPS_ROUND, JOIN_ROUND, NULL );
02795     }
02796     #endif
02797     return TRUE;
02798 }
02799 
02800 
02801 
02802 
02804 //
02805 //                              Offscreen rendering system
02806 //
02808 
02809 INT32 PixelsPerMeterAtCurrentViewScale( FIXED16 Scale)
02810 {
02811     double  PixPerMetre =   PIXELS_PER_INCH * INCHES_PER_METRE;
02812             PixPerMetre *=  Scale.MakeDouble();
02813 
02814     return (INT32) (PixPerMetre + 0.5);
02815 }
02816 
02817 
02818 
02819 /********************************************************************************************
02820 >   virtual void GRenderRegion::SetOffscreen(OffscreenAttrValue* pAttr)
02821     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
02822     Created:    23/2/2000
02823     Inputs:     pAttr   the offscreen attribute (eg FeatherAttrValue) to use.
02824 
02825                 ** Following only used by GRenderRegion version **
02826                 info    pointer to bmp info struct which we will setup.
02827                 bits    pointer to bitmap bits which we'll setup.
02828 
02829     Purpose:    Create a new bitmap into which, the subtree rooted at this attributes parent,
02830                 will be rendered. Then call base version to push the current OffscreenAttr
02831                 onto the context stack.
02832 
02833     SeeAlso:    GRenderRegion::RestoreOffscreen; GRenderRegion::
02834 ********************************************************************************************/
02835 void GRenderRegion::SetOffscreen(OffscreenAttrValue* pAttr)
02836 {
02837     // Karim 23/07/2000
02838     // Mustn't have feathering overhead for hit-testing, so
02839     // don't bother doing anything if we're a hit-test RR.
02840     if (IsHitDetect())
02841         return;
02842 
02843     if (m_ForcePrintingCaps)
02844         return;
02845 
02846     // Save pointer to OffscreenAttr, and move current OffscreenAttr to the attr context stack
02847     RenderRegion::SetOffscreen(pAttr);
02848 }
02849 /*void GRenderRegion::SetOffscreen(OffscreenAttrValue* pAttr)
02850 {
02851 //  TRACEUSER( "Gerry", _T("GRenderRegion::SetOffscreen (0x%08x)\n"), pAttr);
02852 
02853     // Karim 23/07/2000
02854     // Mustn't have feathering overhead for hit-testing, so
02855     // don't bother doing anything if we're a hit-test RR.
02856     if (IsHitDetect())
02857         return;
02858 
02859     if (m_ForcePrintingCaps)
02860         return;
02861 
02862     // Karim 23/07/2000
02863     // Don't bother with feathering at all if our quality setting is too low.
02864     // Note: this test should probably be made in a Feather override of a Node vfn.
02865     if (RRQuality.GetFillQuality() < Quality::Graduated)
02866         return;
02867 
02868     //---------------------------------------------
02869     // Karim 20/07/2000
02870     // Moved from OffscreenAttrValue::Render(), to avoid checks for render-region types
02871     // in the feathering code.
02872     // The following code works out and sets the offscreen attr's
02873     // offscreen bounding box.
02874 
02875     // Invalid area = intersection of node's and render-region's bounding rects.
02876     //
02877     // Notes:   1.  Inflate the node's bounding rect slightly, so it _completely_
02878     //              encloses the node (sometimes it doesn't quite).
02879     //          2.  Inflate the RR's clip-rect slightly, so that we don't get
02880     //              anti-aliasing edge artifacts in the final feather-bmp render.
02881     //          3.  If printing, then use the GRR's inner rect instead of its clipping
02882     //              rect, to fix stripey printing of feathers.
02883     //              This BODGE is necessary because for some reason CurrentClipRect
02884     //              does not cover a GRR's whole bitmap when printing !?!?
02885     MILLIPOINT LargePixelWidth = (MILLIPOINT)ceil(GetScaledPixelWidthDouble());
02886     DocRect NodeBB  = pAttr->GetLinkedNode()->GetBoundingRect();
02887     NodeBB.Inflate( LargePixelWidth );
02888 
02889     DocRect GRegionBB = CurrentClipRect;
02890 // Removed by Phil 2/6/2004
02891 // Seems to be bogus...
02892 //      if (IsPrinting())
02893 //          GRegionBB = InnerRect;
02894 //      else
02895         GRegionBB.Inflate( 2 * LargePixelWidth );
02896 
02897     if (!NodeBB.IsIntersectedWith(GRegionBB))
02898         return;
02899 
02900     // calculate their intersection.
02901     DocRect drOffBB = NodeBB.Intersection(GRegionBB);
02902 
02903     // Ensure that we have minimum pixel dimensions
02904     // Expand cliprect if more pixels required
02905     // NB expanding by GRR->ScaledPixelWidth will ensure we increase bmp size 
02906     // by exactly the no. of pixels required
02907     UINT32 RequiredWidth, RequiredHeight;
02908     pAttr->GetMinimumOffscreenBmpDimensions(&RequiredWidth,&RequiredHeight);
02909     WinRect Rect = CalculateWinRect( drOffBB );
02910     UINT32 ProposedWidth    = Rect.right - Rect.left;
02911     UINT32 ProposedHeight   = Rect.bottom - Rect.top;
02912     MILLIPOINT ScaledPixelWidth = GetScaledPixelWidth();
02913 
02914     // We have to check if the render matrix involves rotation as we have to
02915     // expand the DocRect in the other direction
02916     // First get the components of the matrix
02917     FIXED16 comps[4];
02918     RenderMatrix.GetComponents(comps, NULL);
02919     // It is rotated if a = d = 0 and b = -c
02920     BOOL bRotated = (comps[0] == FIXED16(0) && comps[3] == FIXED16(0) && comps[1] == -comps[2]);
02921     if(ProposedWidth < (INT32)RequiredWidth)
02922     {
02923         // make the bitmap wider
02924         // For odd pixel differences, widen rightwards by extra pixel
02925         MILLIPOINT ExtraPixelWidth = (MILLIPOINT)(RequiredWidth - ProposedWidth);
02926         MILLIPOINT Decrement = (ExtraPixelWidth / 2) * ScaledPixelWidth;
02927         MILLIPOINT Increment = Decrement + ((ExtraPixelWidth % 2) * ScaledPixelWidth);
02928 
02929         // if there is a rotation involved we have to increase the height of the DocRect
02930         // otherwise we increase the width
02931         if (bRotated)
02932         {
02933             drOffBB.loy -= Decrement;
02934             drOffBB.hiy += Increment;
02935         }
02936         else
02937         {
02938             drOffBB.lox -= Decrement;
02939             drOffBB.hix += Increment;
02940         }
02941     }
02942 
02943     if (ProposedHeight < (INT32)RequiredHeight)
02944     {
02945         // make the bitmap taller
02946         // For odd pixel differences, stretch upwards by extra pixel
02947         MILLIPOINT ExtraPixelHeight = (MILLIPOINT)(RequiredHeight - ProposedHeight);
02948         MILLIPOINT Decrement = (ExtraPixelHeight / 2) * ScaledPixelWidth;
02949         MILLIPOINT Increment = Decrement + ((ExtraPixelHeight % 2) * ScaledPixelWidth);
02950 
02951         // if there is a rotation involved we have to increase the width of the DocRect
02952         // otherwise we increase the height
02953         if (bRotated)
02954         {
02955             drOffBB.lox -= Decrement;
02956             drOffBB.hix += Increment;
02957         }
02958         else
02959         {
02960             drOffBB.loy -= Decrement;
02961             drOffBB.hiy += Increment;
02962         }
02963     }
02964 
02965     pAttr->SetOffscreenBoundingRect(drOffBB);
02966 
02967     //---------------------------------------------
02968     // Now startup the offscreen capture...
02969     // 
02970     // If a non-mix attribute is already in scope we must not start capturing transparently
02971     // because transparent bitmaps can't render non-mix transparencies correctly
02972     // (See SetTranspFillGeometry and ChangeCapture)
02973     //
02974     TranspFillAttribute* pTransAttr = (TranspFillAttribute *) GetCurrentAttribute(ATTR_TRANSPFILLGEOMETRY);
02975     UINT32 ttype = pTransAttr->GetTranspType();
02976     BOOL bStartTransparently = (ttype==TT_NoTranspType || ttype==TT_Mix);
02977 
02978     // Also, scan down into the tree and see whether this node has any non-mix that would
02979     // cause us to revert to non-transparent capture
02980     // Because it's (probably) quicker to scan the tree than to revert during rendering...
02981     // Urgh.
02982     NodeRenderableInk* pLinkedNode = pAttr->GetLinkedNode()->IsAnObject() ? (NodeRenderableInk*)pAttr->GetLinkedNode() : NULL;
02983     bStartTransparently = bStartTransparently && !(pLinkedNode && pLinkedNode->ContainsNonMixTransparency(this));
02984 
02985     BOOL bOK = StartCapture(pAttr,
02986                             drOffBB,
02987                             CAPTUREINFO(ctNESTABLE, cfNONE + cfDEBUG),      // Don't allow collapse to master bitmap, CollapseToMaster=0
02988                             bStartTransparently,
02989                             !bStartTransparently
02990                             );
02991     if (!bOK)
02992         return;
02993 
02994     // Save pointer to OffscreenAttr, and move current OffscreenAttr to the attr context stack
02995     RenderRegion::SetOffscreen(pAttr);
02996 }*/
02997 
02998 
02999 
03000 /*
03001     GRenderRegions can be deleted or reset midway through rendering offscreen
03002 
03003     Requirement: ensure all bitmap memory is freed, as well as cleaning up the offscreen state stack
03004 
03005     Problems:   1) Initial bitmap memory needs to be freed by the class that allocated it
03006                 2) GRenderRegion bmp pointers may be pointing to offscreen bitmap memory when
03007                    the classes deconstructor is called
03008                 3) FreeLPBits is a pure virtual function so can't be called from ~GRenderRegion
03009                 4) Normally stack memory freed by GRenderRegion::RestoreOffscreen()
03010                    and bitmap memory freed by OffscreenAttrValue::GoingOutOfScope
03011                    as RenderRegion attribute stack is pushed and popped (ie as attributes
03012                    render and go out of scope)
03013                 5) On deconstruction, attributes can only call the RenderRegion 'Restore-" virtual
03014                    functions, not the GRenderRegion overrides.
03015 
03016     Solution:
03017                 1) BmpMemory and offscreen stack memory must be freed in one go (GRenderRegion::FreeOffscreenState())
03018                 2) This must be called from the deconstructor of the derived render region which is
03019                    being deleted
03020                 OR
03021                    the ResetRegion function
03022                 3) The attributes must be notified that their offscreen bitmap pointers are invalid
03023                    and must not attempt to do anything with that memory
03024                 4) The GRenderRegion stack freeing function (GRenderRegion::RestoreOffscreen())
03025                    must check to see if the stack is empty and default to RenderRegion::RestoreOffscreen()
03026                    if it is
03027 
03028 
03029     // pAttr is the offscreen attribute which is going to be restored.
03030 
03031 */
03032 
03033 void GRenderRegion::RestoreOffscreen(OffscreenAttrValue* pAttr)
03034 {
03035     if (m_ForcePrintingCaps)
03036         return;
03037 
03038     // call our base class, to update the offscreen attr stack.
03039     // this will also trigger a call to the current attr's OffscreenRenderingCompleted() method.
03040     RenderRegion::RestoreOffscreen(pAttr);
03041 }
03042 /*void GRenderRegion::RestoreOffscreen(OffscreenAttrValue* pAttr)
03043 {
03044     if (m_ForcePrintingCaps)
03045         return;
03046 
03047     // End this capture:
03048     // Don't render captured bitmap back into render region - owner will do that after processing
03049     // Release bitmap here - if this region is being reset
03050     LPBITMAPINFO lpCapturedBitmapInfo = NULL;
03051     LPBYTE lpCapturedBits = NULL;
03052     DocRect CaptureRect = CurrentOffscreenAttr->GetOffscreenBoundingRect(); // Initialise to size of feathered object
03053                                                             // so that StopCapture can return sensible 24BPP bitmap if needed
03054     Capture* pTopCapture = GetTopCapture();
03055     ENSURE(pTopCapture && pTopCapture->GetOwner()==CurrentOffscreenAttr, "RestoreOffscreen attr is not owned by top capture\n");
03056     if (pTopCapture && pTopCapture->GetOwner()==CurrentOffscreenAttr)
03057     {
03058         StopCapture(CurrentOffscreenAttr, FALSE, IsBeingReset, &lpCapturedBitmapInfo, &lpCapturedBits, &CaptureRect);
03059     }
03060 
03061     if (!IsBeingReset)
03062     {
03063         // Normal restore in process of traversing the tree
03064         // So tell the offscreen attribute to handle the captured bitmap as it sees fit...
03065         CurrentOffscreenAttr->OffscreenRenderingCompleted(this, lpCapturedBitmapInfo, lpCapturedBits, CaptureRect);
03066     }
03067 
03068     // call our base class, to update the offscreen attr stack.
03069     // this will also trigger a call to the current attr's OffscreenRenderingCompleted() method.
03070     RenderRegion::RestoreOffscreen(pAttr);
03071 }*/
03072 
03073 
03074 // This function is used by OffscreenAttrValue::GoingOutOfScope to render a bitmap
03075 // with its convolution applied as a transparency.
03076 // If we run out of memory we will be unable to allocate memory to create the
03077 // bitmap mask so this function handles a NULL BitmapTranspFillAttribute as input.
03078 BOOL GRenderRegion::RenderBitmapWithTransparency(
03079                                                  Path *pPath,
03080                                                  BitmapFillAttribute* pFill,
03081                                                  BitmapTranspFillAttribute* pTranspFill
03082                                                 )
03083 {
03084 /*
03085  *  Karim 08/11/2000
03086  *  This commented out code does the job using more abstract instructions.
03087  *
03088     ERROR2IF(pFill == NULL || pPath == NULL, FALSE,
03089             "GRenderRegion::RenderBitmapWithTransparency; NULL input params!");
03090 
03091     AttrTranspFillMappingLinear TranspFillMapping;
03092     AttrFillMappingLinear       FillMapping;
03093 
03094     SaveContext();
03095 
03096     SetLineColour(COLOUR_NONE);
03097 
03098     FillMapping.Value.Repeat = 1;
03099     FillMapping.Render(this);
03100 
03101     pFill->Render(this);
03102 
03103     if (pTranspFill != NULL)
03104     {
03105         TranspFillMapping.Value.Repeat = 1;
03106         TranspFillMapping.Render(this);
03107 
03108         pTranspFill->Render(this);
03109     }
03110 
03111     DrawPath(pPath);
03112 
03113     RestoreContext();
03114 
03115     return TRUE;
03116 */
03117 
03118 
03119     // Store a ptr to the current fill-mapping attr, replacing it with a single-tile mapping.
03120     FillMappingAttribute* pCurrentFillMapAttr = (FillMappingAttribute*)CurrentAttrs[ATTR_FILLMAPPING].pAttr;
03121 
03122     FillMappingAttribute FillMap;
03123     FillMap.Repeat = 1;
03124 
03125     CurrentAttrs[ATTR_FILLMAPPING].pAttr = (AttributeValue*)&FillMap;
03126 
03127 
03129     // Transparency fill:-
03130     // 1) store existing current transp attributes (so that they can be restored afterwards)
03131     // 2) create required transp fill mapping
03132     // 3) set current transp attrs to the new transparency attrs
03133 
03134     TranspFillAttribute* pCurrentTranspAttr = NULL;
03135     TranspFillMappingAttribute* pCurrentTranspMapAttr = NULL;
03136     TranspFillMappingAttribute TranspMap;
03137     TranspMap.Repeat = 1;
03138 
03139     if (pTranspFill != NULL)
03140     {
03141         pCurrentTranspAttr = RR_FILLTRANSP();
03142         pCurrentTranspMapAttr = (TranspFillMappingAttribute*)CurrentAttrs[ATTR_TRANSPFILLMAPPING].pAttr;
03143 
03144         CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr = pTranspFill;
03145         CurrentAttrs[ATTR_TRANSPFILLMAPPING].pAttr = (AttributeValue*)&TranspMap;
03146     }
03147 
03148     BOOL res = RenderBitmapFill(pPath, pFill);
03149 
03150     // Restore pre-existing current attrs
03151     CurrentAttrs[ATTR_FILLMAPPING].pAttr = pCurrentFillMapAttr;
03152     if (pTranspFill != NULL)
03153     {
03154         CurrentAttrs[ATTR_TRANSPFILLGEOMETRY].pAttr = pCurrentTranspAttr;
03155         CurrentAttrs[ATTR_TRANSPFILLMAPPING].pAttr = pCurrentTranspMapAttr;
03156     }
03157 
03158     return res;
03159 
03160 }
03161 
03163 
03164 
03165 
03166 // Andy Hills, 23-10-00:
03167 // Helper functions for RenderBitmapFill and SetBitmapTransparencyFill
03168 
03169 
03170 
03171 /********************************************************************************************
03172 
03173 >   BOOL GRenderRegion::IsScaledUp(FillGeometryAttribute *Fill)
03174 
03175     Author:     Andy_Hills (Xara Group Ltd) <camelotdev@xara.com>
03176     Created:    23/10/00
03177     Inputs:     Fill    the bmp fill to test
03178     Outputs:    -
03179     Returns:    TRUE if the bitmap is scaled up (i.e. zoomed into / enlarged)
03180     Purpose:    Helper function for RenderBitmapFill and SetBitmapTransparencyFill.
03181                 Used to work out whether or not to smooth bitmap fills/transparencies.
03182     Errors:     -
03183 
03184 ********************************************************************************************/
03185 
03186 BOOL GRenderRegion::IsScaledUp(FillGeometryAttribute *Fill)
03187 {
03188     // validate *Fill
03189     BOOL bIsBitmapFill = (  (Fill->IsKindOf( CC_RUNTIME_CLASS(BitmapFillAttribute) ))
03190                         ||  (Fill->IsKindOf( CC_RUNTIME_CLASS(TranspFillAttribute) )));
03191 
03192     ERROR3IF( (!bIsBitmapFill), "GRenderRegion::IsScaledUp - Fill should be a bmp fill or a transp bmp fill" );
03193     if( !bIsBitmapFill ) return FALSE;
03194 
03195 
03196     // calculate the desired exactly shrunk bitmap size from the handles on the old bitmap
03197     DocCoord* pStartpoint   = Fill->GetStartPoint();
03198     DocCoord* pEndpoint     = Fill->GetEndPoint();
03199     DocCoord* pEndpoint2    = Fill->GetEndPoint2();
03200 
03201     // Karim 03/08/2000
03202     UINT32 NewWidth = (UINT32)(0.5 + pStartpoint->Distance(*pEndpoint)  / GetScaledPixelWidth());
03203     UINT32 NewHeight    = (UINT32)(0.5 + pStartpoint->Distance(*pEndpoint2) / GetScaledPixelWidth());
03204 
03205     return (NewWidth > Fill->GetBitmap()->GetWidth() && NewHeight > Fill->GetBitmap()->GetHeight());
03206 }
03207 
03208 
03209 /********************************************************************************************
03210 
03211 >   BOOL GRenderRegion::IsAt100Percent(FillGeometryAttribute *Fill)
03212 
03213     Author:     Andy_Hills (Xara Group Ltd) <camelotdev@xara.com>
03214     Created:    23/10/00
03215     Inputs:     Fill    the bmp fill to test
03216     Outputs:    -
03217     Returns:    TRUE if the bitmap is at 100% (i.e. not zoomed in or resized)
03218     Purpose:    Helper function for RenderBitmapFill and SetBitmapTransparencyFill.
03219                 Used to work out whether or not to smooth bitmap fills/transparencies.
03220     Errors:     -
03221 
03222 ********************************************************************************************/
03223 
03224 BOOL GRenderRegion::IsAt100Percent(FillGeometryAttribute *Fill)
03225 {
03226     // validate *Fill
03227     BOOL bIsBitmapFill = (  (Fill->IsKindOf( CC_RUNTIME_CLASS(BitmapFillAttribute) ))
03228                         ||  (Fill->IsKindOf( CC_RUNTIME_CLASS(TranspFillAttribute) )));
03229 
03230     ERROR3IF( (!bIsBitmapFill), "GRenderRegion::IsAt100Percent - Fill should be a bmp fill or a transp bmp fill" );
03231     if( !bIsBitmapFill ) return FALSE;
03232 
03233 
03234     // calculate the desired exactly shrunk bitmap size from the handles on the old bitmap
03235     DocCoord* pStartpoint   = Fill->GetStartPoint();
03236     DocCoord* pEndpoint     = Fill->GetEndPoint();
03237     DocCoord* pEndpoint2    = Fill->GetEndPoint2();
03238 
03239     // Karim 03/08/2000
03240     UINT32 NewWidth = (UINT32)(0.5 + pStartpoint->Distance(*pEndpoint)  / GetScaledPixelWidth());
03241     UINT32 NewHeight    = (UINT32)(0.5 + pStartpoint->Distance(*pEndpoint2) / GetScaledPixelWidth());
03242 
03243     return (NewWidth == Fill->GetBitmap()->GetWidth() && NewHeight == Fill->GetBitmap()->GetHeight());
03244 }
03245 
03246 
03247 /********************************************************************************************
03248 
03249 >   BOOL GRenderRegion::IsDistorted(FillGeometryAttribute *Fill)
03250 
03251     Author:     Andy_Hills (Xara Group Ltd) <camelotdev@xara.com>
03252     Created:    23/10/00
03253     Inputs:     Fill    the bmp fill to test
03254     Outputs:    -
03255     Returns:    TRUE if the bitmap is distorted (rotated or skewed).
03256     Purpose:    Helper function for RenderBitmapFill and SetBitmapTransparencyFill.
03257                 Used to work out whether or not to smooth bitmap fills/transparencies.
03258     Errors:     -
03259 
03260 ********************************************************************************************/
03261 
03262 BOOL GRenderRegion::IsDistorted(FillGeometryAttribute *Fill)
03263 {
03264     // validate *Fill
03265     BOOL bIsBitmapFill = (  (Fill->IsKindOf( CC_RUNTIME_CLASS(BitmapFillAttribute) ))
03266                         ||  (Fill->IsKindOf( CC_RUNTIME_CLASS(TranspFillAttribute) )));
03267 
03268     ERROR3IF( (!bIsBitmapFill), "GRenderRegion::IsDistorted - Fill should be a bmp fill or a transp bmp fill" );
03269     if( !bIsBitmapFill ) return FALSE;
03270 
03271 
03272     // get fill handles
03273     DocCoord* pStartpoint   = Fill->GetStartPoint();
03274     DocCoord* pEndpoint     = Fill->GetEndPoint();
03275     DocCoord* pEndpoint2    = Fill->GetEndPoint2();
03276 
03277     // Is the bmp rotated/skewed?
03278     // If so, it is deemed 'distorted', and will be smoothed, even at 100%.
03279     // N.B. We will ignore rotation through 90/180/270 degrees,
03280     // or vertical/horizontal flipping.
03281     // i.e. we will deem the bmp to be distorted if either of the
03282     // endpoints do not line up with the startpoint.
03283     // 
03284     // e.g. these are all non-distorted fills:
03285     // 
03286     // B       A--->B  C<---A
03287     // ^       |            |
03288     // |       |            |
03289     // |       V            V
03290     // A--->C  C            B
03291     // 
03292     // startpoint A(x0,y0), endpoints B(x1,y1), C(x2,y2)
03293 
03294     ERROR3IF(GetScaledPixelWidth()==0, "Scaled pixel width is 0 in IsDistorted");
03295     if (GetScaledPixelWidth()==0)
03296         return TRUE;
03297     
03298     ERROR3IF(GetScaledPixelWidth()==0, "It's all gone wrong!");
03299     if (GetScaledPixelWidth()==0) return TRUE;                      // Fail safe
03300 
03301     UINT32 x0 = UINT32(0.5 + pStartpoint->x / GetScaledPixelWidth());
03302     UINT32 y0 = UINT32(0.5 + pStartpoint->y / GetScaledPixelWidth());
03303     UINT32 x1 = UINT32(0.5 + pEndpoint  ->x / GetScaledPixelWidth());
03304     UINT32 y1 = UINT32(0.5 + pEndpoint  ->y / GetScaledPixelWidth());
03305     UINT32 x2 = UINT32(0.5 + pEndpoint2 ->x / GetScaledPixelWidth());
03306     UINT32 y2 = UINT32(0.5 + pEndpoint2 ->y / GetScaledPixelWidth());
03307 
03308     //TRACEUSER( "Andy", _T("distorted=%d (%ld,%ld),(%ld,%ld),(%ld,%ld)\n"),
03309     //          (!(((x0==x1) && (y0==y2)) || ((x0==x2) && (y0==y1)))),
03310     //          x0,y0,x1,y1,x2,y2);
03311 
03312     return !((x0==x1 && y0==y2) || (x0==x2 && y0==y1));
03313 }
03314 
03315 
03316 /********************************************************************************************
03317 >   BOOL GRenderRegion::NeedToSmooth(FillGeometryAttribute *Fill,BOOL bAlreadyScaled)
03318 
03319     Author:     Andy_Hills (Xara Group Ltd) <camelotdev@xara.com>
03320     Created:    23/10/00
03321     Inputs:     Fill            the bmp fill to test
03322                 bAlreadyScaled  TRUE if the bmp has already been scaled to the correct size
03323                                 (using the super-smooth scaling algorithm)
03324     Outputs:    -
03325     Returns:    TRUE if the bitmap needs to be smoothed.
03326                 This depends on various factors - e.g.
03327                 * is it at 100%?
03328                 * if not, has it already been scaled to 100%?
03329                 * is it rotated/skewed?
03330                 * is interpolation enabled?
03331                 * are we forcing interpolation? (e.g. we're rendering the shadow of a bitmap)
03332                 * is document-wide bitmap smoothing (options dialogue) enabled?
03333     Purpose:    Helper function for RenderBitmapFill and SetBitmapTransparencyFill.
03334                 Used to work out whether or not to smooth bitmap fills/transparencies.
03335     Errors:     -
03336 
03337 ********************************************************************************************/
03338 
03339 BOOL GRenderRegion::NeedToSmooth(FillGeometryAttribute *Fill,BOOL bAlreadyScaled)
03340 {
03341     // Karim 16/10/2000
03342     // The shadow routines need a way to enforce bitmap smoothing for all
03343     // anti-aliased rendering.
03344 
03345     if (IsForcingBitmapSmoothing())
03346     {
03347         return TRUE;
03348     }
03349 
03350     //TRACEUSER( "Andy", _T("antialias=%d\n"),(RRQuality.GetAntialiasQuality() >= Quality::FullAntialias));
03351     
03352     // check that smoothing is enabled, and detail=max, and document bitmap smoothing is enabled
03353     if (Fill==NULL ||
03354         BitmapFillAttribute::m_doBitmapSmoothing == FALSE ||
03355         RRQuality.GetAntialiasQuality() < Quality::FullAntialias ||
03356         (Document::GetCurrent() && !(Document::GetCurrent())->GetBitmapSmoothing()) )
03357     {
03358         return FALSE;
03359     }
03360 
03361     // Andy 19/10/2000
03362     BOOL bNot100Percent = ! (IsAt100Percent(Fill) || bAlreadyScaled);
03363     BOOL bNotScaledUp   = ! IsScaledUp(Fill);
03364     BOOL bIsDistorted = IsDistorted(Fill);
03365 
03366     // do the smoothing if the bitmap is not at 100%
03367     // if it is at 100% sub-pixel movements will be snapped to pixel alignment
03368     if( Fill->GetBitmap()->GetInterpolation() )
03369     {
03370         // 'smooth when scaled up' is on --> interpolate if zoom isn't 100%
03371         return (bNot100Percent || bIsDistorted);
03372     }
03373     else
03374     {
03375         // 'smooth when scaled up' is off --> don't interpolate if zoomed in (horizontally AND vertically)
03376         return ((bNot100Percent && bNotScaledUp) || ((!bNot100Percent) && bIsDistorted));
03377     }
03378 }
03379 
03380 
03381 /********************************************************************************************
03382 >   BOOL GRenderRegion::SetSmoothingFlags(FillGeometryAttribute *Fill)
03383 
03384     Author:     Andy_Hills (Xara Group Ltd) <camelotdev@xara.com>
03385     Created:    27/10/00
03386     Inputs:     Fill            the bmp fill for which to set the flags
03387     Outputs:    -
03388     Returns:    TRUE on success.
03389     Purpose:    Helper function for RenderBitmapFill and SetBitmapTransparencyFill.
03390                 Sets the smoothing flags using SetBitmapSmoothingFlag and
03391                 SetTileFilteringFlag.
03392                 These flags determine the quality of subsequent SetBitmapFill / 
03393                 SetTransparentBitmapFill operations.
03394     Errors:     -
03395 
03396 ********************************************************************************************/
03397 
03398 BOOL GRenderRegion::SetSmoothingFlags(FillGeometryAttribute *Fill)
03399 {
03400     // if we're printing or exporting, maximise quality
03401     BOOL bNeedMaxQuality = (IsUsingSmoothedBitmaps() || IsPrinting());
03402 
03403     // Andy Hills, 24-10-00:
03404     // Moved the SetExtraSmoothFlag logic to here:
03405     // the flag needs to be set before we SetBitmapFill.
03406     BOOL SetExtraSmoothFlag   = FALSE;
03407     BOOL SetTileFilteringFlag = FALSE;
03408 
03409     if( !bNeedMaxQuality )
03410     {
03411         // Normal document rendering --> use normal bmp rendering functions.
03412         // The bitmap may require smoothing (e.g. if it's being rotated/skewed).
03413         
03414         // to smooth or not to smooth? NeedToSmooth answers the question.
03415         SetExtraSmoothFlag = NeedToSmooth( Fill, FALSE /* we haven't scaled the bitmap down */ );
03416     }
03417     else
03418     {
03419         // Create bitmap dialogue / printing
03420         // --> Set tile filtering flag (i.e. maximum quality scaling/rotation algorithm)
03421         SetTileFilteringFlag = NeedToSmooth( Fill, FALSE );
03422     }
03423 
03424     // Get default values from current active capture
03425     Capture* pCapture = GetTopCapture();
03426     if (pCapture)
03427     {
03428         if (!SetExtraSmoothFlag) SetExtraSmoothFlag = pCapture->info.caFlags.BitmapSmoothing;
03429         if (!SetTileFilteringFlag) SetTileFilteringFlag = pCapture->info.caFlags.TileFiltering;
03430     }
03431 
03432     GetDrawContext()->SetTileSmoothingFlag(SetExtraSmoothFlag);
03433     GetDrawContext()->SetTileFilteringFlag(SetTileFilteringFlag);
03434 
03435     return TRUE;
03436 }
03437 
03438 
03439 /********************************************************************************************
03440 
03441 >   BOOL GRenderRegion::RenderBitmapFill(Path *PathToDraw, BitmapFillAttribute *Fill )
03442 
03443     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
03444     Created:    10/8/94
03445     Inputs:     PathToDraw is a pointer to a Path object to render. Fill is the bitmap fill
03446                 required.
03447     Outputs:    -
03448     Returns:    TRUE if understood fill type & rendered it, FALSE if not
03449     Purpose:    Fills a shape with a bitmap
03450     Errors:     -
03451 
03452 ********************************************************************************************/
03453 
03454 BOOL GRenderRegion::RenderBitmapFill(Path *PathToDraw, BitmapFillAttribute* Fill)
03455 {
03456     if ( Fill==NULL || Fill->GetBitmap()==NULL || Fill->GetBitmap()->ActualBitmap==NULL)
03457         return FALSE;                                   // if no bitmap
03458 
03459     ENSURE( Fill->GetBitmap()->ActualBitmap->IsKindOf( CC_RUNTIME_CLASS( CWxBitmap ) ),
03460                                                                 "Strange bitmapfill");
03461 
03462     INT32 bpp = Fill->GetBitmap()->GetBPP();
03463     CWxBitmap *WinBM = NULL;
03464     CWxBitmap *OrigWinBM = NULL;
03465 //  BYTE *pGreyTable = NULL;
03466 //  BOOL bContoned = FALSE;
03467 //  BOOL bAlpha = FALSE;
03468 /*
03469     if (Fill->GetStartColour()!=NULL && Fill->GetEndColour()!=NULL)
03470     {
03471         // The bitmap is contoned
03472         bContoned = TRUE;
03473 
03474 //      if (bpp == 32 && Fill->GetBitmap()->IsTransparent())
03475 //          bAlpha = TRUE;
03476 
03477         if ( bpp<=8 )
03478         {
03479             // Not alpha so we need to use the greyscale version
03480             WinBM = (CWxBitmap*)Fill->GetBitmap()->GetGreyscaleVersion();
03481             if (WinBM)
03482                 bpp = WinBM->GetBPP();
03483             else
03484             {
03485                 // Aha, we're gunna do some clever palette jiggery pokery
03486                 pGreyTable = Fill->GetBitmap()->ActualBitmap->GetGreyscaleTable();
03487             }
03488         }
03489     }   
03490 
03491     if (WinBM == NULL)
03492     {
03493 */      // Use the normal bitmap
03494         WinBM = (CWxBitmap*)Fill->GetBitmap()->ActualBitmap;
03495 //  }
03496 
03497     if (WinBM == NULL || WinBM->BMInfo == NULL  || WinBM->BMBytes == NULL)
03498         return FALSE;
03499 
03500     // convert ArtWorks style attribute into Gavin-style
03501     POINT PGram[4];
03502     PGram[0].x = Fill->StartPoint.x; PGram[0].y = Fill->StartPoint.y;
03503     PGram[1].x = Fill->EndPoint.x;   PGram[1].y = Fill->EndPoint.y;
03504 
03505     BOOL Perspective = Fill->IsPerspective();
03506     if ( Perspective )
03507     {
03508         // Gerry removed the pixel size test cos it makes small repeating fills go spappy
03509         PGram[2].x = Fill->EndPoint3.x; PGram[2].y = Fill->EndPoint3.y;
03510         PGram[3].x = Fill->EndPoint2.x; PGram[3].y = Fill->EndPoint2.y;
03511 
03512         if ( !MouldPerspective::WillBeValid(PGram) )
03513         {
03514             Perspective = FALSE;
03515             TRACEUSER( "Will", _T("Bitmap Perspective points are Invalid !!\n"));
03516         }
03517     }
03518     if ( !Perspective )
03519     {
03520         PGram[2].x = Fill->EndPoint2.x;
03521         PGram[2].y = Fill->EndPoint2.y;
03522     }       
03523 
03524     // get the colour we use to fill around the edges from the current solid fill colour
03525     COLORREF DefaultColour = 0xFFFFFFFF;
03526 
03527     DWORD Style = 0;
03528     TranspGradTable TranspTable;
03529 
03530     if (uBitmapDepth==32)
03531     {
03532         // Check for a Transparency Fill
03533         GetTransparencyFill(&TranspTable, &Style);
03534     }
03535     else
03536         Style = WhichTransparency<<8;
03537 
03538     INT32 Tiling = ((FillMappingAttribute*)CurrentAttrs[ATTR_FILLMAPPING].pAttr)->Repeat;
03539     Style |= Tiling;
03540 
03541     // --- Colour-correct and/or Contone the bitmap as necessary
03542     RGBQUAD *Palette = NULL;
03543 
03544     // Do the colour correction. This may produce a new pointer in Palette or BitmapBits,
03545     // which we should CCFree() when we are done with it - see the end of this function
03546 /*  ColourCorrectBitmap(Fill, WinBM->BMInfo, &Palette);
03547 
03548     if ( bContoned && bpp>8 )
03549         Style |= 0x80 ;
03550 
03551     // Now see if we need to muck around with the palette for the contoning
03552     if (pGreyTable != NULL)
03553     {
03554 //      ERROR3IF(bpp != 8, "Greytable should only be here when rendering an 8bpp bitmap");
03555         RGBQUAD *OldPalette = Palette;
03556 
03557         // Create a new palette
03558         Palette = (RGBQUAD *) CCMalloc(sizeof(RGBQUAD)<<bpp);
03559         if (Palette == NULL)
03560         {
03561             ERROR3("No memory for palette");
03562             return FALSE;
03563         }
03564         
03565         // Copy the entries from the contone palette into the new one,
03566         // using the Grey table as a guide
03567         for (INT32 i=0; i<1<<bpp; i++)
03568             Palette[i] = OldPalette[pGreyTable[i]];
03569 
03570         if (OldPalette != WinBM->BMInfo->bmiColors)
03571             CCFree(OldPalette);         // Don't need the contone palette any more
03572     }
03573 */
03574     // Check for transparent bitmap plotting
03575     BYTE *BitmapBits = WinBM->BMBytes;
03576 
03577     if (bpp <= 8)
03578     {
03579         INT32 NumCols = 1<<bpp;
03580         // Search for a transparent colour setting the Style flags if necessary...
03581         for (INT32 i=0; i<NumCols; i++)
03582         {
03583             if (WinBM->BMInfo->bmiColors[i].rgbReserved == 0xFF)
03584             {
03585                 Style |= 0x008000;
03586 
03587                 if (RenderFlags.VeryMono)
03588                 {
03589                     // We want to render everything as black,
03590                     // so we'll use a temporary palette, with all
03591                     // the colours set to black
03592                     if (Palette == NULL)    // If no temporary palette allocated, get one
03593                         Palette = (RGBQUAD *) CCMalloc(256 * sizeof(RGBQUAD));
03594 
03595                     if (Palette != NULL)
03596                     {
03597                         // Set the whole palette to black
03598                         memset(Palette, 0, 256*sizeof(RGBQUAD));
03599                         // And set the transparent colour to transparent white
03600                         Palette[i].rgbRed       = 0xFF;
03601                         Palette[i].rgbGreen     = 0xFF;
03602                         Palette[i].rgbBlue      = 0xFF;
03603                         Palette[i].rgbReserved  = 0xFF;
03604                     }
03605                 }
03606                 break;
03607             }
03608         }
03609     }
03610 
03611     // If we didn't create a temporary palette, then we'll use the original bitmap
03612     if ( Palette==NULL && bpp<=8 && !Fill->IsKindOf(CC_RUNTIME_CLASS(FractalFillAttribute)) &&
03613                                     !Fill->IsKindOf(CC_RUNTIME_CLASS(  NoiseFillAttribute)) )
03614         Palette = WinBM->BMInfo->bmiColors;
03615 
03616     LPBYTE pTranspTable = NULL;
03617     if ( uBitmapDepth==32 && bpp==32 )
03618     {
03619         // If rendering a non-paletted bitmap, then gavin needs the
03620         // transparency table to be passed in
03621         pTranspTable = (LPBYTE) TranspTable.GetTable();         // this cast is OK as the structure
03622                                                                 // returned is an array of bytes
03623         Style |= 0x004000;  // MarkH 15/7/99 Need to OR the Style with 0x004000 to say that
03624                             // we want to use the alpha channel!!
03625     }
03626 
03627     BOOL bDoBitmapFill = TRUE;
03628 
03629     BOOL bClearBitmapConv = FALSE;
03630     BYTE* pSepTables = NULL;
03631 //  BGR *pCyanSepTable = NULL;
03632 //  BGR *pMagentaSepTable = NULL;
03633 //  BGR *pYellowSepTable = NULL;
03634 //  BGR *pBlackSepTable = NULL;
03635 //  BYTE *pUnderColourRemovalTable = NULL;
03636 //  BYTE *pBlackGenerationTable = NULL;
03637     CWxBitmap* pNewBitmap = NULL;
03638     
03639     // --- Add Separation Style bits as approriate to the current colour separation mode
03640     // Currently, the only "separation" option we use is composite print preview
03641     // SepStyle for the SetBitmapFill functions are always in the MS byte of Style
03642     if (bpp > 8)    // Only needed for deep bitmaps
03643     {
03644         // If we've got a valid colour plate and it is a composite preview
03645         if (CurrentColContext->GetColourPlate() != NULL &&
03646             !CurrentColContext->GetColourPlate()->IsDisabled())
03647         {
03648             
03649             if (CurrentColContext->GetColourPlate()->GetType() == COLOURPLATE_COMPOSITE)
03650             {
03651                 // Find the colour manager (if there is one), and ask it for the 15-bit RGB
03652                 // printer colour matching lookup table
03653 PORTNOTE("cms", "DisabledXaraCMS")
03654 #ifndef EXCLUDE_FROM_XARALX
03655                 XaraCMS* lpCMSMan = GetApplication()->GetCMSManager();
03656                 if (lpCMSMan != NULL)
03657                 {
03658                     DWORD *MatchTable = lpCMSMan->GetPaperViewTable();
03659                     ERROR3IF(MatchTable == NULL, "Can't create/find colour matching table");
03660                     if (MatchTable != NULL)
03661                     {
03662                         GetDrawContext()->SetBitmapConversionTable((BGR *)MatchTable);
03663                         bClearBitmapConv = TRUE;
03664                         // Bits 3 and 4 of top byte of Style specifies the conversion algorithm
03665                         // Make sure it only affects the 2 bits
03666                         Style |= ((BitmapConversion & 3) << 27);
03667                         
03668                         // Make a copy of the bitmap
03669 //                      pNewBitmap = (WinBitmap*)WinBM->MakeCompositeCopy(RenderView);
03670 //                      OrigWinBM = WinBM;                  // Save original bitmap pointer
03671 //                      WinBM = pNewBitmap;                 // Use this bitmap instead
03672 //                      BitmapBits = WinBM->BMBytes;        // And make sure we update this
03673                     }
03674                 }
03675 #endif
03676             }
03677             else if (CurrentColContext->GetColourPlate()->GetType() == COLOURPLATE_SPOT)
03678             {
03679                 GetDrawContext()->SetColour(0xFFFFFF);
03680                 bDoBitmapFill = FALSE;
03681             }
03682             else if (CurrentColContext->GetColourPlate()->GetType() != COLOURPLATE_NONE)
03683             {
03684                 pSepTables = (BYTE *) CCMalloc(5 * 256 * sizeof(BYTE));
03685                 if (pSepTables != NULL)
03686                 {
03687                     String_256 PrintProfile;
03688 PORTNOTE("cms", "DisabledXaraCMS")
03689 #ifndef EXCLUDE_FROM_XARALX
03690                     XaraCMS* lpCMSMan = GetApplication()->GetCMSManager();
03691                     if (lpCMSMan)
03692                         lpCMSMan->GetPrinterProfile(&PrintProfile);
03693 #endif
03694                     ColourContextCMYK *cc = new ColourContextCMYK(RenderView, &PrintProfile);
03695                     if (cc->GetProfileTables(pSepTables))
03696                     {
03697                         // Make a copy of the bitmap
03698                         pNewBitmap = (CWxBitmap*)WinBM->MakeSeparatedCopy(RenderView->GetColourPlate(), pSepTables);
03699                         OrigWinBM = WinBM;                  // Save original bitmap pointer
03700                         WinBM = pNewBitmap;                 // Use this bitmap instead
03701                         BitmapBits = WinBM->BMBytes;        // And make sure we update this
03702                     }
03703                     delete cc;
03704                 }
03705             }
03706         }
03707     }
03708 
03709     BOOL Result = FALSE; // function working correctly
03710 
03711     if (bDoBitmapFill)
03712     {
03713         //---------------------------------------------------------------------------------------
03714         // Setup contoning
03715         //---------------------------------------------------------------------------------------
03716 
03717         if ( Fill->GetStartColour()!=NULL && Fill->GetEndColour()!=NULL )
03718         {
03719             DocColour* pCS = Fill->GetStartColour();
03720             DocColour* pCE = Fill->GetEndColour  ();
03721             INT32 sr,sg,sb;
03722             INT32 er,eg,eb;
03723             pCS->GetRGBValue(&sr,&sg,&sb);
03724             pCE->GetRGBValue(&er,&eg,&eb);
03725             GetDrawContext()->SetContone(GetFillEffect()+1,RGB(sr,sg,sb),RGB(er,eg,eb));
03726         }
03727         else
03728             GetDrawContext()->SetContone(0);
03729 
03730         GetDrawContext()->SetBias(3,Fill->GetProfile().GetBias()) ;
03731         GetDrawContext()->SetGain(3,Fill->GetProfile().GetGain()) ;
03732         GetDrawContext()->SetOutputRange(3,0x00,0xFF) ;
03733 
03734         //---------------------------------------------------------------------------------------
03735         // Smoothing decisions
03736         //---------------------------------------------------------------------------------------
03737 
03738         SetSmoothingFlags(Fill);
03739 
03740         //---------------------------------------------------------------------------------------
03741         // SetBitmapFill here
03742         //---------------------------------------------------------------------------------------
03743 
03744         //TRACEUSER( "Andy", _T("SetBitmapFill2 (scale and/or rotate)\n"));
03745 
03746         if (Perspective)    // Is a Perspective applied ?
03747         {
03748             // then plot it perspectivised
03749             Result = GetDrawContext()->SetPerspectiveBitmapFill(
03750                             &(WinBM->BMInfo->bmiHeader),
03751                             BitmapBits,
03752                             Style,
03753                             PGram,
03754                             DefaultColour,
03755                             Palette,
03756                             NULL, NULL, NULL, pTranspTable,
03757                             0
03758                             );
03759         }
03760         else
03761         {
03762             // just plot it normally
03763             Result = GetDrawContext()->SetBitmapFill(
03764                             &(WinBM->BMInfo->bmiHeader),
03765                             BitmapBits,
03766                             Style,
03767                             PGram,
03768                             DefaultColour,
03769                             Palette,
03770                             NULL, NULL, NULL, pTranspTable,
03771                             0
03772                             );
03773         }
03774     }
03775 
03776     // Now it is time to Draw the path, so we will Fuzzy Clip it just in case it is too big
03777     DocCoord* Coords;
03778     PathVerb* Verbs;
03779     UINT32 TotalCoords;
03780     BOOL ShouldDeleteCoords = FALSE;
03781 
03782     // try and clip the path before rendering it, for bigger zoom values
03783     if (TryToFuzzyClip(PathToDraw, &Coords, &Verbs, &TotalCoords))
03784     {
03785         // Yes, we clipped the paths alright
03786         ShouldDeleteCoords = TRUE;
03787     }
03788     else
03789     {
03790         // No Clipping here matey
03791         Coords = PathToDraw->GetCoordArray();
03792         Verbs  = PathToDraw->GetVerbArray();
03793         TotalCoords = PathToDraw->GetNumCoords();
03794     }
03795 
03796     // Draw the actual path
03797     if (TotalCoords > 1)
03798         GetDrawContext()->FillPath( (POINT*)Coords, Verbs, TotalCoords, (RR_WINDINGRULE()==EvenOddWinding) ? 0 : 1 );
03799 
03800 PORTNOTE( "other", "m_pTempTransparencyBMPBits seems never to be used, removed by GAT" )
03801 #ifndef EXCLUDE_FROM_XARALX
03802     // Free the memory of the transparency bitmap if this was allocated temporarly
03803     // by either Get/SetTransparency
03804     // from using the bitmap scaling function
03805     if (m_pTempTransparencyBMPBits)
03806     {
03807         CCFree (m_pTempTransparencyBMPBits);
03808         m_pTempTransparencyBMPBits = NULL;
03809     }
03810 #endif
03811 
03812     // Clean up if we need to
03813     if (ShouldDeleteCoords)
03814     {
03815         delete Coords;
03816         delete Verbs;
03817     }
03818 
03819     if (pNewBitmap)
03820     {
03821         WinBM = OrigWinBM;
03822         delete pNewBitmap;
03823     }
03824 /*
03825     if (pAlphaContoneBmp)
03826     {
03827         if (WinBM == pAlphaContoneBmp)
03828             WinBM = pBeforeAlphaContoneBmp;
03829         delete pAlphaContoneBmp;
03830     }
03831 */
03832     // Free any memory used for colour-corrected bitmap palettes.
03833     // If this pointer doesn't point at the original palette, then it has
03834     // been temporarily allocated by ColourCorrectBitmap, above.
03835     if (Palette != WinBM->BMInfo->bmiColors)
03836         CCFree(Palette);
03837 
03838     if (bClearBitmapConv)
03839         GetDrawContext()->SetBitmapConversionTable(NULL);
03840 
03841     if (pSepTables)
03842     {
03843         GetDrawContext()->SetSeparationTables();    // Defaults to setting everything to NULL
03844         CCFree(pSepTables);
03845     }
03846 /*
03847     if (pCyanSepTable)
03848         CCFree(pCyanSepTable);
03849     if (pMagentaSepTable)
03850         CCFree(pMagentaSepTable);
03851     if (pYellowSepTable)
03852         CCFree(pYellowSepTable);
03853     if (pBlackSepTable)
03854         CCFree(pBlackSepTable);
03855     if (pUnderColourRemovalTable)
03856         CCFree(pUnderColourRemovalTable);
03857     if (pBlackGenerationTable)
03858         CCFree(pBlackGenerationTable);
03859 */
03860     // Reset smoothing flags
03861     SetSmoothingFlags(NULL);
03862 
03863     return TRUE;
03864 }
03865 
03866 
03867 
03868 /********************************************************************************************
03869 
03870 >   BOOL GRenderRegion::GetTransparencyFill(TranspGradTable* pTranspTable, DWORD* Style)
03871 
03872     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
03873     Created:    24/8/94
03874     Inputs:     pTranspTable is a pointer to a Transparency Table to fill in.  This table must
03875                 still exist at the time of rendering, as Gavin just keeps a pointer to it.
03876                 So be careful with those Local Variables !!
03877                 Style is a Pointer to the Fill style for us to update.
03878     Outputs:    Style is updated to include Transparency Style.
03879     Returns:    TRUE, if a Transparent fill has been set.
03880                 FALSE, means it will use the Tranparency in the Colour Fill.
03881     Purpose:    Initialises a Transparency fill.
03882     Scope:      Protected
03883 
03884     Notes:      Added support for square, 3 and 4 point transparency (Gerry 12/8/96)
03885 
03886 ********************************************************************************************/
03887 
03888 BOOL GRenderRegion::GetTransparencyFill(TranspGradTable* pTranspTable, DWORD* Style)
03889 {
03890     if (uBitmapDepth != 32)
03891         return FALSE;       // Check transparency rendering is on
03892 
03893     COLORREF StartTransp;
03894     COLORREF EndTransp;
03895     DWORD TransStyle = 0;
03896     BOOL SpecialFill = FALSE;
03897 
03898     // Get the current Transparency Fill Geometry
03899     TranspFillAttribute* TranspFill = RR_FILLTRANSP();
03900 
03901 //  StartTransp = ConvertColourToTransScreenWord(CurrentColContext, &TranspFill->Colour);
03902 //  EndTransp = ConvertColourToTransScreenWord(CurrentColContext, &TranspFill->EndColour);
03903 
03904     // Get the transparency from the Fill
03905 //  StartTransp = (StartTransp  & 0xFF000000) >> 24;
03906 //  EndTransp   = (EndTransp    & 0xFF000000) >> 24;
03907 
03908     StartTransp = 0;
03909 
03910     if (TranspFill->GetStartTransp() != NULL)
03911         StartTransp = *TranspFill->GetStartTransp();
03912 
03913     UINT32 tType = TranspFill->GetTranspType();
03914 
03915     // Get the Transparency Fill Type
03916     CCRuntimeClass* FillType = TranspFill->GetRuntimeClass();
03917 
03918     // If it's a flat fill, then we don't need to do any
03919     // graduated stuff.  So Just update the Style and Return
03920     if (FillType == CC_RUNTIME_CLASS(FlatTranspFillAttribute))
03921     {
03922         if (tType == TT_Mix && StartTransp == 0)
03923             return FALSE;       // Use Colour Fill's Transparency
03924 
03925         *Style |= (MapTranspTypeToGDraw(tType, FALSE)<<8);
03926         *Style |= (StartTransp<<16);
03927 
03928         return TRUE;
03929     }
03930     else if (FillType == CC_RUNTIME_CLASS(ThreeColTranspFillAttribute))
03931     {
03932         SpecialFill = TRUE;
03933     }
03934     else if (FillType == CC_RUNTIME_CLASS(FourColTranspFillAttribute))
03935     {
03936         SpecialFill = TRUE;
03937     }
03938     else if (TranspFill->IsKindOf(CC_RUNTIME_CLASS(BitmapTranspFillAttribute)))
03939     {
03940 //      TRACEUSER( "Will", _T("Bitmap Transparency, Start=%d, End=%d\n"),StartTransp,EndTransp);
03941 
03942         // If it is a bitmap (or fractal) transparency then get the other function to set it up
03943         return SetBitmapTransparencyFill((TranspFillAttribute*)TranspFill, Style, pTranspTable);
03944     }
03945 
03946     EndTransp = 255;
03947 
03948     if (TranspFill->GetEndTransp() != NULL)
03949         EndTransp = *TranspFill->GetEndTransp();
03950 
03951     // It must be a Graduated Transparency !!
03952     // That's the spirit !! None of these boring 'Flat' things.
03953     // You want a nice Elliptical Transparency fading out at the edges.
03954 
03955     // Make the Transparency Table if required
03956 
03957     // CGS ....
03958     // We now need to decide exactly who is going to build the table!
03959     // If the transparency fill has the default biasgain, then we will continue to build
03960     // this in the standard fashion (i.e.  let GDraw build it).
03961     // If however it does NOT, then we will build the table ourselves (with respect to
03962     // the applied biasgain) ....
03963 
03964     CProfileBiasGain DefaultBiasGain;                               // default profile
03965     CProfileBiasGain DiagramMapper = TranspFill->GetProfile ();     // applied profile
03966 
03967     INT32 Tiling = ((FillMappingAttribute*)CurrentAttrs[ATTR_TRANSPFILLMAPPING].pAttr)->Repeat;
03968 
03969     // make some optimisation decisions ....
03970     
03971     if (DiagramMapper == DefaultBiasGain)           // applied profile is the default profile
03972     {
03973         if (!SpecialFill)
03974         {
03975             TransparencyRamp *pTranspRamp = TranspFill->GetTranspRamp();
03976 
03977             if (Tiling != 4)
03978             {
03979                 pTranspTable->BuildTable(StartTransp, EndTransp, pTranspRamp);
03980             }
03981             else
03982             {
03983                 pTranspTable->BuildHighQualityRepeatTable(StartTransp, EndTransp, pTranspRamp);
03984             }
03985         }
03986     }
03987     else
03988     {
03989         if (!SpecialFill)
03990         {
03991             if (Tiling != 4)
03992             {
03993                 pTranspTable->BuildTable(StartTransp, EndTransp, DiagramMapper);
03994             }
03995             else
03996             {
03997                 pTranspTable->BuildHighQualityRepeatTable(StartTransp, EndTransp, DiagramMapper);
03998             }
03999         }
04000     }
04001 
04002 //  if (IsUserName("Will")) TRACE( _T("Grad Transparency, Start=%d, End=%d\n"),StartTransp,EndTransp);
04003 
04004     // Find the control points of the Transparency Fill
04005     POINT TA,TB,TC,TD;
04006 
04007     DocCoord* StartPoint    = TranspFill->GetStartPoint();
04008     DocCoord* EndPoint      = TranspFill->GetEndPoint();
04009     DocCoord* EndPoint2     = TranspFill->GetEndPoint2();
04010     DocCoord* EndPoint3     = TranspFill->GetEndPoint3();
04011 
04012     if (StartPoint != NULL)
04013     {
04014         TA.x = (*StartPoint).x; 
04015         TA.y = (*StartPoint).y;
04016     }
04017 
04018     if (EndPoint != NULL)
04019     {
04020         TB.x = (*EndPoint).x;   
04021         TB.y = (*EndPoint).y;
04022     }
04023 
04024     if (EndPoint2 != NULL)
04025     {
04026         TC.x = (*EndPoint2).x;  
04027         TC.y = (*EndPoint2).y;
04028     }
04029 
04030     // Convert the Fill Type into a Gavin Fill Type
04031     if (FillType == CC_RUNTIME_CLASS(RadialTranspFillAttribute))
04032     {
04033         TransStyle = 1;     // Elliptical Transparency
04034     }
04035     else if (FillType == CC_RUNTIME_CLASS(LinearTranspFillAttribute))
04036     {
04037         TransStyle = 0;     // Linear Transparency
04038 
04039         TA.x = (*StartPoint).x; TA.y = (*StartPoint).y;
04040         TB.x = (*EndPoint2).x;  TB.y = (*EndPoint2).y;
04041         TC.x = (*EndPoint).x;   TC.y = (*EndPoint).y;
04042     }
04043     else if (FillType == CC_RUNTIME_CLASS(ConicalTranspFillAttribute))
04044     {
04045         TransStyle = 2;     // Conical Transparency
04046 
04047         TB.x = TA.x - (TB.x - TA.x);
04048         TB.y = TA.y - (TB.y - TA.y);
04049     }
04050     else if (FillType == CC_RUNTIME_CLASS(SquareTranspFillAttribute))
04051     {
04052         TransStyle = 3;     // Square Transparency
04053     }
04054 
04055 
04056     BOOL Perspective = FALSE;
04057 
04058     // Is it a perspectivised fill ?
04059     if (TranspFill->IsPerspective())
04060     {
04061         Perspective = TRUE;
04062 
04063         POINT PGram[4];
04064 
04065         // Setup the Perspective control points
04066         if (FillType==CC_RUNTIME_CLASS(LinearTranspFillAttribute))
04067         {
04068             PGram[0].x = (*StartPoint).x;   PGram[0].y = (*StartPoint).y;
04069             PGram[1].x = (*EndPoint2).x;    PGram[1].y = (*EndPoint2).y;
04070             PGram[2].x = (*EndPoint3).x;    PGram[2].y = (*EndPoint3).y;
04071             PGram[3].x = (*EndPoint).x;     PGram[3].y = (*EndPoint).y;
04072         }
04073         else
04074         {
04075             PGram[0].x = TA.x;              PGram[0].y = TA.y;
04076             PGram[1].x = TB.x;              PGram[1].y = TB.y;
04077             PGram[2].x = (*EndPoint3).x;    PGram[2].y = (*EndPoint3).y;
04078             PGram[3].x = (*EndPoint2).x;    PGram[3].y = (*EndPoint2).y;
04079         }
04080 
04081         // Check the mould is valid
04082         // Gerry removed the pixel size test cos it makes small repeating fills go spappy
04083         if (MouldPerspective::WillBeValid(PGram))
04084         {
04085             // We're going to plot a perspective fill,
04086             // so copy the perspective control points
04087             TA.x = PGram[0].x;  TA.y = PGram[0].y;
04088             TB.x = PGram[1].x;  TB.y = PGram[1].y;
04089             TC.x = PGram[2].x;  TC.y = PGram[2].y;
04090             TD.x = PGram[3].x;  TD.y = PGram[3].y;
04091         }
04092         else 
04093         {
04094             // The mould is bad...
04095             Perspective = FALSE;
04096         }
04097     }
04098 
04099     if (SpecialFill)
04100     {
04101         // The fill is a fabby new one
04102 
04103         if ((FillType != CC_RUNTIME_CLASS(ThreeColTranspFillAttribute)) &&
04104             (FillType != CC_RUNTIME_CLASS(FourColTranspFillAttribute)))
04105         {
04106             ERROR3("Unknown new fill type");
04107             return FALSE;                               // unknown fill type
04108         }
04109 
04110         BYTE StartTransp = *TranspFill->GetStartTransp();
04111         BYTE EndTransp = *TranspFill->GetEndTransp();
04112         BYTE EndTransp2 = *TranspFill->GetEndTransp2();
04113 
04114         BYTE EndTransp3 = 255;
04115         if (TranspFill->GetEndTransp3() != NULL)
04116             EndTransp3 = *TranspFill->GetEndTransp3();
04117 
04118         DWORD OurStyle = 0;
04119 
04120         if (FillType == CC_RUNTIME_CLASS(ThreeColTranspFillAttribute))
04121         {           
04122             // Style & 0xFF = 0 (simple with better colours outside the mesh)
04123             // Style & 0xFF = 2 (tiled)
04124 
04125             if (Tiling == 1)
04126                 OurStyle |= 0;
04127             else
04128                 OurStyle |= 2;
04129 
04130             if (Perspective)
04131                 GetDrawContext()->SetTransparent3WayGraduation4(OurStyle, StartTransp, EndTransp, EndTransp2,
04132                                                     &TA, &TB, &TC, &TD);
04133             else
04134                 GetDrawContext()->SetTransparent3WayGraduation(OurStyle, StartTransp, EndTransp, EndTransp2,
04135                                                     &TA, &TB, &TC);
04136         }
04137         else
04138         {
04139             // Style & 0xFF = 1 (for better colours outside the mesh)
04140 
04141             if (Tiling == 1)
04142                 OurStyle |= 1;
04143             else
04144                 OurStyle |= 2;
04145 
04146             // The transparency values in the following lines are correct!!!
04147             if (Perspective)
04148                 GetDrawContext()->SetTransparent4WayGraduation4(OurStyle, StartTransp, EndTransp, EndTransp3, EndTransp2,
04149                                                     &TA, &TB, &TC, &TD);
04150             else
04151                 GetDrawContext()->SetTransparent4WayGraduation(OurStyle, StartTransp, EndTransp, EndTransp3, EndTransp2,
04152                                                     &TA, &TB, &TC);
04153         }
04154     }
04155     else
04156     {
04157 //Mark Howitt, 14/10/97. If we have selected the new transparent repeating grad fills, set repeating.
04158 #ifdef NEW_FEATURES
04159         if(Tiling == 4)
04160             TransStyle |= 0x10000;
04161 #endif  
04162 // Set the Current Transparency to be a graduated Transparency
04163         if (Perspective)
04164             GetDrawContext()->SetTransparentGraduation4( TransStyle, pTranspTable, &TA, &TB, &TC, &TD );
04165         else
04166             GetDrawContext()->SetTransparentGraduation( TransStyle, pTranspTable, &TA, &TB, &TC );
04167     }
04168 
04169     // Set the fill style to be a graduated transparency
04170     // MarkH 2/8/99 - Check to see which type we`re using and alter the style accordingly!
04171     *Style |= (MapTranspTypeToGDraw(tType, TRUE)<<8);
04172     return TRUE;
04173 }
04174 
04175 /********************************************************************************************
04176 
04177 >   BOOL GRenderRegion::SetBitmapTransparencyFill(TranspFillAttribute* Fill, DWORD* Style,
04178                                               TranspGradTable* pTranspTable)
04179     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04180     Created:    13/9/94
04181     Returns:    TRUE, if transparency was set ok.
04182                 FALSE, if failed to set the bitmap transparency.
04183     Purpose:    Sets up a bitmap transparency fill.
04184     Scope:      Protected
04185 
04186 ********************************************************************************************/
04187 
04188 BOOL GRenderRegion::SetBitmapTransparencyFill(TranspFillAttribute* Fill, DWORD* Style,
04189                                               TranspGradTable* pTranspTable)
04190 {
04191     if (Fill->GetBitmap()->ActualBitmap == NULL)
04192         return FALSE;                                   // if no bitmap
04193 
04194     ENSURE( Fill->GetBitmap()->ActualBitmap->IsKindOf( CC_RUNTIME_CLASS( CWxBitmap ) ),
04195                                                                 "Strange bitmapfill");
04196 
04197     UINT32 bpp = Fill->GetBitmap()->GetBPP();
04198     CWxBitmap *WinBM = (CWxBitmap*)Fill->GetBitmap()->ActualBitmap;
04199 
04200 /*  CWxBitmap *WinBM = NULL;
04201 
04202     BYTE *pGreyTable = NULL;
04203     if ( bpp<=8 )
04204     {
04205         WinBM = (CWxBitmap*)Fill->GetBitmap()->GetGreyscaleVersion();
04206         if (WinBM)
04207             bpp = WinBM->GetBPP();
04208         else
04209         {
04210             // Aha, we're gunna do some clever palette jiggery pokery
04211             pGreyTable = Fill->GetBitmap()->ActualBitmap->GetGreyscaleTable();
04212         }
04213     }
04214 
04215     if (WinBM == NULL)
04216     {
04217         // Use the normal bitmap
04218         WinBM = (CWxBitmap*)Fill->GetBitmap()->ActualBitmap;
04219     }
04220 */
04221     if (WinBM == NULL || WinBM->BMInfo == NULL  || WinBM->BMBytes == NULL)
04222         return FALSE;
04223 
04224     INT32 StartTransp = 0;
04225     INT32 EndTransp = 0;
04226     if (Fill->GetStartTransp() != NULL)
04227         StartTransp = *Fill->GetStartTransp();
04228     if (Fill->GetEndTransp() != NULL)
04229         EndTransp = *Fill->GetEndTransp();
04230 /*
04231     TransparencyRamp *pTranspRamp=Fill->GetTranspRamp();
04232     // Note:  BuildBitmapTable is optimised internally depending upon the profile ....
04233     pTranspTable->BuildBitmapTable(StartTransp, EndTransp, pTranspRamp, Fill->GetProfile ());
04234 
04235     BYTE* pRamp = (LPBYTE)(pTranspTable->GetTable());
04236     // Now see if we need to muck around with the palette for the contoning
04237     BYTE aRamp[0x100];
04238     if ( pGreyTable )
04239     {
04240         // Copy the entries from the old ramp into the new one,
04241         // using the Grey table as a guide
04242         for (INT32 i=0; i<1<<bpp; i++)
04243             aRamp[i] = pRamp[pGreyTable[i]];
04244         pRamp = aRamp;
04245     }
04246 */
04247 
04248     BYTE aRamp[0x100];
04249     BYTE* pRamp = NULL;
04250     if ( bpp<=8 && !Fill->IsKindOf(CC_RUNTIME_CLASS(FractalTranspFillAttribute)) &&
04251                    !Fill->IsKindOf(CC_RUNTIME_CLASS(  NoiseTranspFillAttribute)) )
04252     {
04253         RGBQUAD* pPalette = WinBM->BMInfo->bmiColors;
04254         if ( pPalette )
04255         {
04256             for (INT32 i=0; i<1<<bpp; i++)
04257                 aRamp[i] = (pPalette[i].rgbRed  *0x4D4D4D+
04258                             pPalette[i].rgbGreen*0x979797+
04259                             pPalette[i].rgbBlue *0x1C1C1C) >> 24;
04260             pRamp = aRamp;
04261         }
04262     }
04263 
04264     // convert ArtWorks style attribute into Gavin-style
04265     POINT PGram[4];
04266     PGram[0].x = (*Fill->GetStartPoint()).x; 
04267     PGram[0].y = (*Fill->GetStartPoint()).y;
04268     PGram[1].x = (*Fill->GetEndPoint  ()).x;
04269     PGram[1].y = (*Fill->GetEndPoint  ()).y;
04270 
04271     BOOL Perspective = Fill->IsPerspective();
04272     if ( Perspective )
04273     {
04274         // Gerry removed the pixel size test cos it makes small repeating fills go spappy
04275         PGram[2].x = (*Fill->GetEndPoint3()).x;
04276         PGram[2].y = (*Fill->GetEndPoint3()).y;
04277         PGram[3].x = (*Fill->GetEndPoint2()).x;
04278         PGram[3].y = (*Fill->GetEndPoint2()).y;
04279 
04280         if ( !MouldPerspective::WillBeValid(PGram) )
04281         {
04282             Perspective = FALSE;
04283             TRACEUSER( "Will", _T("Bitmap Perspective points are Invalid !!\n"));
04284         }
04285     }
04286     if ( !Perspective )
04287     {
04288         PGram[2].x = (*Fill->GetEndPoint2()).x;
04289         PGram[2].y = (*Fill->GetEndPoint2()).y;
04290     }       
04291 
04292     // get the colour we use to fill around the edges from the current solid fill colour
04293     COLORREF DefaultColour;
04294 
04295 //  DefaultColour = ConvertColourToTransScreenWord(CurrentColContext, &RR_FILLCOLOUR() );
04296     DefaultColour = 0xFFFFFFFF;
04297 
04298     UINT32 tType = Fill->GetTranspType();
04299     DWORD TranspStyle = tType<<8;
04300 
04301 //  INT32 Tiling = Fill->GetTesselation();
04302     INT32 Tiling = 
04303         ((TranspFillMappingAttribute*)CurrentAttrs[ATTR_TRANSPFILLMAPPING].pAttr)->Repeat;
04304     TranspStyle |= Tiling;
04305 
04306     // MarkH 2/8/99 - Check to see which type we`re using and alter the style accordingly!
04307     *Style |= (MapTranspTypeToGDraw(tType, TRUE)<<8);
04308 
04309     // If the bitmap has an alpha channel, then use this for the transparency channel.
04310     if ( bpp==32 && Fill->GetBitmap()->IsTransparent() )
04311         TranspStyle |= 0x8000;
04312 
04313     GetDrawContext()->SetBias(3,Fill->GetProfile().GetBias()) ;
04314     GetDrawContext()->SetGain(3,Fill->GetProfile().GetGain()) ;
04315     GetDrawContext()->SetOutputRange(3,StartTransp,EndTransp) ;
04316 
04317     //---------------------------------------------------------------------------------------
04318     // Smoothing decisions
04319     //---------------------------------------------------------------------------------------
04320 
04321     SetSmoothingFlags(Fill);
04322 
04323     if (Perspective)    // Is a Perspective applied ?
04324     {
04325         GetDrawContext()->SetPerspectiveTransparentBitmapFill(
04326                             &(WinBM->BMInfo->bmiHeader),
04327                             WinBM->BMBytes,
04328                             TranspStyle,
04329                             PGram,
04330                             DefaultColour,
04331                             pRamp,
04332                             0
04333                             );
04334     }
04335     else
04336     {
04337         GetDrawContext()->SetTransparentBitmapFill(
04338                             &(WinBM->BMInfo->bmiHeader),
04339                             WinBM->BMBytes,
04340                             TranspStyle,
04341                             PGram,
04342                             DefaultColour,
04343                             pRamp,
04344                             0
04345                             );
04346     }
04347 
04348     // Reset smoothing flags
04349     SetSmoothingFlags(NULL);
04350 
04351     return TRUE;
04352 }
04353 
04354 /********************************************************************************************
04355 
04356 >   BOOL GRenderRegion::SetFractalFill(ColourFillAttribute* Fill, DWORD* Style)
04357 
04358     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04359     Created:    22/9/94
04360     Returns:    TRUE, if fill  was set ok.
04361                 FALSE, if failed to set the fill.
04362     Purpose:    Sets up a fractal fill.
04363     Scope:      Protected
04364 
04365 ********************************************************************************************/
04366 
04367 BOOL GRenderRegion::SetFractalFill(ColourFillAttribute* Fill, DWORD* Style)
04368 {
04369     return FALSE;
04370 }
04371 
04372 /********************************************************************************************
04373 
04374 >   BOOL GRenderRegion::SetFractalTransparencyFill(TranspFillAttribute* Fill, DWORD* Style)
04375 
04376     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04377     Created:    13/9/94
04378     Returns:    TRUE, if transparency was set ok.
04379                 FALSE, if failed to set the fractal transparency.
04380     Purpose:    Sets up a fractal transparency fill.
04381     Scope:      Protected
04382 
04383 ********************************************************************************************/
04384 
04385 BOOL GRenderRegion::SetFractalTransparencyFill(TranspFillAttribute* Fill, DWORD* Style)
04386 {
04387 /*
04388     BeginBusyCursor();
04389 
04390     FractalTranspFillAttribute* FractFill = (FractalTranspFillAttribute*)Fill;
04391 
04392     // First make a fractal from the variables stored in the fill.
04393     PlasmaFractalFill TheFractal(FractFill->Seed, TRUE, 0, 
04394                                     FractFill->Graininess, FractFill->Gravity);
04395 
04396     // Get the fill control points
04397     DocCoord Start = *Fill->GetStartPoint();
04398     DocCoord End   = *Fill->GetEndPoint();
04399     DocCoord End2  = *Fill->GetEndPoint2();
04400 
04401     //if (IsUserName("Will")) TRACE( _T("Start = %d,%d\n"),Start.x, Start.y);
04402     //if (IsUserName("Will")) TRACE( _T("End   = %d,%d\n"),End.x, End.y);
04403     //if (IsUserName("Will")) TRACE( _T("End2  = %d,%d\n"),End2.x, End2.y);
04404 
04405     // Find the size of a pixel.  Note: This assumes pixels are square at the moment.
04406     MILLIPOINT PixelWidth = GetScaledPixelWidth();
04407 
04408     // Calculate the size of the fractal (in Pixels) from the control points
04409     INT32 FracPixWidth  = INT32(Start.Distance(End) * 2 / PixelWidth);
04410     INT32 FracPixHeight     = INT32(Start.Distance(End2)* 2 / PixelWidth);
04411 
04412     // The 'actual' dimensions of a fractal must be square and a power of 2.
04413     // 'GetDimension' finds an appropriate value for this dimension.
04414     // It will be the next power of 2 higher than Width or Height (whichever is biggest).
04415     INT32 FracPixDim    = TheFractal.GetDimension(FracPixWidth, FracPixHeight);
04416 
04417     //if (IsUserName("Will")) TRACE( _T("Fractal Pixel Width = %d, Height = %d\n"),FracPixWidth,FracPixHeight);
04418     //if (IsUserName("Will")) TRACE( _T("Fractal Pixel Dim   = %d\n"),FracPixDim);
04419 
04420     // Because the 'actual' fractal is always square we have to scale it to fit into
04421     // our no-square render region.
04422     double FracXScale = double(FracPixDim) / double(FracPixWidth);
04423     double FracYScale = double(FracPixDim) / double(FracPixHeight);
04424     //if (IsUserName("Will")) TRACE( _T("X Scale = %f\n"),FracXScale);
04425     //if (IsUserName("Will")) TRACE( _T("Y Scale = %f\n"),FracYScale);
04426 
04427     // Get the 'display' fractal size in document units (MILLIPOINTS)
04428     INT32 FracDocWidth  = FracPixWidth  * PixelWidth;
04429     INT32 FracDocHeight = FracPixHeight * PixelWidth;
04430     // and find the origin.
04431     DocCoord FractalOrigin = DocCoord(Start.x - FracDocWidth/2, Start.y - FracDocHeight/2);
04432 
04433     //if (IsUserName("Will")) TRACE( _T("Fract Origin = %d,%d\n"),FractalOrigin.x, FractalOrigin.y);
04434     //if (IsUserName("Will")) TRACE( _T("Fract Width  = %d\n"),FracDocWidth);
04435     //if (IsUserName("Will")) TRACE( _T("Fract Height = %d\n"),FracDocHeight);
04436 
04437     // Make a rectangle describing the unscaled fractal bounds.
04438     DocRect FractRect = DocRect(FractalOrigin, FractalOrigin);
04439     FractRect.IncludePoint(DocCoord(FractalOrigin.x + FracDocWidth, 
04440                                     FractalOrigin.y + FracDocHeight));
04441 
04442     //if (IsUserName("Will")) TRACE( _T("Fractal Rect = %d,%d, %d,%d\n"),FractRect.lox, FractRect.loy,
04443     //                                                              FractRect.hix, FractRect.hiy);
04444 
04445     // Get the bounds of the Render Region.
04446     DocRect RRRect = GetClipRect();
04447 
04448     //if (IsUserName("Will")) TRACE( _T("RR Rect      = %d,%d, %d,%d\n"),RRRect.lox, RRRect.loy,
04449     //                                                              RRRect.hix, RRRect.hiy);
04450 
04451     // Clip the render region rect to the fractal rect.
04452     DocRect RRClipRect;
04453     if (RRRect.IsIntersectedWith(FractRect))
04454         RRClipRect = RRRect.Intersection(FractRect);
04455     else
04456         RRClipRect = DocRect(0,0,0,0);
04457 
04458     //if (IsUserName("Will")) TRACE( _T("RR Clip Rect = %d,%d, %d,%d\n"),RRClipRect.lox, RRClipRect.loy,
04459     //                                                              RRClipRect.hix, RRClipRect.hiy);
04460 
04461     // Find the offset of the clipped render region rect from the fractal origin.
04462     INT32 dx = (RRClipRect.lox - FractalOrigin.x) / PixelWidth;
04463     INT32 dy = (RRClipRect.loy - FractalOrigin.y) / PixelWidth;
04464 
04465     // Find the size of the bitmap, by scaling the clipped render region rect.
04466     INT32 BitmapPixWidth        = INT32((RRClipRect.Width()  / PixelWidth) * FracXScale);
04467     INT32 BitmapPixHeight   = INT32((RRClipRect.Height() / PixelWidth) * FracYScale);
04468 
04469     //if (IsUserName("Will")) TRACE( _T("Bitmap Width  = %d\n"),BitmapPixWidth);
04470     //if (IsUserName("Will")) TRACE( _T("Bitmap Height = %d\n"),BitmapPixHeight);
04471     //if (IsUserName("Will")) TRACE( _T("Bitmap Origin = %d,%d\n"),dx,dy);
04472 
04473     // The width and height to actually plot the bitmap.
04474     INT32 BitmapPlotWidth   = (RRClipRect.Width());
04475     INT32 BitmapPlotHeight  = (RRClipRect.Height());
04476 
04477     // Calculate the Dpi of the bitmap.
04478     INT32 Dpi = 72000/PixelWidth;
04479     //if (IsUserName("Will")) TRACE( _T("Dpi = %d\n"),Dpi);
04480 
04481     // Create the Bitmap !!
04482     FractalBitmap = new KernelBitmap(BitmapPixWidth, BitmapPixHeight, 8, Dpi);
04483 
04484     CWxBitmap *WinBM = (CWxBitmap*)FractalBitmap->ActualBitmap;
04485 
04486     // Bodge !!
04487     // Initialise the Bitmap so that areas that aren't plotted into come out white
04488 
04489     // Render the Fractal into the bitmap
04490     TheFractal.DoFill(FractalBitmap, FracPixDim, INT32(dx*FracXScale), INT32(dy*FracYScale));
04491 
04492     // convert ArtWorks style attribute into Gavin-style
04493     POINT PGram[3];
04494 
04495     PGram[0].x = RRClipRect.lox;                    PGram[0].y = RRClipRect.loy;
04496     PGram[1].x = RRClipRect.lox + BitmapPlotWidth;  PGram[1].y = RRClipRect.loy;
04497     PGram[2].x = RRClipRect.lox;                    PGram[2].y = RRClipRect.loy + BitmapPlotHeight;
04498 
04499     // get the colour we use to fill around the edges from the current solid fill colour
04500     COLORREF DefaultColour;
04501 
04502     DefaultColour = ConvertColourToTransScreenWord(CurrentColContext, &RR_FILLCOLOUR() );
04503 
04504     DWORD TranspStyle = 0;
04505 
04506     UINT32 TranspType = Fill->GetTranspType();
04507 
04508     TranspStyle  = (TranspType)<<8;
04509 //  TranspStyle |= WhichTiling;
04510     TranspStyle |= 2;
04511 
04512     *Style |= (TranspType + 6)<<8;
04513 
04514     // and finally ... plot the bitmat
04515     BOOL Result = GetDrawContext()->SetTransparentBitmapFill(
04516                             &(WinBM->BMInfo->bmiHeader),
04517                             WinBM->BMBytes,
04518                             TranspStyle,
04519                             PGram,
04520                             DefaultColour,
04521                             (LPBYTE*)pTranspTable,
04522                             0
04523                             );
04524 
04525     EndBusyCursor();
04526 */
04527     return TRUE;
04528 }
04529 
04530 
04531 
04532 
04533 /********************************************************************************************
04534 
04535 >   void GRenderRegion::DrawRect(DocRect *RectToRender)
04536 
04537     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
04538     Created:    7/12/93
04539     Inputs:     RectToRender is a pointer to a rectangle to render
04540     Outputs:    -
04541     Returns:    -
04542     Purpose:    Renders a rectangle using gavins routines. Rectangles are not anti-aliased.
04543     Errors:     -
04544     SeeAlso:    -
04545 
04546 ********************************************************************************************/
04547 
04548 void GRenderRegion::DrawRect(DocRect *RectToRender)
04549 {
04550     // If we are not drawing complex shapes and this shape is, then return
04551     if ((!RenderComplexShapes) && (TestForComplexShape(&Caps)))
04552         return;
04553 
04554     // If the rect given does not intersect the clip rect, then do not bother
04555     // Draw rect is only really used to draw the paper etc, so this check is not
04556     // generally performed in situ, which is why I do it here
04557     if (!RectToRender->IsIntersectedWith(CurrentClipRect))
04558         return;
04559 
04560     // OK, it intersects, but we should try to clip it with the inner rect
04561     DocRect DocDrawRect = RectToRender->Intersection(InnerRect);
04562     RECT    DrawRect;
04563     DrawRect.left   = DocDrawRect.lo.x;
04564     DrawRect.right  = DocDrawRect.hi.x;
04565     DrawRect.top    = DocDrawRect.hi.y;
04566     DrawRect.bottom = DocDrawRect.lo.y;
04567 
04568     RememberMe("DrawRect");
04569     HaveRenderedSomething = TRUE;
04570 
04571     // Render the rectangle
04572     if (SetFillGCol(RR_FILLCOLOUR()))
04573         GetDrawContext()->FillRectangle(&DrawRect);
04574 
04575     // And maybe stroke the outline of the rect if we need to
04576     if (SetGCol(RR_STROKECOLOUR()))
04577     {
04578         // build up a path so we can Fuzzy Clip and render it
04579         static BYTE  Verbs[4] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_LINETO | PT_CLOSEFIGURE};
04580         DocCoord Coords[4];
04581 
04582         // Fill in the coords to be going on with
04583         Coords[0].x = DocDrawRect.lo.x;
04584         Coords[0].y = DocDrawRect.lo.y;
04585 
04586         Coords[1].x = DocDrawRect.lo.x;
04587         Coords[1].y = DocDrawRect.hi.y;
04588 
04589         Coords[2].x = DocDrawRect.hi.x;
04590         Coords[2].y = DocDrawRect.hi.y;
04591 
04592         Coords[3].x = DocDrawRect.hi.x;
04593         Coords[3].y = DocDrawRect.lo.y;
04594 
04595         // draw a line around it
04596         StrokePath(Coords, Verbs, 4,
04597                    Coords, Verbs, 4, FALSE);
04598     }
04599 }
04600 
04601 /********************************************************************************************
04602 
04603 >   void GRenderRegion::DrawDragRect(DocRect *RectToRender)
04604 
04605     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
04606     Created:    7/12/93
04607     Inputs:     RectToRender is a pointer to a rectangle to render in EOR type mode.
04608     Outputs:    -
04609     Returns:    -
04610     Purpose:    Does NOTHING AT ALL as gdraw cannot do xor plotting
04611     Errors:     -
04612     SeeAlso:    -
04613 
04614 ********************************************************************************************/
04615 
04616 void GRenderRegion::DrawDragRect(DocRect *)
04617 {
04618     ENSURE(FALSE, "Gdraw cannot do DrawDragRect");
04619 }
04620 
04621 /********************************************************************************************
04622 
04623 >   void GRenderRegion::DrawBlob(DocCoord p, BlobType type)
04624 
04625     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
04626     Created:    7/12/93
04627     Inputs:     A point and a blob type
04628     Outputs:    -
04629     Returns:    -
04630     Purpose:    Does NOTHING AT ALL as gdraw cannot do xor plotting
04631     Errors:     -
04632     SeeAlso:    -
04633 
04634 ********************************************************************************************/
04635 
04636 void GRenderRegion::DrawBlob(DocCoord p, BlobType type)
04637 {
04638     // class GRenderClickColour needs to render the paper (for custom colour picker control)
04639     // BUT we also need to avoid firing off the ENSURE !!!!
04640     
04641     if (this->IsKindOf (CC_RUNTIME_CLASS (GRenderClick/*Colour*/)))
04642     {
04643         return;
04644     }
04645 
04646     ENSURE( FALSE, "GDraw cannot do blobs");
04647 
04648     DocRect MyBlob;
04649 
04650     OSRenderRegion::GetBlobRect( ScaleFactor, p, type, &MyBlob);
04651     DrawRect( &MyBlob );
04652 }
04653 
04654 /********************************************************************************************
04655 
04656 >   void GRenderRegion::DrawLine(const DocCoord &StartPoint, const DocCoord &EndPoint)
04657 
04658     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
04659     Created:    7/12/93
04660     Inputs:     Two points to render a line between
04661     Outputs:    -
04662     Returns:    -
04663     Purpose:    Renders a line using gdraw.
04664     Errors:     -
04665     SeeAlso:    -
04666 
04667 ********************************************************************************************/
04668 
04669 void GRenderRegion::DrawLine(const DocCoord &StartPoint, const DocCoord &EndPoint)
04670 {
04671     // If we are not drawing complex shapes and this shape is, then return
04672     if ((!RenderComplexShapes) && (TestForComplexShape(&Caps)))
04673         return;
04674 
04675     RememberMe("DrawLine");
04676     HaveRenderedSomething = TRUE;
04677 
04678     // Set the line colour
04679     if (!SetGCol( RR_STROKECOLOUR() ))
04680         return;
04681 
04682     // Build a path for gavin to render
04683     static PathVerb Verbs[2] = {PT_MOVETO, PT_LINETO};
04684     DocCoord Coords[2];
04685     DocCoord ClippedCoords[2];
04686     PathVerb ClippedVerbs[2];
04687 
04688     Coords[0] = StartPoint;
04689     Coords[1] = EndPoint;
04690 
04691     // Actually clip the path to the rectangles
04692     size_t Worked = FuzzyClip( (PPOINT)Coords, Verbs, 2, FALSE, (RECT*)(&InnerRect), (RECT*)(&OuterRect),
04693                             (PPOINT)(ClippedCoords), ClippedVerbs, 2);
04694 
04695     // Render it
04696     if (Worked==(size_t)-1)
04697     {
04698         StrokePath( Coords, Verbs, 2,
04699                     Coords, Verbs, 2, TRUE);
04700     }
04701     else
04702     {
04703         StrokePath( ClippedCoords, ClippedVerbs, (UINT32)Worked, 
04704                     Coords, Verbs, 2, TRUE);
04705     }
04706 }
04707 
04708 /********************************************************************************************
04709 
04710 >   void GRenderRegion::DrawBitmap(const DocCoord &Point, KernelBitmap* pBitmap)
04711 
04712     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04713     Created:    23/3/95
04714     Inputs:     Point - The Coord specifying the bottom left of the Bitmap.
04715                 pBitmap, the KernelBitmap to plot.
04716     Purpose:    Draws an un-scaled Bitmap.
04717                 Use this for drawing Icons for dialogue boxes etc.
04718                 The Bitmap can be any size, but will be plotted unscaled.
04719                 Note that 'Point' specifies where the bottom left of the bitmap will be.
04720 
04721 ********************************************************************************************/
04722 
04723 void GRenderRegion::DrawBitmap(const DocCoord &Point, KernelBitmap* pBitmap)
04724 {
04725     if (pBitmap == NULL)
04726         return;
04727 
04728     ENSURE( pBitmap->ActualBitmap->IsKindOf( CC_RUNTIME_CLASS( CWxBitmap ) ),
04729                                                                 "Strange bitmapfill");
04730     CWxBitmap *WinBM = (CWxBitmap*)pBitmap->ActualBitmap;
04731 
04732     // Check the Bitmap has some data in it
04733     if (
04734         (WinBM->BMInfo==NULL) ||
04735         (WinBM->BMBytes==NULL)
04736        )
04737         return;
04738 
04739     INT32 PixelSize = CalcPixelWidth();
04740 
04741     BitmapInfo Info;
04742     BOOL GotInfo = pBitmap->ActualBitmap->GetInfo( &Info );
04743 
04744     // Get the Bitmap width and height in Millipoints
04745     INT32 Width  = GotInfo ? Info.PixelWidth  * PixelSize : 16 * PixelSize;
04746     INT32 Height = GotInfo ? Info.PixelHeight * PixelSize : 16 * PixelSize;
04747         
04748     // Setup the Gavin control points
04749     POINT PGram[3];
04750     PGram[0].x = Point.x;               PGram[0].y = Point.y;
04751     PGram[1].x = Point.x + Width;       PGram[1].y = Point.y;
04752     PGram[2].x = Point.x;               PGram[2].y = Point.y + Height;
04753 
04754 
04755     // --- Colour-correct and/or Contone the bitmap as necessary
04756     RGBQUAD *Palette = NULL;
04757 
04758     // Do the colour correction. This may produce a new pointer in Palette,
04759     // which we should CCFree() when we are done with it - see the end of this function
04760     ColourCorrectBitmap(NULL, WinBM->BMInfo, &Palette);
04761 
04762     // If it didn't create a new palette for us, then we'll use the original one
04763     if (Palette == NULL)
04764         Palette = WinBM->BMInfo->bmiColors;
04765 
04766     DWORD Style = 1;        // GDraw bitmap-plotting style flagword
04767     BOOL bClearBitmapConv = FALSE;
04768 
04769     // --- Add Separation Style bits as approriate to the current colour separation mode
04770     // Currently, the only "separation" option we use is composite print preview
04771     // SepStyle for the SetBitmapFill functions are always in the MS byte of Style
04772 
04773     if (WinBM->GetBPP() > 8)    // Only needed for deep bitmaps
04774     {
04775         // If we've got a valid colour plate and it is a composite preview
04776         if (CurrentColContext->GetColourPlate() != NULL &&
04777             !CurrentColContext->GetColourPlate()->IsDisabled() &&
04778             CurrentColContext->GetColourPlate()->GetType() == COLOURPLATE_COMPOSITE)
04779         {
04780             // Find the colour manager (if there is one), and ask it for the 15-bit RGB
04781             // printer colour matching lookup table
04782 PORTNOTE("cms", "DisabledXaraCMS")
04783 #ifndef EXCLUDE_FROM_XARALX
04784             XaraCMS* lpCMSMan = GetApplication()->GetCMSManager();
04785             if (lpCMSMan != NULL)
04786             {
04787                 DWORD *MatchTable = lpCMSMan->GetPaperViewTable();
04788                 ERROR3IF(MatchTable == NULL, "Can't create/find colour matching table");
04789                 if (MatchTable != NULL)
04790                 {
04791                     GetDrawContext()->SetBitmapConversionTable((BGR *)MatchTable);
04792                     bClearBitmapConv = TRUE;
04793                     // Bits 3 and 4 of top byte of Style specifies the conversion algorithm
04794                     // Make sure it only affects the 2 bits
04795                     Style |= (BitmapConversion & 3) << 27;
04796                 }
04797             }
04798 #endif
04799         }
04800     }
04801 
04802     BYTE *BitmapBits = WinBM->BMBytes;
04803 
04804     // Plot the Bitmap
04805     GetDrawContext()->PlotBitmap(   &(WinBM->BMInfo->bmiHeader),
04806                     BitmapBits,
04807                     Style,
04808                     PGram,
04809                     Palette,
04810                     NULL, NULL, NULL,
04811                     NoTransTable
04812                     );
04813 
04814     // Free any memory used for colour-corrected bitmap palettes.
04815     // If this pointer doesn't point at the original palette, then it has
04816     // been temporarily allocated by ColourCorrectBitmap, above.
04817     if (Palette != WinBM->BMInfo->bmiColors)
04818         CCFree(Palette);
04819 
04820     if (bClearBitmapConv)
04821     {
04822         GetDrawContext()->SetBitmapConversionTable(NULL);
04823     }
04824 }
04825 
04826 
04827 
04828 /********************************************************************************************
04829 
04830 >   void GRenderRegion::DrawBitmap(const DocRect& rect, KernelBitmap* pBitmap)
04831 
04832     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04833     Created:    23/3/95
04834     Inputs:     Point - The Coord specifying the bottom left of the Bitmap.
04835                 pBitmap, the KernelBitmap to plot.
04836     Purpose:    Draws an un-scaled Bitmap.
04837                 Use this for drawing Icons for dialogue boxes etc.
04838                 The Bitmap can be any size, but will be plotted unscaled.
04839                 Note that 'Point' specifies where the bottom left of the bitmap will be.
04840 
04841 ********************************************************************************************/
04842 
04843 void GRenderRegion::DrawBitmap(const DocRect& rect, KernelBitmap* pBitmap)
04844 {
04845     if (pBitmap == NULL)
04846         return;
04847 
04848     ENSURE( pBitmap->ActualBitmap->IsKindOf( CC_RUNTIME_CLASS( CWxBitmap ) ),
04849                                                                 "Strange bitmapfill");
04850     CWxBitmap *WinBM = (CWxBitmap*)pBitmap->ActualBitmap;
04851 
04852     // Check the Bitmap has some data in it
04853     if (
04854         (WinBM->BMInfo==NULL) ||
04855         (WinBM->BMBytes==NULL)
04856        )
04857         return;
04858 
04859 //  INT32 PixelSize = CalcPixelWidth();
04860 
04861     // Setup the Gavin control points
04862     POINT PGram[3];
04863     PGram[0].x = rect.lo.x; PGram[0].y = rect.lo.y;
04864     PGram[1].x = rect.hi.x; PGram[1].y = rect.lo.y;
04865     PGram[2].x = rect.lo.x; PGram[2].y = rect.hi.y;
04866 
04867 
04868     // --- Colour-correct and/or Contone the bitmap as necessary
04869     RGBQUAD *Palette = NULL;
04870 
04871     // Do the colour correction. This may produce a new pointer in Palette,
04872     // which we should CCFree() when we are done with it - see the end of this function
04873     ColourCorrectBitmap(NULL, WinBM->BMInfo, &Palette);
04874 
04875     // If it didn't create a new palette for us, then we'll use the original one
04876     if (Palette == NULL)
04877         Palette = WinBM->BMInfo->bmiColors;
04878 
04879     DWORD Style = 1;        // GDraw bitmap-plotting style flagword
04880     BOOL bClearBitmapConv = FALSE;
04881 
04882     // --- Add Separation Style bits as approriate to the current colour separation mode
04883     // Currently, the only "separation" option we use is composite print preview
04884     // SepStyle for the SetBitmapFill functions are always in the MS byte of Style
04885     if (WinBM->GetBPP() > 8)    // Only needed for deep bitmaps
04886     {
04887         // If we've got a valid colour plate and it is a composite preview
04888         if (CurrentColContext->GetColourPlate() != NULL &&
04889             !CurrentColContext->GetColourPlate()->IsDisabled() &&
04890             CurrentColContext->GetColourPlate()->GetType() == COLOURPLATE_COMPOSITE)
04891         {
04892             // Find the colour manager (if there is one), and ask it for the 15-bit RGB
04893             // printer colour matching lookup table
04894 PORTNOTE("cms", "DisabledXaraCMS")
04895 #ifndef EXCLUDE_FROM_XARALX
04896             XaraCMS* lpCMSMan = GetApplication()->GetCMSManager();
04897             if (lpCMSMan != NULL)
04898             {
04899                 DWORD *MatchTable = lpCMSMan->GetPaperViewTable();
04900                 ERROR3IF(MatchTable == NULL, "Can't create/find colour matching table");
04901                 if (MatchTable != NULL)
04902                 {
04903                     GetDrawContext()->SetBitmapConversionTable((BGR *)MatchTable);
04904                     bClearBitmapConv = TRUE;
04905                     // Bits 3 and 4 of top byte of Style specifies the conversion algorithm
04906                     // Make sure it only affects the 2 bits
04907                     Style |= (BitmapConversion & 3) << 27;
04908                 }
04909             }
04910 #endif
04911         }
04912     }
04913     BYTE *BitmapBits = WinBM->BMBytes;
04914 
04915     // Plot the Bitmap
04916     GetDrawContext()->PlotBitmap(   &(WinBM->BMInfo->bmiHeader),
04917                     BitmapBits,
04918                     Style,
04919                     PGram,
04920                     Palette,
04921                     NULL, NULL, NULL,
04922                     NoTransTable
04923                     );
04924 
04925     // Free any memory used for colour-corrected bitmap palettes.
04926     // If this pointer doesn't point at the original palette, then it has
04927     // been temporarily allocated by ColourCorrectBitmap, above.
04928     if (Palette != WinBM->BMInfo->bmiColors)
04929         CCFree(Palette);
04930 
04931     if (bClearBitmapConv)
04932     {
04933         GetDrawContext()->SetBitmapConversionTable(NULL);
04934     }
04935 }
04936 
04937 
04938 
04939 /********************************************************************************************
04940 
04941 >   void GRenderRegion::DrawBitmap(const DocCoord &Point, UINT32 BitmapID, UINT32 ToolID = NULL)
04942 
04943     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04944     Created:    23/3/95
04945     Inputs:     Point - The Coord specifying the bottom left of the Bitmap.
04946                 BitmapID, the resource ID of the bitmap to plot.
04947                 ToolID, the optional ToolID of the tool containing the Bitmap resource.
04948     Purpose:    Draws an un-scaled Bitmap.
04949                 Use this for drawing Icons for dialogue boxes etc.
04950                 The Bitmap can be any size, but will be plotted unscaled.
04951                 Note that 'Point' specifies where the bottom left of the bitmap will be.
04952 
04953 ********************************************************************************************/
04954 
04955 void GRenderRegion::DrawBitmap(const DocCoord &Point, UINT32 BitmapID, UINT32 ToolID)
04956 {
04957     ERROR3IF( 0 != ToolID, "GRenderRegion::DrawBitmap can't cope with Tool resources yet" );
04958 
04959     KernelBitmap* pBitmap;
04960 
04961     // Make a new Oil Bitmap
04962     OILBitmap* pOilBmp = OILBitmap::Create();
04963     if (pOilBmp == NULL)
04964         return;
04965 
04966     // and copy the data from the resources
04967     pOilBmp->LoadBitmap(BitmapID);
04968 
04969     // Make a KernelBitmap and attach the Oil Bitmap
04970     pBitmap = new KernelBitmap(pOilBmp, TRUE);      // TRUE = temp bitmap
04971     if (pBitmap == NULL)
04972         return;
04973 
04974     // Plot the Bitmap
04975     DrawBitmap(Point, pBitmap);
04976 
04977     // Delete it (will also delete the Oil Bitmap)
04978     delete pBitmap;
04979 }
04980 
04981 
04982 /********************************************************************************************
04983 
04984 >   virtual void GRenderRegion::DrawFixedSystemText(StringBase *TheText,
04985                                                         DocRect &BoundsRect)
04986 
04987     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04988     Created:    2/4/95
04989     Inputs:     TheText - The string to render
04990                 BoundsRect - Determines where the text is to be plotted. The text will also
04991                 be clipped within this bounding rectangle if it exceeds the available space.
04992 
04993     Purpose:    To draw simple text, using the default host-operating-system font.
04994                 The size and style of this font are decided by the host OS (or oil code)
04995                 and cannot be set in any way. To determine how much space is needed to
04996                 display a string with this method, see the SeeAlso.
04997 
04998     Notes:      This method is intended solely for the use of kernel-rendered dialogues,
04999                 such as SuperGalleries, which need to display simple text information. It
05000                 should not be confused with document rendering of arbitrary text paths etc.
05001 
05002                 Currently, the text is drawn in a default manner (left justified and centered
05003                 vertically; one line of text only (no word-wrap onto subsequent lines), etc)
05004                 Do not use special characters such as tab/newline -their effect is undefined
05005 
05006                 NOTE: this GRenderRegion version of the function plots with BkMode OPAQUE.
05007 
05008     SeeAlso:    GRenderRegion::GetFixedSystemTextSize;
05009                 GRenderRegion::SetFixedSystemTextColours
05010 
05011 ********************************************************************************************/
05012 
05013 void GRenderRegion::DrawFixedSystemText(StringBase *TheText, DocRect &BoundsRect, UINT32 uFormat)
05014 {
05015     wxString Text = (wxString)(TCHAR *)(*TheText);
05016 
05017     wxFont SaveFont=RenderDC->GetFont();
05018 
05019     wxFont FixedFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
05020     FixedFont.SetPointSize(8);
05021     RenderDC->SetFont(FixedFont);
05022 
05023     wxDC * pDC = RenderDC;
05024     wxSize DPI = OSRenderRegion::GetFixedDCPPI(*pDC);
05025 //  INT32 XDPI = DPI.GetWidth();
05026 //  INT32 YDPI = DPI.GetHeight();
05027 //  INT32 LineHeight = RenderDC->GetCharHeight();
05028 
05029     wxCoord w, h;
05030     RenderDC->GetTextExtent(Text, &w, &h);
05031 
05032     RenderDC->SetFont(SaveFont);
05033 
05034     INT32 PixelWidth = CalcScaledPixelWidth();
05035     // Check for divide by zeros. Shouldn't happen but very bad when it happens on galleries
05036     ERROR3IF(PixelWidth == 0, "GRenderRegion::DrawFixedSystemText PixelWidth = 0");
05037     if (PixelWidth == 0)
05038         PixelWidth = 1;
05039 
05040     // Create a memory DC
05041     wxBitmap bitmap(w, h);
05042     wxMemoryDC MemDC;
05043     MemDC.SelectObject(bitmap);
05044     MemDC.SetFont(FixedFont);
05045 
05046     MemDC.SetBackgroundMode(wxSOLID);
05047 
05048     // Copy the Text colours from the RenderDC into the memory DC
05049     MemDC.SetTextForeground(RenderDC->GetTextForeground());
05050     MemDC.SetTextBackground(RenderDC->GetTextBackground());
05051 
05052     // Draw the text into the memory DC
05053     MemDC.DrawText((TCHAR *) (*TheText), 0, 0);
05054 
05055     KernelBitmap* pBitmap;
05056 
05057     // Make a new Oil Bitmap
05058     OILBitmap* pOilBmp = OILBitmap::Create();
05059     if (pOilBmp == NULL)
05060         return;
05061 
05062     // and copy the data from the resources
05063     ((CWxBitmap *)pOilBmp)->CreateFromwxBitmap(&bitmap);
05064 
05065     // Make a KernelBitmap and attach the Oil Bitmap
05066     pBitmap = new KernelBitmap(pOilBmp, TRUE);      // TRUE = temp bitmap
05067     if (pBitmap == NULL)
05068         return;
05069 
05070     // Calculate the orgin needed to centre the bitmap vertically
05071     INT32 Height = h * PixelWidth;
05072 
05073     DocCoord BottomLeft;
05074     BottomLeft.x = BoundsRect.lo.x;
05075     BottomLeft.y = (BoundsRect.lo.y + BoundsRect.Height()/2) - Height/2;
05076 
05077     GetDrawContext()->SetDefaultBitmapParameters();
05078     // Get gavin to plot the kernel bitmap
05079     DrawBitmap(BottomLeft, pBitmap);
05080 
05081     // Delete the Kernel Bitmap
05082     delete pBitmap;
05083 
05084 }
05085 
05086 
05087 
05088 /********************************************************************************************
05089 
05090 >   virtual void GRenderRegion::SetFixedSystemTextColours(DocColour *TextCol,
05091                                                          DocColour *Background)
05092 
05093     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05094     Created:    2/4/95
05095     Inputs:     TextCol - The foreground (text) colour (may be NULL)
05096                 Background - The background colour (may be NULL)
05097 
05098     Purpose:    To set the text and background colour(s) for any FixedSystem text rendered
05099                 in this render region in the future (within the current rendering pass).
05100 
05101     Notes:      If either of the colours is passed in as a NULL pointer, that colour will
05102                 not be set, and will remain at the previous setting.
05103 
05104                 Note that these values are passed directly to the host OS at the point
05105                 of calling, so you must call this method every time the colour is changed
05106                 (i.e. don't rely on just changing the DocColours that you passed in
05107                 originally, as they aren't remembered in any way). Note also that if you
05108                 call DrawFixedSystemText without a prior call to this method, the colours
05109                 used are undefined.
05110 
05111                 The colour chosen may not exactly match the colour requested - under
05112                 Windows, for example, the nearest solid (non-dithered) colour to that
05113                 requested will be used. Thus, it is best to stick to 'simple' colour
05114                 schemes.
05115 
05116                 This method may or may not affect some other rendering processes (for
05117                 example, under Windows, plotting of bitmaps may be affected by the
05118                 settings used here...)
05119 
05120     SeeAlso:    GRenderRegion::DrawFixedSystemText
05121 
05122 ********************************************************************************************/
05123 
05124 void GRenderRegion::SetFixedSystemTextColours(DocColour *TextCol, DocColour *Background)
05125 {
05126     if (TextCol != NULL)
05127     {
05128         COLORREF clr = ConvertColourToScreenWord(CurrentColContext, TextCol);
05129         RenderDC->SetTextForeground(clr);
05130     }
05131 
05132     if (Background != NULL)
05133     {
05134         COLORREF clr = ConvertColourToScreenWord(CurrentColContext, Background);
05135         RenderDC->SetTextBackground(clr);
05136     }
05137 }
05138 
05139 
05140 
05141 /********************************************************************************************
05142 
05143 >   virtual void GRenderRegion::GetFixedSystemTextSize(StringBase *TheText,
05144                                                         DocRect *BoundsRect)
05145 
05146     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05147     Created:    2/4/95
05148 
05149     Inputs:     TheText - The string to obtain the rendered size from
05150 
05151     Outputs:    BoundsRect - Returned with the size of the rectangle needed to display
05152                 said text string. This rect always has one corner at (0,0)
05153 
05154     Returns:    -
05155 
05156     Purpose:    To determine how much room is needed to plot a bit of text with
05157                 GRenderRegion::DrawFixedSystemText
05158 
05159     Notes:      If for any reason the call fails, an origin based rectangle with zero
05160                 height and width will be returned.
05161                 
05162     SeeAlso:    GRenderRegion::DrawFixedSystemText
05163 
05164 ********************************************************************************************/
05165 
05166 void GRenderRegion::GetFixedSystemTextSize(StringBase *TheText, DocRect *BoundsRect, double* atDpi)
05167 {
05168     ERROR3IF(TheText == NULL, "GRenderRegion::GetFixedSystemTextSize given a null text pointer");
05169     ERROR3IF(BoundsRect == NULL, "GRenderRegion::GetFixedSystemTextSize given a null bounds rect pointer");
05170     if(TheText == NULL || BoundsRect == NULL)
05171         return;
05172 
05173 
05174     wxString Text = (wxString)(TCHAR *)(*TheText);
05175 
05176     wxFont SaveFont=RenderDC->GetFont();
05177 
05178     wxFont FixedFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
05179     FixedFont.SetPointSize(8);
05180     RenderDC->SetFont(FixedFont);
05181 
05182     wxDC * pDC = RenderDC;
05183     wxSize DPI = OSRenderRegion::GetFixedDCPPI(*pDC);
05184     INT32 XDPI = DPI.GetWidth();
05185     INT32 YDPI = DPI.GetHeight();
05186     INT32 LineHeight = RenderDC->GetCharHeight();
05187 
05188     wxCoord w, h;
05189     RenderDC->GetTextExtent(Text, &w, &h);
05190 
05191     RenderDC->SetFont(SaveFont);
05192 
05193     // For some reason, Rect.bottom and Rect.top seem to be incorrect, so we have
05194     // to use the returned LineHeight value
05195 
05196     *BoundsRect = DocRect(0, 0,
05197                           (INT32)(((double)(w) * IN_MP_VAL) / XDPI),
05198                           (INT32)(((double)LineHeight * IN_MP_VAL) / YDPI) );
05199 
05200 }
05201 
05202 /********************************************************************************************
05203 
05204 >   BOOL GRenderRegion::DrawArrowHead(ArrowRec &ArrowToDraw,
05205                                       DocCoord &Centre, DocCoord &Direction)
05206 
05207     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05208     Created:    3/4/95
05209     Inputs:     An ArrowRec defining the Arrowhead, the Centre point of the Arrow and a 
05210                 point defining the direction of the Arrow.
05211     Purpose:    Draw an Arrow head on the start or end of a line.
05212     SeeAlso:    -
05213 
05214 ********************************************************************************************/
05215 
05216 BOOL GRenderRegion::DrawArrowHead(ArrowRec &ArrowToDraw,
05217                                   DocCoord &Centre, DocCoord &Direction)
05218 {
05219     // Call base class version for now.
05220     return RenderRegion::DrawArrowHead(ArrowToDraw, Centre, Direction);
05221 }
05222 
05223 /********************************************************************************************
05224 
05225 >   GMATRIX GRenderRegion::SetGavinMatrix(GMATRIX* GMatrix)
05226 
05227     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05228     Created:    6/4/95
05229     Inputs:     The new GMATRIX to use.
05230     Returns:    The old GMATRIX that was being used.
05231     Purpose:    Updates the GMATRIX used for rendering.
05232     SeeAlso:    GRenderRegion::MakeGavinMatrix
05233 
05234 ********************************************************************************************/
05235 
05236 GMATRIX GRenderRegion::SetGavinMatrix(GMATRIX* GMat)
05237 {
05238     // Get the current GMATRIX being used
05239     GMATRIX OldMatrix = CurrentGMatrix;
05240 
05241     // See if anyone wants to adjust the matrix
05242     if (!StartRenderAfter( GMat ))
05243         return OldMatrix;
05244 
05245     // Now update the current Matrix.
05246 
05247     // Why am I assigning each element individually ?
05248     // Don't ask me.  Ask the compiler why it can't
05249     // handle 'CurrentGMatrix = *GMat'
05250     CurrentGMatrix.AX = GMat->AX;
05251     CurrentGMatrix.AY = GMat->AY;
05252     CurrentGMatrix.BX = GMat->BX;
05253     CurrentGMatrix.BY = GMat->BY;
05254     CurrentGMatrix.CX = GMat->CX;
05255     CurrentGMatrix.CY = GMat->CY;
05256 
05257     // Set the new Matrix
05258     GetDrawContext()->SetMatrix( GMat );
05259 
05260     return OldMatrix;
05261 }
05262 
05263 
05264 
05265 
05266 /********************************************************************************************
05267 
05268 >   virtual GMATRIX GRenderRegion::MakeGavinMatrix(Matrix NewRenderMatrix, DocRect ClipRect, double dPixelsPerInch, BOOL bMasterCapture)
05269 
05270     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> (from Will (from Phil code))
05271     Created:    ??/??/2004
05272     Inputs:     The Kernel Matrix and cliprect to use to create the Gavin Matrix.
05273     Returns:    TRUE if the GMatrix was created ok.
05274     Purpose:    Make a Gavin Matrix out of a Kernel Matrix
05275     SeeAlso:    GRenderRegion::SetGavinMatrix
05276     Notes:      Doesn't rely on current state of CurrentClipRect like the above version
05277 
05278 ********************************************************************************************/
05279 
05280 GMATRIX GRenderRegion::MakeGavinMatrix(Matrix NewRenderMatrix, DocRect ClipRect, double dPixelsPerInch, BOOL bMasterCapture)
05281 {
05282     GMATRIX gmat;
05283     // Get the scale factors from the original render matrix
05284     FIXED16 abcd[4];
05285     INT32 ef[2];
05286     NewRenderMatrix.GetComponents( abcd, ef );
05287 
05288     // Use them to call DocRect to win on the clipping region, without attempting any translation.
05289     // Thus, the DocCoord cliprect gets turned directly into a Windows pixel values cliprect!
05290     Matrix UnscrolledRender(abcd[0], abcd[1], abcd[2], abcd[3], 0, 0);
05291 
05292     // in order to get Gavin's matrix calcs to agree with ours, we have to force him to
05293     // round before shifting down. We do this by adding half a pixel to the offsets in
05294     // his matrices. There is a school of thought which says that his matrix code
05295     // should be made to round, but it might have unpleasant side-effects. For now, we do
05296     // it this way. A pixel is 1<<(FX+16), so half a pixel is this incantation:
05297 
05298     // sjk's (5/12/00) preferred version as this works with the decimal places that may be in PixelsPerInch
05299     const XLONG Mult = (INT32)(dPixelsPerInch*(double)(1 << FX) + 0.5);
05300 
05301     gmat.AX = ( (XLONG)abcd[0].GetRawLong() * Mult ) / XLONG(72000);
05302     gmat.AY = ( (XLONG)abcd[1].GetRawLong() * Mult ) / XLONG(72000);
05303     gmat.BX = ( (XLONG)abcd[2].GetRawLong() * Mult ) / XLONG(72000);
05304     gmat.BY = ( (XLONG)abcd[3].GetRawLong() * Mult ) / XLONG(72000);
05305 
05306 #if 0 //_DEBUG
05307     // Check the translation in the matrix is a pixel multiple
05308     // Only run# check on integer ppi where an exact divisor into 72000
05309     if ( !Error::IsUserName("Gavin") )
05310         if (dPixelsPerInch == floor(dPixelsPerInch))
05311         {
05312             INT32 pixelmp = (INT32)(72000.0 / dPixelsPerInch);
05313             if ((double)(72000/pixelmp) == dPixelsPerInch)
05314             {
05315                 if ( (((INT64)(ef[0])) % pixelmp) || (((INT64)(ef[1])) % pixelmp) )
05316                 {
05317 //                  ERROR3("Render matrix on unaligned pixel boundary");
05318                     TRACE(_T("***********************************************"));
05319                     TRACE(_T("** Render matrix on unaligned pixel boundary **"));
05320                     TRACE(_T("***********************************************"));
05321                 }
05322             }
05323         }
05324 #endif
05325 
05326     // Use a version of OSRenderRegion::DocRectToWin that uses the actual dpi we have stored
05327     // in PixelsPerInch
05328     WinRect UnscrolledClip = OSRenderRegion::DocRectToWin(UnscrolledRender, ClipRect, dPixelsPerInch);
05329 
05330     // Now, the offsets to the Gavin bitmap are simply the corner of the Windows cliprect.
05331     // This needs to be the exclusive bottom value rather than the inclusive value returned 
05332     // by wxRect::GetBottom.  Hence we call our extra GetBottomEx function.
05333     INT32 xdisp = +UnscrolledClip.GetLeft();
05334     INT32 ydisp = -UnscrolledClip.GetBottomEx();
05335 
05336     // Make the offsets to the cliprect suitable for use by Gavin.
05337     // Just shift them up so the binary point is where he expects it...
05338     gmat.CX = -( (XLONG)xdisp * (XLONG)(1<<(FX+16)) );
05339     gmat.CY = -( (XLONG)ydisp * (XLONG)(1<<(FX+16)) );
05340 
05341 //  TRACE(_T("%08x %08x  %08x %08x\n"), gmat.AX, gmat.BX, (UINT32)(gmat.CX >> 32), (UINT32)(gmat.CX & 0xFFFFFFFF));
05342 //  TRACE(_T("%08x %08x  %08x %08x\n"), gmat.AY, gmat.BY, (UINT32)(gmat.CY >> 32), (UINT32)(gmat.CY & 0xFFFFFFFF));
05343 
05344     return gmat;
05345 }
05346 
05347 /********************************************************************************************
05348 
05349 >   BOOL GRenderRegion::SetGCol( DocColour &Col ) const
05350 
05351     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (Andy)
05352     Created:    15/04/94 (7/12/93)
05353     Inputs:     A DocColour object
05354     Outputs:    -
05355     Returns:    TRUE if not transparent, FALSE if transparent (i.e. don't bother rendering)
05356     Purpose:    Sets Gavins drawing colour. He does not distinguish between line & fill
05357                 colours - the caller has to do that.
05358     Errors:     -
05359     SeeAlso:    -
05360 
05361 ********************************************************************************************/
05362 
05363 BOOL GRenderRegion::SetGCol( DocColour &Col ) const
05364 {
05365     if ( Col.IsTransparent() )
05366         return FALSE;
05367 
05368     COLORREF rgbt;
05369     rgbt = ConvertColourToScreenWord(CurrentColContext, &Col);
05370 
05371     // get RGB value, or RGBT value if deep bitmap  
05372     // Find out about the line quality
05373     if (uBitmapDepth==32)
05374     {
05375         // Only do transparency if the line quality is better than black outline AND
05376         // the overall quality it not guide layer quality
05377         if ((RRQuality.GetLineQuality() >  Quality::BlackLine) && 
05378             (RRQuality.GetQuality()     != Quality::QualityGuideLayer))
05379         {
05380             DWORD Transp = *RR_STROKETRANSP()->GetStartTransp();
05381 
05382             DWORD Style = RR_STROKETRANSP()->GetTranspType();
05383 
05384             if (!(Style == 1 && Transp == 0))
05385             {
05386                 if (RenderFlags.HitDetect)
05387                     Style = T_REFLECTIVE;
05388 
05389                 rgbt |= Transp<<24;
05390                 GetDrawContext()->SetTransparency( rgbt, (TransparencyEnum)Style );
05391                 return(TRUE);
05392             }
05393         }
05394     }
05395 
05396     if (UseSolidColours)
05397     {
05398         // Determine the correct hinting value for the current output mode, and call gavin to
05399         // set up his offscreen bitmap.
05400         DWORD GavinHint = DIBUtil::GetGavinBlitFormat(ScreenDepth, uBitmapDepth, ScreenHinting);
05401         GetDrawContext()->SetSolidColour( rgbt, ScreenDepth, GavinHint);
05402     }
05403     else
05404         GetDrawContext()->SetColour( rgbt );
05405 
05406     return TRUE;
05407 }
05408 
05409 /********************************************************************************************
05410 
05411 >   BOOL GRenderRegion::SetFillGCol( DocColour &Col ) const
05412 
05413     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (Andy)
05414     Created:    15/04/94 (7/12/93)
05415     Inputs:     A DocColour object
05416     Outputs:    -
05417     Returns:    TRUE if not transparent, FALSE if transparent (i.e. don't bother rendering)
05418     Purpose:    Sets Gavins drawing colour. He does not distinguish between line & fill
05419                 colours - the caller has to do that.
05420     Errors:     -
05421     SeeAlso:    -
05422 
05423 ********************************************************************************************/
05424 
05425 BOOL GRenderRegion::SetFillGCol( DocColour &Col ) const
05426 {
05427     if ( Col.IsTransparent() )
05428         return FALSE;
05429 
05430     COLORREF rgbt;
05431 
05432     // If rendering to the hit-detect bitmap force all fill colours to black.
05433     if (RenderFlags.VeryMono)
05434         rgbt = RGB(0,0,0);
05435     else
05436         rgbt = ConvertColourToScreenWord(CurrentColContext, &Col);
05437 
05438     if (UseSolidColours)
05439     {
05440         // Determine the correct hinting value for the current output mode, and call gavin to
05441         // set up his offscreen bitmap.
05442         DWORD GavinHint = DIBUtil::GetGavinBlitFormat(ScreenDepth, uBitmapDepth, ScreenHinting);
05443         GetDrawContext()->SetSolidColour( rgbt, ScreenDepth, GavinHint);
05444     }
05445     else
05446         GetDrawContext()->SetColour( rgbt );
05447 
05448     return TRUE;
05449 }
05450 
05451 /********************************************************************************************
05452 
05453 >   void GRenderRegion::SetSolidColours(BOOL SetSolid)
05454 
05455     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
05456     Created:    11/5/95
05457     Inputs:     TRUE to turn off dithering of colours
05458     Purpose:    Allows the dithering of colours to be turned off so they look the same
05459                 using GDraw as they do with the GDI.
05460 
05461 ********************************************************************************************/
05462 
05463 void GRenderRegion::SetSolidColours(BOOL SetSolid)
05464 {
05465     UseSolidColours = SetSolid;
05466 }
05467 
05468 /********************************************************************************************
05469 
05470 >   MILLIPOINT GRenderRegion::CalcPixelWidth()
05471 
05472     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
05473     Created:    24/4/94
05474     Returns:    The size of a pixel in MILLIPOINTS
05475     Purpose:    Calculates the size of a Pixel in MILLIPOINTS, based on the output DPI
05476                 but IGNORES the scale factor.
05477     SeeAlso:    GetScaledPixelWidth()
05478 
05479 ********************************************************************************************/
05480 
05481 MILLIPOINT GRenderRegion::CalcPixelWidth()
05482 {
05483     return MILLIPOINT( MILLIPOINTS_PER_INCH / PixelsPerInch);
05484 }
05485 
05486 /********************************************************************************************
05487 
05488 >   double GRenderRegion::CalcPixelWidthDouble()
05489 
05490     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
05491     Created:    20/02/2006
05492     Returns:    The size of a pixel in a double
05493     Purpose:    Calculates the size of a Pixel in MILLIPOINTS, based on the output DPI
05494                 but IGNORES the scale factor.
05495     SeeAlso:    GetScaledPixelWidth()
05496 
05497 ********************************************************************************************/
05498 
05499 double GRenderRegion::CalcPixelWidthDouble()
05500 {
05501     return MILLIPOINTS_PER_INCH / PixelsPerInch;
05502 }
05503 
05504 /********************************************************************************************
05505 
05506 >   MILLIPOINT GRenderRegion::CalcScaledPixelWidth()
05507 
05508     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
05509     Created:    25/4/94
05510     Returns:    The size of a pixel in MILLIPOINTS
05511     Purpose:    Calculates the size of a Pixel in MILLIPOINTS, based on the output DPI
05512                 and current scale factor.
05513     SeeAlso:    CalcPixelWidth()
05514 
05515 ********************************************************************************************/
05516 
05517 MILLIPOINT GRenderRegion::CalcScaledPixelWidth()
05518 {
05519     MILLIPOINT spw = (MILLIPOINT)( MILLIPOINTS_PER_INCH/(PixelsPerInch*ScaleFactor.MakeDouble()) + 0.5 );
05520     ERROR3IF(spw==0, "CalcScaledPixelWidth attempting to set a 0 value");
05521     return spw;
05522 }
05523 
05524 
05525 
05526 /********************************************************************************************
05527 
05528 >   double GRenderRegion::CalcScaledPixelWidthDouble()
05529 
05530     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
05531     Created:    20/02/2006
05532     Returns:    The size of a pixel in a double
05533     Purpose:    Calculates the size of a Pixel in MILLIPOINTS, based on the output DPI
05534                 and current scale factor.
05535     SeeAlso:    CalcPixelWidthDouble()
05536 
05537 ********************************************************************************************/
05538 
05539 double GRenderRegion::CalcScaledPixelWidthDouble()
05540 {
05541     double spw = MILLIPOINTS_PER_INCH/(PixelsPerInch*ScaleFactor.MakeDouble());
05542     ERROR3IF(spw==0, "CalcScaledPixelWidthDOuble attempting to set a 0 value");
05543     return spw;
05544 }
05545 
05546 
05547 
05548 /********************************************************************************************
05549 
05550 >   double GRenderRegion::GetScaledPixelWidthDouble()
05551 
05552     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
05553     Created:    25 September 2000
05554 
05555     Purpose:    Returns the true scaled pixel width of this GRenderRegion, to the accuracy
05556                 of a double. GetScaledPixelWidth() returns a whole number, which is highly
05557                 inaccurate at high zooms - eg SPW at 6031% is usually 750 / 60.31 = 12.44ish
05558                 but GetScaledPixelWidth() returns 12. This method is useful if your code
05559                 needs precise conversion between millipoints and pixels.
05560 
05561     Notes:      USE AT YOUR PERIL!!!
05562 
05563                 PLEASE Note that if you mix and match GetScaledPixelWidthDouble() with
05564                 GetScaledPixelWidth(), you are HIGHLY likely to run into problems. Most of
05565                 Camelot uses the original GetScaledPixelWidth(), so if you do decide to use
05566                 this version, watch out for any interaction problems with the rest of the App!
05567 
05568     See also:   GetScaledPixelWidth().
05569 
05570 ********************************************************************************************/
05571 double GRenderRegion::GetScaledPixelWidthDouble()
05572 {
05573     return dScaledPixelWidth;
05574 }
05575 
05576 
05577 
05578 void GRenderRegion::InitClipping()
05579 {
05580     RememberMe("InitClipping");
05581 
05582     GetDrawContext()->ClipRectangle( (LPRECT)&CurrentClipRect );
05583     IsPaperRendered = FALSE;
05584 }
05585 
05586 void GRenderRegion::InitAttributes()
05587 {
05588 }
05589 
05590 void GRenderRegion::SetLineAttributes()
05591 {
05592 }
05593 
05594 void GRenderRegion::SetFillAttributes()
05595 {
05596 }
05597 
05598 void GRenderRegion::SetOSDrawingMode()
05599 {
05600     ENSURE( DrawingMode != DM_EORPEN, "Gdraw cannot EOR");
05601 }
05602 
05603 /********************************************************************************************
05604 
05605 >   void GRenderRegion::SetQualityLevel()
05606 
05607     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
05608     Created:    30/11/94
05609     Purpose:    Called after the Quality setting has been changed on the region. We have
05610                 to recalculate the antialiasing & flatness settings. Also used by
05611                 StartRender.
05612 
05613 ********************************************************************************************/
05614 
05615 void GRenderRegion::SetQualityLevel()
05616 {
05617     const BOOL Anti = (RRQuality.GetAntialiasQuality() < Quality::FullAntialias) ? FALSE : TRUE;
05618     GetDrawContext()->SetAntialiasFlag( Anti );
05619 
05620     if (Anti)
05621     {
05622         GetDrawContext()->SetAntialiasQualityFlag(HighQualityAA);
05623     }
05624 
05625     // Set up flatness...
05626     // Gavin recommends half-pixel smoothing. One pixel is 72000/dpi millipoints
05627     //INT32 Flatness = (72000L / PixelsPerInch.MakeLong()) / 2;
05628     INT32 Flatness = (INT32)((MILLIPOINTS_PER_INCH / PixelsPerInch) / 2);
05629     Flatness = LongDivFixed16( Flatness, ScaleFactor );
05630     if (Anti)
05631         Flatness /= 5;
05632     GetDrawContext()->SetFlatness( Flatness );
05633 }
05634 
05635 
05636 void GRenderRegion::Restore(RenderRegion*)
05637 {
05638 }
05639 
05640 /********************************************************************************************
05641 
05642 >   BOOL GRenderRegion::AttachDevice(View* ViewToAttach, CDC *pCDC, Spread *pSpread)
05643 
05644     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
05645     Created:    7/12/93
05646     Inputs:     ViewToAttach is the output view, pCDC is the destination DC, pSpread is which
05647                 spread we are rendering.
05648     Returns:    TRUE if attached ok;
05649                 FALSE if not.
05650     Purpose:    Gets ready to do actual rendering. In this case it does nothing.
05651                 bitmap.
05652     Errors:     Same as base class.
05653     SeeAlso:    RenderRegion::AttachDevice; GRenderRegion::InitDevice
05654 
05655 ********************************************************************************************/
05656 
05657 BOOL GRenderRegion::AttachDevice(View* ViewToAttach, wxDC *pDC, Spread *pSpread, bool fOwned /*= false*/)
05658 {
05659     RememberMe("AttachDevice");
05660 
05661     // Call the base class *first*
05662     BOOL Result = RenderRegion::AttachDevice( ViewToAttach, pDC, pSpread, fOwned );
05663 
05664     // Gives us a colour context if there is no render view
05665     if (RenderView==NULL)
05666         CurrentColContext = ColourContext::GetGlobalDefault(COLOURMODEL_RGBT);
05667 
05668     // return the result
05669     return Result;
05670 }
05671 
05672 /********************************************************************************************
05673 
05674 >   BOOL GRenderRegion::InitDevice()
05675 
05676     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
05677     Created:    27/05/94
05678     Returns:    TRUE if initialised ok;
05679                 FALSE if not.
05680     Purpose:    Initialise the device specific mechanisms for this render region. IN this
05681                 case the bitmap is allocated, so can fail.
05682     Errors:     Same as base class.
05683     SeeAlso:    RenderRegion::InitDevice; GRenderRegion::AttachDevice
05684 
05685 ********************************************************************************************/
05686 
05687 BOOL GRenderRegion::InitDevice()
05688 {
05689     ENSURE(MasterCaptureIsCurrent() || GetCaptureDepth()==0, "InitDevice called when captures running");
05690     RememberMe("InitDevice");
05691 
05692     // Call the base class *first*
05693     BOOL Worked = RenderRegion::InitDevice();
05694 
05695     if (!Worked)
05696         return FALSE;
05697 
05698     // Make sure we only set WRect ONCE!
05699     if ( LocalBitmap && WRect==wxRect(0,0,0,0) )
05700     {
05701 //      WRect = OSRenderRegion::DocRectToWin( RenderView, RenderMatrix, CurrentClipRect, 0,0,0,0 );
05702         WRect = OSRenderRegion::DocRectToWin( RenderMatrix, CurrentClipRect, PixelsPerInch );
05703     }
05704 
05705     // Make sure rectangle is sensible size...
05706     ERROR2IF(WRect.width==0 || WRect.height==0, FALSE, "GRenderRegion::InitDevice was passed a rectangle with zero size");
05707     if (WRect.width == 0 || WRect.height == 0)
05708         return FALSE;
05709     
05710     // Make sure the rectangle is ok
05711     ERROR2IF(WRect.width<0  || WRect.height<0 , FALSE, "GRenderRegion::InitDevice was passed a rectangle with -ve size");
05712     if (WRect.width < 0 || WRect.height < 0)
05713         return FALSE;
05714 
05715     // Nothing rendered yet
05716     SetClean(FALSE, FALSE);
05717 
05718     return TRUE;
05719 }
05720 
05721 
05722 /********************************************************************************************
05723 
05724 >   RenderRegion* GRenderRegion::Create(DocRect ClipRegion, Matrix ConvertMatrix, 
05725                                         FIXED16 ViewScale,  RenderType rType,
05726                                         View *pView = NULL)
05727 
05728     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
05729     Created:    7/12/93
05730     Inputs:     -
05731     Outputs:    -
05732     Returns:    Pointer to a render region if we can use gdraw, else NULL (if not a screen
05733                 type, or gdraw disabled, or not compatible with this machine).
05734     Purpose:    Determines whether a GRenderRegion can be created for rendering. A NULL return
05735                 should NOT be tested with ENSURE, it is a perfectly valid return result.
05736     Errors:     -
05737     SeeAlso:    -
05738 
05739 ********************************************************************************************/
05740 
05741 RenderRegion* GRenderRegion::Create(DocRect ClipRegion, Matrix ConvertMatrix, FIXED16 ViewScale,
05742                                     RenderType rType, View* pView, BOOL bForce32BPP)
05743 {
05744     if (CanDoGDraw && WantDoGDraw)
05745     {
05746         if (rType==RENDERTYPE_SCREEN)
05747         {
05748 PORTNOTE("other","We no longer handle less than 32bit per pixel")
05749             UINT32 BitmapDepthWanted = 32; // ScreenDepth;          // default to screen
05750             if (WantGDrawDepth)
05751                 BitmapDepthWanted = WantGDrawDepth;                 // override if user wants to
05752 
05753             // Find out from the associated DocView/Document whether the document requires
05754             // 32-bit transparency mode.  By default we don't.
05755             if (pView != NULL)
05756             {
05757                 // if in outline quality then don't go transparent.
05758                 // ideally would like it to be 1-bit, but the pastboard won't render in that case
05759                 if (pView->RenderQuality.GetLineQuality() != Quality::BlackLine)
05760                 {
05761                     BitmapDepthWanted = 32;
05762                 }
05763 
05764                 // If we are in less than 16 bpp and we want error diffusing then force 32 bpp
05765                 if (BitmapDepthWanted < 16)
05766                 {
05767                     if ((ViewDither == 0) || (ViewDither == 1) || (ViewDither == 3))
05768                         BitmapDepthWanted = 32;
05769                 }
05770             }
05771 
05772             // FORCE depth to 32bpp when needed (input flag)
05773             if (bForce32BPP)
05774                 BitmapDepthWanted = 32;
05775 
05776             // GDraw cannot do 24-bit bitmaps, so use 32-bit ones
05777             if (BitmapDepthWanted == 24)
05778                 BitmapDepthWanted = 32;
05779 
05780             GRenderRegion * pRegion = NULL;
05781 
05782 //          #if REAL_DDB
05783 //          if ((BlitMode == BLITMODE_BADDDB) && (BitmapDepthWanted == 8))
05784 //              pRegion = new GRenderDDB(ClipRegion, ConvertMatrix, ViewScale, BitmapDepthWanted, LogPixelsX);
05785 //          else
05786 //          #endif
05787 //          if (WantWinG && GRenderWinG::CanWinG(BitmapDepthWanted))
05788 //              pRegion = new GRenderWinG(ClipRegion, ConvertMatrix, ViewScale, BitmapDepthWanted, LogPixelsX);
05789 //          else
05790 //              TRACE(_T("Creating SCREEN region (%d, %d) - (%d, %d)  GRenderDIB\n"), ClipRegion.lo.x, ClipRegion.lo.y, ClipRegion.hi.x, ClipRegion.hi.y);
05791                 pRegion = new GRenderDIB(ClipRegion, ConvertMatrix, ViewScale, BitmapDepthWanted, LogPixelsX);
05792 
05793             if ((pView != NULL) && (pRegion != NULL))
05794             {
05795                 // If we have a view and we got a region then set the dither style
05796                 pRegion->SetDitherStyle8Bit(ViewDither);
05797 
05798                 // Now check for separated rendering and alter the RRCaps of the new region
05799                 // to simulate a printing render region
05800             if (pView->GetColourPlate() != NULL && !pView->GetColourPlate()->IsDisabled())
05801                 {
05802                     ColourPlateType PlateType = pView->GetColourPlate()->GetType();
05803                     if (PlateType != COLOURPLATE_NONE && PlateType != COLOURPLATE_COMPOSITE)
05804                     {
05805                         // First try to set this view to using a printing colour context
05806                         // so the separations appear the same on screen as on the printer
05807 PORTNOTE("cms", "DisabledXaraCMS")
05808 #ifndef EXCLUDE_FROM_XARALX
05809                         XaraCMS* ptheCMS=GetApplication()->GetCMSManager();
05810                         if (ptheCMS != NULL)
05811                         {
05812                             String_256 PrintProfile;
05813                             ptheCMS->GetPrinterProfile(&PrintProfile);
05814                             ColourContext *pContext = new ColourContextCMYK(pView, &PrintProfile);
05815                             if (pContext)
05816                                 pView->SetColourContext(COLOURMODEL_CMYK, pContext);
05817                         }
05818 #endif
05819                         // Now check what sort of printer we have to get the RenderRegion Caps correct
05820                         UINT32 PrintType = CCPrintDialog::IsPostscript() ? 2 : 1;
05821                         pRegion->SetSimulatePrinting(PrintType);
05822                     }
05823                 }
05824             }
05825 
05826             // return the region pointer
05827             return(pRegion);
05828         }
05829         else if ((rType==RENDERTYPE_PRINTER) || (rType==RENDERTYPE_PRINTER_PS))
05830         {
05831             // Always use 24 bit for printers, which means 32bit because Gavin can't do
05832             // 24-bit bitmaps.
05833             UINT32 BitmapDepth = 32;
05834 
05835             // Get document pointer
05836             Document* pDoc = pView->GetDoc();
05837 
05838             // Get print information for this document.
05839             PrintComponent *pPrint = 
05840                 (PrintComponent *) pDoc->GetDocComponent(CC_RUNTIME_CLASS(PrintComponent));
05841             ERROR2IF(pPrint == NULL, NULL, "Unable to find PrintComponent in document.");
05842 
05843             PrintControl *pPrintControl = pPrint->GetPrintControl();
05844             ERROR2IF(pPrintControl == NULL, NULL, 
05845                      "Unable to find PrintControl object in document component.");
05846 
05847             // Find out what DPI to use...
05848             INT32 PrintDPI = pPrintControl->GetDotsPerInch();
05849 
05850             return new GRenderPrint(ClipRegion, ConvertMatrix, ViewScale, 
05851                                     BitmapDepth, PrintDPI);
05852         }
05853     }
05854 
05855     return NULL;
05856 }
05857 
05858 
05859 
05860 /********************************************************************************************
05861 
05862 >   void GRenderRegion::DisplayLtoHBitmap()
05863 
05864     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com> (based on Gavin)
05865     Created:    4/3/94
05866     Inputs:     -
05867     Outputs:    -
05868     Returns:    -
05869     Purpose:    Slightly misleading name for historic reasons. Actually plots any depth
05870                 bitmap on any device, without any special handling. Use as a fallback
05871                 when the more specialist versions are not suitable.
05872 
05873 ********************************************************************************************/
05874 
05875 void GRenderRegion::DisplayLtoHBitmap()
05876 {
05877     DWORD *rgb = (DWORD *)pBitmapInfo->bmiColors ;
05878 
05879     // note that the number of RGBs used here must agree with the number allocated in
05880     // AllocDIB for each and every bitmap depth
05881 
05882     switch ( uBitmapDepth )
05883     {
05884         case 1 :
05885             *rgb++ = 0x000000 ;
05886             *rgb++ = 0xffffff ;
05887             break ;
05888         case 4 :
05889             *rgb++ = 0x000000 ; *rgb++ = 0x800000 ; *rgb++ = 0x008000 ; *rgb++ = 0x808000 ;
05890             *rgb++ = 0x000080 ; *rgb++ = 0x800080 ; *rgb++ = 0x008080 ; *rgb++ = 0x808080 ;
05891             *rgb++ = 0xc0c0c0 ; *rgb++ = 0xff0000 ; *rgb++ = 0x00ff00 ; *rgb++ = 0xffff00 ;
05892             *rgb++ = 0x0000ff ; *rgb++ = 0xff00ff ; *rgb++ = 0x00ffff ; *rgb++ = 0xffffff ;
05893             break ;
05894         case 16 :
05895             *rgb++ = 0x7c00 ;
05896             *rgb++ = 0x03e0 ;
05897             *rgb++ = 0x001f ;
05898             break ;
05899         case 32 :
05900             *rgb++ = 0x00ff0000 ;
05901             *rgb++ = 0x0000ff00 ;
05902             *rgb++ = 0x000000ff ;
05903             break ;
05904     }
05905 
05906     PlotBitmap( DIB_RGB_COLORS );
05907 }
05908 
05909 /********************************************************************************************
05910 
05911 >   void GRenderRegion::DisplayHto8Bitmap()
05912 
05913     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com> (based on Gavin)
05914     Created:    4/3/94
05915     Inputs:     -
05916     Outputs:    -
05917     Returns:    -
05918     Purpose:    Plot high colour bitmap (16 or 32-bits) to a 256 colour device. If we let
05919                 GDI do this it would take a very long time, so we convert to an intermediate
05920                 bitmap first. NEW - also plots to a 16-colour device. Will ENSURE if not 16-
05921                 or 256-colours.
05922 
05923 ********************************************************************************************/
05924 /*
05925 void GRenderRegion::DisplayHto8Bitmap()
05926 {
05927     // this is a test clause that skips the colour conversion.
05928     // Draws very slowly though.
05929     if (WantHighColourDirect)
05930     {
05931         DisplayLtoHBitmap();
05932         return;
05933     }
05934 
05935     //if ((ScreenDepth != 4) && (ScreenDepth != 8))
05936     //{
05937     //  ERROR3("Wrong screen depth in DisplayHto8");
05938     //  return;
05939     //}
05940 
05941     LPBITMAPINFOHEADER lpBitmapHeader = &lpBitmapInfo->bmiHeader;
05942     INT32 BWidth  = (INT32)lpBitmapHeader->biWidth;
05943     INT32 BHeight = (INT32)lpBitmapHeader->biHeight;
05944 
05945     INT32 DestX = WRect.x;
05946     INT32 DestY = WRect.y;
05947     INT32 RectWidth = WRect.width;
05948     INT32 RectHeight= WRect.height;
05949 
05950     INT32 SourceX = ScreenRect.x;
05951     INT32 SourceY = ScreenRect.y;
05952 
05953     INT32 StripBottom = BHeight;
05954     INT32 StripTop = 0;
05955 
05956     RECT UsedRect;
05957 
05958     if (GetDrawContext()->GetChangedBBox(&UsedRect) &&
05959         UsedRect.right > UsedRect.left &&
05960         UsedRect.bottom > UsedRect.top)
05961     {
05962         // blit less, thanks to changedBBox
05963 
05964         // Gavin usefully returns his rectangles the wrong way up
05965         // he returns x1,y1,x2,y2 and we want
05966         // x1,h-y2,x2,h-y1
05967 
05968         const INT32 ChangeX = UsedRect.left;
05969         SourceX += ChangeX;
05970         DestX += ChangeX;
05971 
05972         INT32 ChangeY = RectHeight - UsedRect.bottom;
05973     
05974         SourceY += ChangeY;
05975         DestY += ChangeY;
05976 
05977         RectWidth = UsedRect.right - UsedRect.left;
05978         RectHeight = UsedRect.bottom - UsedRect.top;
05979         
05980     
05981         if (UsedRect.top > 4)
05982         {
05983             // Allow 4 pixels extra
05984             StripTop = UsedRect.top - 4;
05985 
05986             // Round down to multiple of 4 to avoid dither alignment problems
05987             StripTop = StripTop & ~3;
05988         }
05989 
05990         // Allow 4 pixels extra
05991         StripBottom = UsedRect.bottom + 4;
05992     
05993         // Round up to multiple of 4 to avoid dither alignment problems
05994         StripBottom = (StripBottom + 3) & ~3;
05995         
05996         // Clip to bitmap height
05997         if (StripBottom > BHeight)
05998             StripBottom = BHeight;
05999     }
06000     else
06001     {
06002         TRACEUSER( "Gerry", _T("Empty clip rectangle in DisplayHto8\n"));
06003         return;
06004     }
06005 
06006     INT32 StripHeight = StripBottom - StripTop;
06007 
06008     // Copy the source bitmap header for the strip header
06009     BITMAPINFOHEADER SourceHeader = *lpBitmapHeader;
06010 
06011     // Calculate the size of a source scanline
06012     DWORD SourceScanSize = DIBUtil::ScanlineSize(SourceHeader.biWidth, SourceHeader.biBitCount);
06013 
06014     // Set the height and size of the strip
06015     SourceHeader.biHeight = StripHeight;
06016     SourceHeader.biSizeImage = StripHeight * SourceScanSize;
06017 
06018     INT32 StripDepth = ScreenDepth;
06019 
06020     // this is like a BITMAPINFO but with 256 colours
06021     struct
06022     {
06023         BITMAPINFOHEADER bmiHeader;
06024         RGBQUAD bmiColors[256];
06025     } DBitmapInfo;
06026 
06027     DBitmapInfo.bmiHeader.biSize            = sizeof(BITMAPINFOHEADER);
06028     DBitmapInfo.bmiHeader.biWidth           = BWidth;
06029     DBitmapInfo.bmiHeader.biHeight          = StripHeight;
06030     DBitmapInfo.bmiHeader.biPlanes          = 1;
06031     DBitmapInfo.bmiHeader.biBitCount        = StripDepth;
06032     DBitmapInfo.bmiHeader.biCompression     = BI_RGB;
06033     DBitmapInfo.bmiHeader.biSizeImage       = DIBUtil::ScanlineSize(BWidth, StripDepth) * StripHeight;
06034     DBitmapInfo.bmiHeader.biXPelsPerMeter   = 100;
06035     DBitmapInfo.bmiHeader.biYPelsPerMeter   = 100;
06036     DBitmapInfo.bmiHeader.biClrUsed         = 1 << StripDepth;
06037     DBitmapInfo.bmiHeader.biClrImportant    = 0;
06038 
06039     const LPBYTE DBitmap = (LPBYTE)CCMalloc( DBitmapInfo.bmiHeader.biSizeImage );
06040 
06041     if (DBitmap == NULL)
06042     {
06043         ERROR3( "Low mem in Hto8 - will display v. slowly" );
06044         // display something at least, though this is not an ideal solution.
06045         DisplayLtoHBitmap();
06046         return;
06047     }
06048 
06049     // Get the right context for the convert bitmap
06050     GDrawContext *GDC = GetStaticDrawContext(DitherStyle8Bit);
06051 
06052     // Offset source coord by distance of strip in from edge
06053     SourceY -= (BHeight - StripBottom);
06054     if (SourceY < 0)
06055         SourceY = 0;
06056 
06057     // Get the pointer to the correct scan line
06058     LPBYTE SourceBits = lpBits + (StripTop * SourceScanSize);
06059 
06060     INT32 ColourFlag;           // ColourFlag for the PlotBitmap call below
06061 
06062     if (StripDepth == 4)
06063     {
06064         // In 4 bpp we need a LOGPALETTE structure so we can
06065         // call GDrawContext::SetConversionPalette()
06066         struct {
06067             WORD palVersion;
06068             WORD palNumEntries;
06069             PALETTEENTRY palPalEntry[16];
06070         } LogPal = {0x300, 16};
06071 
06072         // Get the screen DC
06073         HDC hDC = ::GetDC(NULL);
06074 
06075         if (hDC != NULL)
06076         {
06077             // Get the 16 palette entries from the system palette
06078             // into the LOGPALETTE
06079             GetSystemPaletteEntries(hDC,
06080                                 0,
06081                                 16,
06082                                 LogPal.palPalEntry);
06083 
06084             RGBQUAD *rgb = DBitmapInfo.bmiColors;
06085 
06086             // Swap R and B.
06087             size_t i;
06088             for (i = 0; i < 16; i++ )
06089             {
06090                 PALETTEENTRY &PalRef = LogPal.palPalEntry[i];
06091 
06092                 rgb->rgbRed = PalRef.peRed;
06093                 rgb->rgbGreen = PalRef.peGreen;
06094                 rgb->rgbBlue = PalRef.peBlue;
06095                 rgb->rgbReserved = 0;
06096                 rgb++;
06097             }
06098 
06099             // Release the DC
06100             ::ReleaseDC(NULL, hDC);
06101         }
06102 
06103         ColourFlag = DIB_RGB_COLORS;
06104 
06105         // Tell GDraw to use the palette
06106         GDC->SetConversionPalette((PLOGPALETTE)&LogPal);
06107 
06108         GDC->ConvertBitmap(&SourceHeader, SourceBits,
06109                             &(DBitmapInfo.bmiHeader), DBitmap, DitherStyle8Bit);
06110 
06111         // Stop GDraw using the palette before it goes out of scope
06112         GDC->SetConversionPalette(NULL);
06113     }
06114     else
06115     {   
06116     
06117         ColourFlag = SetPaletteEntries((LPBITMAPINFO)&DBitmapInfo, RenderDC);
06118 
06119         GDC->ConvertBitmap(&SourceHeader, SourceBits,
06120                             &(DBitmapInfo.bmiHeader), DBitmap, DitherStyle8Bit);
06121     }
06122 
06123     PlotBitmap(RenderDC, ColourFlag, (LPBITMAPINFO)&DBitmapInfo, DBitmap, DestX, DestY,
06124                 RectWidth, RectHeight, hPalette, SourceX, SourceY);
06125 
06126     CCFree(DBitmap);
06127 }
06128 */
06129 /********************************************************************************************
06130 
06131 >   UINT32 SetPaletteEntries( LPBITMAPINFO lpBmi );
06132 
06133     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com> (based on Gavin)
06134     Created:    4/3/94
06135     Inputs:     lpBmi will usually be lpBitmapInfo
06136     Outputs:    -
06137     Returns:    DIB_PAL_INDICES or DIB_RGB_COLORS
06138     Purpose:    If can do PAL_INDICES, just does that, else
06139                 fills in the RGB quads in the DIB and returns DIB_RGB_COLOR. Only really
06140                 make sense to call on 16 or 256 colour bitmaps.
06141     Errors:     Will ensure if >256 colours (then mess upon memory).
06142 
06143 ********************************************************************************************/
06144 
06145 UINT32 GRenderRegion::SetPaletteEntries( LPBITMAPINFO lpBmi, wxDC* pOutputDC )
06146 {
06147     PORTNOTETRACE("other","GRenderRegion::SetPaletteEntries - do nothing");
06148 #ifndef EXCLUDE_FROM_XARALX
06149 #if WIN32
06150 // This has been commented out as we now always use the GDraw palette
06151 
06152 //  if (CanDoPalIndices)
06153 //      return(DIB_PAL_INDICES);                        // always best option if possible
06154 #endif
06155 
06156     LPBITMAPINFOHEADER BitmapHeader = &lpBmi->bmiHeader;
06157     const INT32 Depth  = BitmapHeader->biBitCount;
06158 
06159     if (Depth > 8 )
06160     {
06161     //  ERROR3("Too deep for SetPal");
06162     //  return(DIB_RGB_COLORS);
06163     }
06164 
06165     RGBQUAD *rgb = lpBmi->bmiColors;
06166     const size_t Count = 1<<Depth;
06167 
06168     if (Fixed256Palette)
06169     {
06170         // if fixed palette then use it as is
06171         memcpy(rgb, Fixed256Palette, sizeof(RGBQUAD) * 256);
06172         return(DIB_RGB_COLORS);
06173     }
06174 
06175     // This now uses the ErrorDiffPalette
06176     // Which is set up to avoid problems when the palette changes
06177     if (Count == 256)
06178     {
06179         if (ViewDither == 2)
06180             memcpy(rgb, &(StandardPalette.palPalEntry[0]), sizeof(PALETTEENTRY) * 256 );
06181         else
06182             memcpy(rgb, &(ErrorDiffPalette.palPalEntry[0]), sizeof(PALETTEENTRY) * 256 );
06183     }
06184     else
06185     {
06186         HDC hDC = ::GetDC(NULL);
06187         if (hDC != NULL)
06188         {
06189             GetSystemPaletteEntries(hDC,0,Count,(LPPALETTEENTRY) rgb);
06190             ::ReleaseDC(NULL, hDC);
06191         }
06192     }
06193 
06194     // Swap R and B.
06195     size_t i;
06196     for ( i=0 ; i<Count ; i++ )
06197     {
06198         BYTE t = rgb->rgbRed;
06199         rgb->rgbRed = rgb->rgbBlue;
06200         rgb->rgbBlue = t;
06201         rgb ++;
06202     }
06203 #endif
06204     return(DIB_RGB_COLORS);
06205 }
06206 
06207 // set this to 1 to evaluate 16-bit DIB plotting. I (Andy) have yet to find a Win16 driver
06208 // that understands 16-bit DIBs
06209 #define TEST16BIT   0
06210 
06211 #if TEST16BIT
06212 // like RGB macro, except defines 15-bit RGB word
06213 #define C16(r,g,b)  (WORD) ( ((r>>3)<<10) | ((g>>3)<<5) | (b>>3) )
06214 
06215 // a table of visible 15-bit colours
06216 static WORD ColDebugTable[32] =
06217 {
06218     C16(255,0,0),           // Red
06219     C16(255,0,0),           // Red
06220     C16(0,255,0),           // Green
06221     C16(0,255,0),           // Green
06222     C16(0,0,255),           // Blue
06223     C16(0,0,255),           // Blue
06224 
06225     C16(128,0,0),           // half Red
06226     C16(0,128,0),           // half green
06227     C16(0,0,128),           // half blue
06228 
06229 
06230     C16(128,255,0),
06231     C16(128,128,0),
06232 
06233     C16(128,0,255),
06234     C16(128,0,128),
06235 
06236 
06237     C16(255,128,0),
06238     C16(128,128,0),
06239 
06240     C16(0,128,255),
06241     C16(0,128,128),
06242 
06243 
06244     C16(255,0,128),
06245     C16(128,0,128),
06246 
06247     C16(0,255,128),
06248     C16(0,128,128)
06249 
06250 
06251 };
06252 #endif
06253 
06254 /********************************************************************************************
06255 
06256 >   void GRenderRegion::PlotBitmap( HDC hDC, UINT32 ColourFlag, LPBITMAPINFO BitmapInfo,
06257             LPBYTE Bits, INT32 Left, INT32 Top, INT32 Width, INT32 Height, HPALETTE hPal,
06258             INT32 SourceLeft, INT32 SourceTop )
06259 
06260     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
06261     Created:    3/3/94
06262     Inputs:     ColourFlag as used in SetDIBitsToDevice (e.g. DIB_RGB_COLORS). hPal must
06263                 already be selected into the device. Left & Top are the destination in
06264                 screen coords. SourceLeft and SourceTop are the offset from logical top left
06265                 of the source bitmap to be plotted.
06266     Outputs:    -
06267     Returns:    -
06268     Purpose:    Plot the DIB as fast as possible to the display surface. IMPORTANT: Only
06269                 works on SCREEN devices.
06270     Errors:     -
06271     Scope:      Static
06272 
06273 ********************************************************************************************/
06274 
06275 void GRenderRegion::PlotBitmap( wxDC* hDC, UINT32 ColourFlag,
06276         INT32 Left,INT32 Top, UINT32 Width,UINT32 Height, wxPalette* hPalette, INT32 SourceLeft,INT32 SourceTop )
06277 {
06278     pBits=StaticPlotBitmap(hDC, ColourFlag, pBitmapInfo, pBits, Left, Top, Width, Height, hPalette, SourceLeft, SourceTop);
06279 }
06280 
06281 LPBYTE GRenderRegion::StaticPlotBitmap( wxDC* hDC, UINT32 ColourFlag,
06282         LPBITMAPINFO lpBitmapInfo, LPBYTE lpBits,
06283         INT32 Left,INT32 Top, UINT32 Width,UINT32 Height, wxPalette* hPalette, INT32 SourceLeft,INT32 SourceTop )
06284 {
06285     if( Width==0 || Height==0 )
06286         return lpBits;
06287 
06288     // Test preconditions
06289     ERROR3IF((lpBitmapInfo->bmiHeader.biSize==0x00000000) /*|| 
06290              (lpBitmapInfo->bmiHeader.biSize==0xdddddddd) || 
06291              (lpBitmapInfo->bmiHeader.biSize==0xcdcdcdcd) */,"Illegal BitmapInfo structure passed to PlotBitmap");
06292             // AB commented second two checks out as bmiHeader.biSize is a WORD, i.e. 16 bits in size, according to compatdef.h
06293 //  TRACE( _T("SrcRect(%d, %d, %d, %d) - (%d, %d)"), rectDraw.GetLeft(), rectDraw.GetTop(),
06294 //      rectDraw.GetWidth(), rectDraw.GetHeight(), pBitmap->GetWidth(), pBitmap->GetHeight() );
06295 
06296     CamProfile cp(CAMPROFILE_BLIT);
06297 
06298 #if !USE_wxBITMAP
06299 
06300     ERROR3IF(lpBitmapInfo->bmiHeader.biBitCount!=32,"Image must (currently) be 32bpp");
06301 
06302     wxBitmap Bitmap(Width,Height,32);
06303     wxAlphaPixelData BitmapData(Bitmap);
06304     //
06305     // Copy source (or part of source) into wxBitmap.
06306     //
06307     DWORD* pSBuffer = 
06308             (DWORD*)lpBits + 
06309             lpBitmapInfo->bmiHeader.biWidth*(lpBitmapInfo->bmiHeader.biHeight-1-SourceTop) +
06310             SourceLeft;
06311     DWORD* pDBuffer = (DWORD*)Bitmap.GetRawData(BitmapData,32);
06312     DWORD* pDLine = pDBuffer;
06313     INT32 nStep = Width;
06314     if ( BitmapData.GetRowStride()<0 )
06315         nStep = -nStep;
06316     for( UINT32 y=0 ; y<Height ; ++y )
06317     {
06318         //
06319         // Set all pixels to be opaque. (We don't want to plot with alpha here
06320         // so inverting the alpha channel would not be correct, and it's
06321         // possible that the transparency channel will not always be zero).
06322         //
06323 #if defined(__WXGTK__)
06324         for( UINT32 x=0; x<Width; ++x )
06325         {
06326             BYTE* pS = pBYTE(pSBuffer+x);
06327             BYTE* pD = pBYTE(pDLine  +x);
06328             pD[0] = pS[2];
06329             pD[1] = pS[1];
06330             pD[2] = pS[0];
06331             pD[3] = 0xFF;
06332         }
06333 #else
06334         for( UINT32 x=0; x<Width; ++x )
06335             pDLine[x] = pSBuffer[x];
06336 #endif
06337         pSBuffer -= lpBitmapInfo->bmiHeader.biWidth;
06338         pDLine += nStep;
06339     }
06340     if ( ScreenHinting==CONVHINT_FINAL16  ||
06341          ScreenHinting==CONVHINT_FINAL555 ||
06342          ScreenHinting==CONVHINT_FINAL565 ||
06343          ScreenHinting==CONVHINT_FINAL655 ||
06344          ScreenHinting==CONVHINT_FINAL664 )
06345     {
06346         BITMAPINFOHEADER Info = { sizeof(BITMAPINFOHEADER),Width,Height,1,32 } ;
06347         if ( nStep<0 )
06348             pDBuffer += (Height-1)*nStep;
06349         UINT32 uHint;
06350         switch (ScreenHinting)
06351         {
06352         case CONVHINT_FINAL565: uHint = 8+0; break;
06353         case CONVHINT_FINAL655: uHint = 8+1; break;
06354         case CONVHINT_FINAL664: uHint = 8+3; break;
06355         default:                uHint = 8+2; break;
06356         }
06357         GRenderRegion::GetStaticDrawContext()->ConvertBitmap(&Info,(BYTE*)pDBuffer,&Info,(BYTE*)pDBuffer,uHint);
06358     }
06359     Bitmap.UngetRawData(BitmapData) ;
06360 
06361 #ifdef _DEBUG
06362     // Alex's test to test scaling
06363     if ((hDC->LogicalToDeviceX(wxCoord(72000)))!=wxCoord(72000))
06364     {
06365         ERROR3("X coordinate out");
06366     }
06367     if ((hDC->LogicalToDeviceY(wxCoord(72000)))!=wxCoord(72000))
06368     {
06369         ERROR3("Y coordinate out");
06370     }
06371 #endif
06372 
06373     {
06374 //      CamProfile cp(CAMPROFILE_BLIT);
06375         hDC->DrawBitmap(Bitmap,Left,Top) ;
06376     }
06377 
06378 #else
06379 
06380 #if defined(__WXGTK__)
06381     RGBT* pBuffer = (RGBT*)lpBits + pBitmapData->m_width*SourceTop + SourceLeft;
06382     for( UINT32 y=0 ; y<Height ; ++y )
06383     {
06384         //
06385         // Set all pixels to be opaque. (We don't want to plot with alpha here
06386         // so inverting the alpha channel would not be correct as it's
06387         // possible that the transparency channel will not always be zero).
06388         //
06389         for( UINT32 x=0; x<Width; ++x )
06390             pBuffer[x].Transparency = 0xFF;
06391         pBuffer += pBitmapData->m_width;
06392     }
06393 #endif
06394 
06395     BITMAPINFOHEADER Info = { sizeof(BITMAPINFOHEADER),Width,Height,1,32 } ;
06396 
06397     bool bIs16Bit = false ;
06398     UINT32 uHint = 8+2;
06399     if ( ScreenHinting==CONVHINT_FINAL16  ||
06400          ScreenHinting==CONVHINT_FINAL555 ||
06401          ScreenHinting==CONVHINT_FINAL565 ||
06402          ScreenHinting==CONVHINT_FINAL655 ||
06403          ScreenHinting==CONVHINT_FINAL664 )
06404     {
06405         switch (ScreenHinting)
06406         {
06407         case CONVHINT_FINAL565: uHint = 8+0; break;
06408         case CONVHINT_FINAL655: uHint = 8+1; break;
06409         case CONVHINT_FINAL664: uHint = 8+3; break;
06410         default:                             break;
06411         }
06412         bIs16Bit = true ;
06413     }
06414     if ( SourceLeft || SourceTop || Width!=pBitmap->GetWidth() || Height!=pBitmap->GetHeight() )
06415     {
06416         pBitmap->UngetRawData(*pBitmapData) ;
06417         wxBitmap bmp = pBitmap->GetSubBitmap( wxRect(SourceLeft,SourceTop,Width,Height) ) ;
06418         if ( bIs16Bit )
06419         {
06420             wxAlphaPixelData bmpData(bmp);
06421             BYTE* pData = (BYTE*)bmp.GetRawData(bmpData,32);
06422             if ( bmpData.GetRowStride()<0 )
06423                 pData += bmpData.GetRowStride()*(Height-1);
06424             GRenderRegion::GetStaticDrawContext()->ConvertBitmap(&Info,pData,&Info,pData,uHint);
06425             bmp.UngetRawData(bmpData) ;
06426         }
06427         {
06428 //          CamProfile cp(CAMPROFILE_BLIT);
06429             hDC->DrawBitmap(bmp,Left,Top);
06430         }
06431         TRACE( _T("DrawBitmap(%08x,%04x,%04x),%04x,%04x\n"),hDC,Left,Top,Width,Height);
06432     }
06433     else
06434     {
06435         if ( bIs16Bit )
06436             GRenderRegion::GetStaticDrawContext()->ConvertBitmap(&Info,lpBits,&Info,lpBits,uHint);
06437         pBitmap->UngetRawData(*pBitmapData) ;
06438         {
06439 //          CamProfile cp(CAMPROFILE_BLIT);
06440             hDC->DrawBitmap(*pBitmap,Left,Top) ;
06441         }
06442         TRACE( _T("DrawBitmap(%08x,%04x,%04x)\n"),hDC,Left,Top);
06443     }
06444 
06445     lpBits = (BYTE*)pBitmap->GetRawData(*pBitmapData,uBitmapDepth);
06446 #endif
06447     return lpBits;
06448 }
06449 
06450 
06451 /********************************************************************************************
06452 
06453 >   void GRenderRegion::PlotBitmap( UINT32 ColourFlag )
06454 
06455     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
06456     Created:    3/3/94
06457     Inputs:     ColourFlag as used in SetDIBitsToDevice (e.g. DIB_RGB_COLORS).
06458     Outputs:    -
06459     Returns:    -
06460     Purpose:    Plot the DIB as fast as possible to the display surface. Member function
06461                 version. There is also a more general static version (which this uses).
06462                 This member fn one uses the ChangedBBox for optimal blitting.
06463     Errors:     -
06464 
06465 ********************************************************************************************/
06466 
06467 void GRenderRegion::PlotBitmap( UINT32 ColourFlag )
06468 {
06469     RememberMe("PlotBitmap");
06470 
06471     #if REMEMBER_GDRAW==2
06472     TRACE( _T("Rect=(%d,%d,%d,%d) BM=%dx%d\n"),WRect.left,WRect.top,WRect.right,WRect.bottom,
06473                 lpBitmapInfo->bmiHeader.biWidth,
06474                 lpBitmapInfo->bmiHeader.biHeight
06475         );
06476     #endif
06477 
06478     #if FILL_BITMAP
06479     if (IsUserName("Andy") && (BitmapDepth==8) )
06480     {
06481         LPBYTE p = lpBits;
06482         // is the top scanline is all the same value?
06483         const BYTE value = *p;
06484         INT32 i = (INT32)lpBitmapInfo->bmiHeader.biWidth;               // check first scanline
06485         while (i--)
06486         {
06487             if (*p != value)
06488                 break;
06489             p++;
06490         }
06491         if (i<0)
06492         {
06493             if (value==FILL_BITMAP)
06494             {
06495                 TRACE( _T("Got FILL_BITMAPed bitmap\n"));
06496                 RememberDump();
06497             }
06498             else if (value==FILL_BITMAP+1)
06499             {
06500                 TRACE( _T("Got FILL_BITMAPed bitmap+1 bitmap\n"));
06501                 RememberDump();
06502             }
06503         }
06504     }
06505     #endif
06506 
06507     #if 0
06508     {
06509         // helper code to render hatching before the blit to detect if it fails
06510         static INT32 BrushNum = 2;
06511         CBrush Brush;
06512 
06513         // different colour every time
06514         Brush.CreateHatchBrush( BrushNum, PALETTEINDEX( rand() & 0xFF ) );
06515 
06516         if (++BrushNum > 5)
06517             BrushNum = 2;
06518 
06519         RenderDC->FillRect( &WRect, &Brush );
06520     }
06521     #endif
06522 
06523     // default values, assume blitting everything
06524     INT32 DestX = WRect.x;
06525     INT32 DestY = WRect.y;
06526     INT32 Width = WRect.width;
06527     INT32 Height= WRect.height;
06528 
06529     INT32 SourceX = ScreenRect.x;
06530     INT32 SourceY = ScreenRect.y;
06531 
06532     RECT UsedRect;
06533     if (GetDrawContext()->GetChangedBBox( &UsedRect ))
06534     {
06535 //      TRACE( _T("ChangedBBox = (%d, %d, %d, %d)"), UsedRect.left, UsedRect.top, UsedRect.right, UsedRect.bottom );
06536         
06537         if ((UsedRect.right < UsedRect.left) ||
06538             (UsedRect.bottom< UsedRect.top ))
06539         {
06540             // Changed box is illegal so exit
06541             TRACE(_T("Bad ChangedBBox\n"));
06542             return;
06543         }
06544         else
06545         {
06546             // blit less, thanks to changedBBox
06547 
06548             // Gavin usefully returns his rectangles the wrong way up
06549             // he returns x1,y1,x2,y2 and we want
06550             // x1,h-y2,x2,h-y1
06551 
06552             const INT32 ChangeX = UsedRect.left;
06553             SourceX += ChangeX;
06554             DestX += ChangeX;
06555 
06556             INT32 ChangeY = Height - UsedRect.bottom;
06557             SourceY += ChangeY;
06558             DestY += ChangeY;
06559 
06560             Width  = UsedRect.right  - UsedRect.left;
06561             Height = UsedRect.bottom - UsedRect.top;
06562 
06563 //          TRACE( _T("Reg    %d - %d\n"),WRect.top, WRect.bottom);
06564 //          TRACE( _T("Gav    %d - %d\n"),UsedRect.top, UsedRect.bottom);
06565 //          TRACE( _T("Height %d\n"), Height);
06566             
06567 //          if (FALSE) 
06568 //          {
06569 //              TRACE( _T("Was %dx%d now %dx%d\n"), WRect.right-WRect.left, WRect.bottom-WRect.top,
06570 //                                              Width, Height );
06571 //          }
06572         }
06573     }
06574 
06575 //  TRACE(_T("Blitting (%d, %d) (%d, %d) (%d, %d)\n"), DestX, DestY, Width, Height, SourceX, SourceY);
06576     
06577 // GAT
06578 //  PlotBitmap( RenderDC, ColourFlag, lpBitmapInfo, lpBits, DestX, DestY,
06579 //              Width, Height, hPalette, SourceX, SourceY );
06580     PlotBitmap( RenderDC, ColourFlag, DestX,DestY, Width,Height, hPalette, SourceX,SourceY );
06581 }
06582 
06583 /********************************************************************************************
06584 
06585 >   void GRenderRegion::Display1to1Bitmap()
06586 
06587     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com> (based on Gavin)
06588     Created:    4/3/94
06589     Inputs:     -
06590     Outputs:    -
06591     Returns:    -
06592     Purpose:    Plot a bitmap to a device of the same colour depth.
06593 
06594 ********************************************************************************************/
06595 
06596 void GRenderRegion::Display1to1Bitmap()
06597 {
06598     UINT32 ColourFlag = DIB_RGB_COLORS ;
06599 
06600     DWORD *rgb = (DWORD *)pBitmapInfo->bmiColors ;
06601 
06602     switch (uBitmapDepth)
06603     {
06604         case 16:
06605             *rgb++ = 0x7c00 ;
06606             *rgb++ = 0x03e0 ;
06607             *rgb++ = 0x001f ;
06608             break;
06609     
06610         case 32:
06611             *rgb++ = 0x00ff0000 ;
06612             *rgb++ = 0x0000ff00 ;
06613             *rgb++ = 0x000000ff ;
06614             break;
06615 
06616         default:
06617             ColourFlag = SetPaletteEntries( pBitmapInfo, RenderDC );
06618             break;
06619     }
06620 
06621     PlotBitmap( ColourFlag );
06622 }
06623 
06624 
06625 /********************************************************************************************
06626 
06627 >   const LOGPALETTE* GRenderRegion::GetRecommendedPalette()
06628 
06629     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
06630     Created:    10/3/94
06631     Inputs:     -
06632     Outputs:    -
06633     Returns:    A pointer to a logical palette, or NULL if the screen does not do palettes.
06634     Purpose:    For the main window to get a Gavin-approved logical palette.
06635     Scope:      Static
06636 
06637 ********************************************************************************************/
06638 
06639 const LOGPALETTE* GRenderRegion::GetRecommendedPalette()
06640 {
06641     // as this can be called very early in the startup sequence, it does not rely
06642     // on ::Init having been called first
06643 
06644     const LOGPALETTE* lpPal = NULL;
06645 
06646 
06647     if (pRealGD == NULL)
06648         pRealGD = new GDrawAsm;
06649 
06650     if (pRealGD->Init())
06651     {
06652         // always call this regardless of screen depth. For 8-bit and less screens,
06653         // call it with 0 (dithering), else 1 (error diffusion)
06654 
06655         // In fact we will always call it with 0 as the palette returned is the same
06656         // We will try to keep the static GD context set up for ordered dithering
06657         PORTNOTETRACE("other","GRenderRegion::GetRecommendedPalette - removed palette code");
06658 #ifndef EXCLUDE_FROM_XARALX
06659         const INT32 ScreenDepth = ::wxDisplayDepth();
06660         lpPal = pRealGD->SelectPalette(0);
06661 
06662         // the returned pointer is only interesting to 8-bit palette devices
06663         if ((ScreenDepth!=8) ||
06664             !(GetDeviceCaps( hdc, RASTERCAPS ) & RC_PALETTE ) ||
06665             WantNoPalette)
06666 #endif
06667         {
06668             lpPal = NULL;
06669         }
06670     }
06671 
06672     GD = pRealGD;
06673 
06674     return(lpPal);
06675 }
06676 
06677 
06678 
06679 void GRenderRegion::DrawPixel(const DocCoord &Point)
06680 {
06681     // If we are not drawing complex shapes and this shape is, then return
06682     if ((!RenderComplexShapes) && (TestForComplexShape(&Caps)))
06683         return;
06684 
06685     RememberMe("DrawPixel");
06686 
06687     if (!SetGCol(RR_STROKECOLOUR()))                
06688         return;
06689 
06690     POINT PlotMe;
06691     PlotMe.x = Point.x-(ScaledPixelWidth/2);        // >>>> Bodge to make grid dots align with crosses
06692     PlotMe.y = Point.y-(ScaledPixelWidth/2);        // >>>>
06693     GetDrawContext()->FillPoint( &PlotMe );
06694 
06695     HaveRenderedSomething = TRUE;
06696 }
06697 
06698 /********************************************************************************************
06699 
06700 >   void GRenderRegion::DrawCross(const DocCoord &Point, const UINT32 Size)
06701 
06702     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
06703     Created:    25/4/94
06704     Inputs:     Point - the centre point of the cross.
06705                 Size - the length of the lines used to draw the cross with.
06706     Purpose:    Draws a cross in the render region.  The cross consists of a vertical
06707                 line 'Size' millipoints high, and a horizontal line 'Size' millipoints
06708                 wide.
06709 
06710 ********************************************************************************************/
06711 
06712 void GRenderRegion::DrawCross(const DocCoord &Point, const UINT32 Size)
06713 {
06714     // If we are not drawing complex shapes and this shape is, then return
06715     if ((!RenderComplexShapes) && (TestForComplexShape(&Caps)))
06716         return;
06717 
06718     RememberMe("DrawCross");
06719 
06720     if (!SetGCol(RR_STROKECOLOUR()))
06721         return;
06722 
06723     HaveRenderedSomething = TRUE;
06724 
06725     const INT32 Length = Size * ScaledPixelWidth;
06726 
06727     static PathVerb Verbs[] =
06728     {
06729         PT_MOVETO, PT_LINETO,
06730         PT_MOVETO, PT_LINETO
06731     };
06732     DocCoord Coords[4];
06733 
06734     DocCoord NewPoint = Point;
06735 
06736     Coords[0].x = NewPoint.x - Length;
06737     Coords[0].y = NewPoint.y;
06738     Coords[1].x = NewPoint.x + Length;
06739     Coords[1].y = NewPoint.y;
06740 
06741     Coords[2].x = NewPoint.x;
06742     Coords[2].y = NewPoint.y - Length;
06743     Coords[3].x = NewPoint.x;
06744     Coords[3].y = NewPoint.y + Length;
06745 
06746     GetDrawContext()->StrokePath( (POINT*)Coords, Verbs, sizeof(Verbs), FALSE,
06747                                             0, CAPS_BUTT, JOIN_MITER, NULL );
06748 }
06749 
06750 /********************************************************************************************
06751 
06752 >   BOOL GRenderRegion::StrokePathAvailable()
06753 
06754     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
06755     Created:    18/4/94
06756     Inputs:     -
06757     Outputs:    -
06758     Returns:    TRUE if StrokePathToPath is available, FALSE if it is not.
06759     Purpose:    Used to know whether StrokePathToPath will fail. If we don't have GDraw,
06760                 we cannot do this, if we do, we can.
06761     Scope:      Static
06762 
06763 ********************************************************************************************/
06764 
06765 BOOL GRenderRegion::StrokePathAvailable()
06766 {
06767     return CanDoGDraw;
06768 //  return TRUE;
06769 }
06770 
06771 /********************************************************************************************
06772 
06773 >   INT32 GRenderRegion::StrokePathToPath(
06774         CONST DocCoord *IPoints,
06775         CONST BYTE FAR *ITypes,
06776         DWORD ILength,
06777         DocCoord *OPoints,
06778         BYTE  *OTypes,
06779         DWORD OLength,
06780         BOOL Close,
06781         DWORD LineWidth,
06782         DWORD Flattening,
06783         LineCapType LineCaps,
06784         JointType LineJoin,
06785         CONST DashType *Dash)
06786 
06787     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
06788     Created:    18/4/94
06789     Inputs:     IPoints is the path of points to be stroked, ITypes its verb list and ILength
06790                 the length. OPoints, OTypes and OLength are the output path. If Close is
06791                 TRUE then the path will be closed. Flattening is how flat it is required.
06792     Outputs:    -
06793     Returns:    Length of resultant path. Returns -1 if errored.
06794     Purpose:    Used for rendering complex strokes when the native system cannot do it (e.g.
06795                 GDI16).
06796     Scope:      Static
06797 
06798 ********************************************************************************************/
06799 
06800 INT32 GRenderRegion::StrokePathToPath(
06801         CONST DocCoord *IPoints,
06802         CONST BYTE FAR *ITypes,
06803         size_t ILength,
06804         DocCoord *OPoints,
06805         BYTE  *OTypes,
06806         DWORD OLength,
06807         BOOL Close,
06808         DWORD LineWidth,
06809         DWORD Flattening,
06810         LineCapType LineCaps,
06811         JointType LineJoin,
06812         CONST DashType *Dash)
06813 {
06814     if (!CanDoGDraw)
06815         return -1;
06816 
06817     CapStyles CapS = (LineCaps==LineCapButt) ? CAPS_BUTT : (LineCaps==LineCapRound) ? CAPS_ROUND : CAPS_SQUARE;
06818     JoinStyles JoinS = (LineJoin==MitreJoin) ? JOIN_MITER : (LineJoin==RoundJoin) ? JOIN_ROUND : JOIN_BEVEL;
06819 
06820     DASH GDash = { 0, 0, { 0 } };
06821 
06822     if(Dash)
06823         memcpy(&GDash,Dash,sizeof(GDash));
06824 
06825     PPOINT SPoints = NULL;
06826     PBYTE STypes = NULL;
06827 //  INT32 SLength = 0;
06828 
06829     GenStroke GStroke;
06830     INT32 Result = GStroke.StrokePathToPath((LPPOINT)IPoints, ITypes, (UINT32)ILength,
06831                                             &SPoints, &STypes,
06832                                             Close, LineWidth, (UINT32)(10<<16), Flattening,
06833                                             CapS, JoinS, &GDash);
06834 
06835     if (Result < 0)
06836         TRACE( _T("GDraw_StrokePtoP error=%lx\n"), 0 );
06837 
06838     // If the Resultant length is larger than the Output path length then fail and return the overflow!
06839     if(Result > (INT32)OLength)
06840         return (INT32)OLength - Result;
06841 
06842     for (INT32 i = 0; i < Result; i++)
06843     {
06844         OPoints[i].x = SPoints[i].x;
06845         OPoints[i].y = SPoints[i].y;
06846         OTypes[i] = STypes[i];
06847     }
06848 
06849     delete SPoints;
06850     delete STypes;
06851 
06852     return Result;
06853 }
06854 
06855 
06856 
06857 
06858 /********************************************************************************************
06859 
06860 >   void GRenderRegion::GColInit( HDC hdc, BOOL Force = FALSE )
06861 
06862     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com> (Rewritten by Jason. Originally by AndyP)
06863     Created:    2/5/96 (30/6/94)
06864 
06865     Inputs:     A device context and whether the GDraw fn should be called regardless. If
06866                 hdc is NULL and Force is TRUE then the next time someone calls this it
06867                 will always do a Force.
06868     Outputs:    -
06869     Purpose:    Initialises GDraw for rendering into 8bpp bitmaps
06870 
06871                 Actually, GColour Init is not very expensive (5 milliseconds if the
06872                 palette hasn't changed) but this function is more efficient (0.5 millisecs
06873                 if it hasn't changed).
06874 
06875                 This function will also force a redraw of all windows if it detects that
06876                 the palette has changed - this is because a palette change detected in the
06877                 middle of a background redraw could leave the already-drawn areas invalid.
06878 
06879     Scope:      Static public
06880 
06881 ********************************************************************************************/
06882 
06883 void GRenderRegion::GColInit( wxDC* hdc, BOOL Force )
06884 {
06885     PORTNOTETRACE("other","GRenderRegion::GColInit - do nothing");
06886 #ifndef EXCLUDE_FROM_XARALX
06887     static PALETTEENTRY OldPal[260];
06888 
06889     //BOOL DoRedraw = TRUE;
06890 
06891 //  TRACEUSER( "Gerry", _T("GColInit() : DC = %08x  (%d)\n"), hdc, Force);
06892 
06893     if (hdc != NULL)
06894     {
06895         // If this isn't a palette device then don't do anything...
06896         if (!(::GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE))
06897             return;
06898         
06899         // The user wants us to make sure GDraw is ready to render. We will check
06900         // to see if the palette has changed, and if it has, we'll redraw
06901         PALETTEENTRY NewPal[260];
06902 
06903         if (GetSystemPaletteEntries(hdc, 0, 256, NewPal) == 0)
06904         {
06905             TRACE( _T("GColInit() : GetSystemPaletteEntries failed %d\n"), GetLastError());
06906             return;
06907         }
06908 
06909         for (DWORD Index = 0; Index < 256; Index++)
06910             NewPal[Index].peFlags = 0;
06911 
06912         if (memcmp(NewPal, OldPal, sizeof(PALETTEENTRY) * 256) != 0)
06913         {
06914 //          TRACEUSER( "Gerry", _T("GColInit() : Palette has changed\n"));
06915 
06916             // The palette has changed, so we copy the palette
06917             // data across to update OldPal
06918             memcpy(OldPal, NewPal, sizeof(PALETTEENTRY) * 256);
06919 
06920             // And ensure that all palette-reliant windows are redrawn
06921             PaletteManager::RedrawAllPalettedWindows();
06922         }
06923     }
06924     else
06925     {
06926 //      TRACEUSER( "Gerry", _T("GColInit() : Vaping OldPal record\n"));
06927         // The caller is just informing us that the palette has changed, so we should
06928         // flag the fact that GDraw needs initialisation next time.
06929         // The easiest way to do this is to vape the OldPal record.
06930         memset(OldPal, 0, sizeof(PALETTEENTRY) * 256);
06931     }
06932 #endif
06933 }
06934 
06935 /********************************************************************************************
06936 
06937 >   static void GRenderRegion::EnsurePalette(INT32 PaletteFlag)
06938 
06939     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
06940     Created:    3/5/96
06941 
06942     Inputs:     PaletteFlag - value to pass to GDraw_SelectPalette. If -1 then uses the
06943                               correct value for the current WhichDither setting
06944     Outputs:    -
06945     Purpose:    Calls SelectPalette for the static GDraw context and sets the palette
06946     Scope:      Static public
06947 
06948 ********************************************************************************************/
06949 
06950 void GRenderRegion::EnsurePalette(INT32 PaletteFlag)
06951 {
06952     if (PaletteFlag == -1)
06953     {
06954         PaletteFlag = 0;
06955         if ((WhichDither == 0) || (WhichDither == 3))
06956             PaletteFlag = 1;
06957     }
06958 
06959     const LOGPALETTE* pPalette = GetStaticDrawContext()->SelectPalette(PaletteFlag);
06960     if (pPalette != NULL)
06961         GetStaticDrawContext()->InitialiseWithPalette(pPalette);
06962 }
06963 
06964 
06965 /********************************************************************************************
06966 
06967 >   static void GRenderRegion::UpdateErrorDiffPalette(void)
06968 
06969     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
06970     Created:    29/5/96
06971     Inputs:     -
06972     Outputs:    -
06973     Purpose:    Sets up a sensible palette for error diffusion
06974                 It sets 3 of the entries to black to avoid them being used
06975     Scope:      Static protected
06976 
06977 ********************************************************************************************/
06978 
06979 void GRenderRegion::UpdateErrorDiffPalette(void)
06980 {
06981     if (ErrorDiffContext != NULL)
06982     {
06983         const LOGPALETTE* pPal = ErrorDiffContext->SelectPalette(1);
06984 
06985         if (pPal != NULL)
06986         {
06987             // Calculate length of palette
06988             INT32 Length = 2 * sizeof(WORD) + (pPal->palNumEntries * sizeof(PALETTEENTRY));
06989 
06990             // Copy it away
06991             memcpy(&ErrorDiffPalette, pPal, Length);
06992 
06993             // Set the rampant entries that Windows changes to black so we don't use them
06994             INT32* pEntry = (INT32*) &(ErrorDiffPalette.palPalEntry[0]);
06995             pEntry[8] = 0;
06996             pEntry[9] = 0;
06997             pEntry[246] = 0;
06998             pEntry[247] = 0;
06999 
07000             memcpy(&StandardPalette, &ErrorDiffPalette, Length);
07001 
07002 #ifdef RALPH
07003             // Set the silly entries to black...
07004             for(INT32 i=10; i<=15; i++)
07005                 pEntry[i] = 0;
07006             for(i=24; i<=31; i++)
07007                 pEntry[i] = 0;
07008             for(i=224; i<=231; i++)
07009                 pEntry[i] = 0;
07010             for(i=240; i<=245; i++)
07011                 pEntry[i] = 0;          
07012 
07013 // DEFCONS: This is a marker for updating the default context tables
07014 //          Change the following #if FALSE to TRUE
07015 #if FALSE
07016             // Initialise the error diffusion context so we can save it
07017             ErrorDiffContext->InitialiseWithPalette(GetErrorDiffPalette());
07018 #endif
07019             // Set the context up from the static block (or save it)
07020             ((GDrawAsm*)ErrorDiffContext)->InitContext((GCONTEXT*)ErrorDiffContextData, 1);
07021 
07022 #else // ifdef RALPH
07023             // And initialise the error diffusion context
07024             ErrorDiffContext->InitialiseWithPalette(GetErrorDiffPalette());
07025 #endif
07026 
07027             // Either way set the stack limit here
07028             ErrorDiffContext->SetStackSize(102400);
07029         }
07030     }
07031 }
07032 
07033 
07034 
07035 /********************************************************************************************
07036 
07037 >   static DWORD GRenderRegion::GetMaxBitmapWidth(void)
07038 
07039     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
07040     Created:    8/10/96
07041     Inputs:     -
07042     Outputs:    -
07043     Returns:    Max width of off screen bitmap supported
07044     Scope:      Public
07045     SeeAlso:    GDrawAsm::GetMaxBitmapDepth()
07046 
07047     Notes:      This function does not require a GDraw critical section
07048 
07049 ********************************************************************************************/ 
07050 
07051 DWORD GRenderRegion::GetMaxBitmapWidth(void)
07052 {
07053     return XaDraw_GetMaxBitmapWidth();
07054 }
07055 
07056 
07057     
07058 /********************************************************************************************
07059 
07060 >   static DWORD GRenderRegion::GetMaxBitmapDepth(void)
07061 
07062     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
07063     Created:    8/10/96
07064     Inputs:     -
07065     Outputs:    -
07066     Returns:    Max depth of off screen bitmap supported
07067     Scope:      Public
07068     SeeAlso:    GDrawAsm::GetMaxBitmapWidth()
07069 
07070     Notes:      This function does not require a GDraw critical section
07071 
07072 ********************************************************************************************/ 
07073 
07074 DWORD GRenderRegion::GetMaxBitmapDepth(void)
07075 {
07076     return XaDraw_GetMaxBitmapDepth();
07077 }
07078 
07079 
07080 
07081 /********************************************************************************************
07082 
07083 >   const REGION* GRenderRegion::MakeClipRegionFromClipAttr(ClipRegionAttribute* pClipAttr)
07084 
07085     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
07086     Created:    10 April 2000
07087     Inputs:     pClipAttr       ptr to the ClipRegionAttribute whose path we'll base the new
07088                                 clip region on.
07089     Outputs:    
07090     Returns:    Pointer to a new GDraw clipping region, or
07091                 NULL if unsuccessful for some reason.
07092 
07093     Purpose:    Given a ptr to a ClipRegionAttribute, generate an appropriate GDraw clipping
07094                 region and return it.
07095     Errors:     
07096     See also:   
07097 
07098 ********************************************************************************************/
07099 const REGION* GRenderRegion::MakeClipRegionFromClipAttr(ClipRegionAttribute* pClipAttr)
07100 {
07101     // we need a path from pClipAttr, to which we'll clip, but we'll
07102     // do one or two validation checks on it before we trust it.
07103     Path* pClipPath = pClipAttr->GetClipPath();
07104     if (pClipPath == NULL || pClipPath->GetNumCoords() < 2)
07105         return NULL;
07106 
07107 // paranoia check...
07108 #ifdef _DEBUG
07109     if (!pClipPath->CheckPathValid())
07110         return NULL;
07111 #endif
07112 
07113     // ok, extract the raw data from our new path.
07114     DWORD       Winding   = (RR_WINDINGRULE() == EvenOddWinding) ? 0 : 1;
07115     UINT32      NumCoords = pClipPath->GetNumCoords();
07116     DocCoord*   Coords    = pClipPath->GetCoordArray();
07117     PathVerb*   Verbs     = pClipPath->GetVerbArray();
07118 
07119     // now we make the new clipping region.
07120 
07121     // as an initial guess of the size of the region, we'll say ~16 bytes per scanline,
07122     // and we'll arbitrarily set the maximum region size to be 256K. we'll keep doubling
07123     // our guess until it works or it hits our imposed ceiling.
07124     //
07125     //  NOTE:
07126     //      This is ok for uncomplicated paths. Complex paths require proportionally more 
07127     //      memory, so we should really be slightly more intelligent in guesswork here...
07128     //
07129     // Regions require approximatly the following amount of memory per scanline:
07130     //      Non-antialiased =  6 bytes
07131     //      LQ antialiased  = 20 bytes
07132     //      HQ antialiased  = 44 bytes
07133     //
07134     BYTE* pNewRegion        = NULL;
07135     UINT32  NumScans        = 500;      // initial guess - 500 scanlines.
07136     UINT32  nRegionLen      = NumScans * (RRQuality.GetAntialiasQuality() == Quality::FullAntialias ? 48 : 16);
07137     size_t  nMaxRegionLen   = 0x100000; // max region size = 1M at the mo'.
07138     BOOL    bMadeRegion     = FALSE;
07139     for (INT32 attempts = 0; (nRegionLen < nMaxRegionLen) && !bMadeRegion; attempts ++)
07140     {
07141         // allocate an empty region-buffer at our guess-size.
07142         pNewRegion = new BYTE[nRegionLen];
07143         if (pNewRegion == NULL)
07144         {
07145             // we shout out in debug mode - in release we try to fail quietly.
07146 #ifdef _DEBUG
07147             ERROR3( "Application has ran out of memory" );
07148 #endif
07149             return NULL;
07150         }
07151         memset(pNewRegion, 0, nRegionLen);
07152 
07153         // attempt to make the new clipping region.
07154         // if unsuccessful, double our buffer size and try again.
07155         if ( GetDrawContext()->MakeRegion(  (POINT*)Coords, Verbs, NumCoords,
07156                                             Winding, (REGION*)pNewRegion, nRegionLen) == -1 )
07157         {
07158             delete [] pNewRegion;
07159             pNewRegion  = NULL;
07160             nRegionLen *= 2;
07161         }
07162 
07163         // otherwise, record a success.
07164         else
07165         {
07166             bMadeRegion = TRUE;
07167         }
07168     }
07169 
07170     if (pNewRegion != NULL)
07171     {
07172         RECT r = ((REGION*)pNewRegion)->Rect;
07173         if (r.left  == 0 &&
07174             r.right == 0 &&
07175             r.bottom== 0 &&
07176             r.top   == 0)
07177         {
07178             if (RRQuality.GetAntialiasQuality() == Quality::FullAntialias)
07179                 ((REGION*)pNewRegion)->Type = 1;
07180             else
07181                 ((REGION*)pNewRegion)->Type = 0;
07182         }
07183     }
07184 
07185     return (REGION*)pNewRegion;
07186 }
07187 
07188 
07189 /********************************************************************************************
07190 
07191 >   void GRenderRegion::SetDeepDIB(BOOL Value)
07192 
07193     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
07194     Created:    29/10/99
07195     Inputs:     Value - the value to set
07196     Outputs:    
07197     Purpose:    Sets the flag which indicates that we are rendering to a 32bit bitmap
07198 
07199 ********************************************************************************************/
07200 
07201 
07202 void GRenderRegion::SetDeepDIB(BOOL Value)
07203 {
07204 //  if (Value && ScreenDepth <= 16) // don't do it if we don't have a deep screen depth
07205 //      return;
07206 
07207 //  CanDoDeepDIBs = Value;
07208 }
07209 
07210 /********************************************************************************************
07211 
07212 >   void GRenderRegion::FreeStoredClipRegions()
07213 
07214     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
07215     Created:    11 April 2000
07216     Outputs:    Any clip regions stored in this render region will be freed up, so pointers
07217                 to them will become invalid.
07218 
07219     Purpose:    Delete and free memory used by all clip regions which this render region
07220                 has stored.
07221 
07222     See also:   FreeClipRegionForAttr().
07223 
07224 ********************************************************************************************/
07225 void GRenderRegion::FreeStoredClipRegions()
07226 {
07227     // now delete all cached clip-regions *except* for GDraw's, which we've already freed.
07228 //  POSITION pos = m_ClipRegionMap.GetStartPosition();
07229 //  REGION*     pClipRegion = NULL;
07230 //  void*       refpKey     = NULL;
07231 //  while (pos != NULL)
07232 //  {
07233 //      m_ClipRegionMap.GetNextAssoc(pos, refpKey, (void*&)pClipRegion);
07234 //      if (pClipRegion != NULL)
07235 //          delete [] ((BYTE *)pClipRegion);
07236 //  }
07237 //  m_ClipRegionMap.RemoveAll();
07238 
07239     ListT<Capture*>* pList = m_CaptureStack.GetListT();
07240     {
07241         Capture* pCapture = NULL;
07242         ListT<Capture*>::Iterator it = pList->End();
07243         INT32 nListSize = pList->Size();
07244         for (INT32 i = 0; i < nListSize; i++)
07245         {
07246             pCapture = *(--it);
07247 
07248             pCapture->RemoveAllCachedClipRegions();
07249         }
07250     }
07251 }
07252 
07253 
07254 
07255 /********************************************************************************************
07256 
07257 >   void GRenderRegion::OffsetByHalfPixel()
07258 
07259     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
07260     Created:    14/08/2000
07261 
07262     Purpose:    Intended solely for use by the feathering and shadowing systems, both of
07263                 which make use of a bitmap blurring algorithm which can sometimes return
07264                 a blurred bitmap up and right by half a pixel.
07265 
07266                 To compensate for this, the source bitmap must be rendered at an offset
07267                 of half a pixel down and left. This function sets GDraw and this render
07268                 region up to do that.
07269 
07270 ********************************************************************************************/
07271 void GRenderRegion::OffsetByHalfPixel()
07272 {
07273     // offset our render matrix by half a pixel.
07274     INT32 OffsetX = (INT32)(0.5 + (0.5 * ScaledPixelWidth));
07275     INT32 OffsetY = (INT32)(0.5 + (0.5 * ScaledPixelWidth));
07276     RenderMatrix.translate(OffsetX, OffsetY);
07277 
07278 //  if (GetTopCaptureBitmap())
07279 //  {
07280 //      GetTopCaptureBitmap()->CaptureMatrix = RenderMatrix;
07281 //  }
07282 
07283     // offset GDraw's render-matrix by half a pixel.
07284     // one GDraw pixel-width is (1 << FX + 16).
07285     INT32   LEFTSHIFT   = FX + 15;
07286     CurrentGMatrix.CX -= (XLONG)(1<<LEFTSHIFT);
07287     CurrentGMatrix.CY -= (XLONG)(1<<LEFTSHIFT);
07288     GetDrawContext()->SetMatrix( &CurrentGMatrix );
07289 }
07290 
07291 
07292 /********************************************************************************************
07293 
07294 >   virtual void GRenderRegion::GetRenderRegionCaps(RRCaps* pCaps)
07295 
07296     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
07297     Created:    23/01/2004
07298     Outputs:    pCaps - the flags to set for the things we are able to render
07299     Purpose:    This function allows a GRenderRegion to declare what it can render and
07300                 what it can not render. This allows us to pretend to be a simple render region
07301                 when doing onscreen print previews.
07302 
07303 ********************************************************************************************/
07304 
07305 void GRenderRegion::GetRenderRegionCaps(RRCaps* pCaps)
07306 {
07307     if (m_ForcePrintingCaps == 1)
07308     {
07309         // Return the same caps as a printing OSRenderRegion
07310         pCaps->CanDoNothing();
07311         pCaps->GradFills = TRUE;
07312         pCaps->LineAttrs = TRUE;
07313         pCaps->ArrowHeads = TRUE;
07314         pCaps->DashPatterns = TRUE;
07315         pCaps->SimpleBitmaps = TRUE;
07316     }
07317     else if (m_ForcePrintingCaps == 2)
07318     {
07319         // Return the same caps as a PS render region
07320         pCaps->CanDoNothing();
07321         pCaps->GradFills = TRUE;
07322         pCaps->SimpleBitmaps = TRUE;
07323         pCaps->ArbitraryBitmaps = TRUE;
07324         pCaps->ClippedSimpleBitmaps = TRUE;
07325         pCaps->ClippedArbitraryBitmaps = TRUE;
07326         pCaps->ClippedOutput = TRUE;
07327     }
07328     else
07329     {
07330         // We are fabby!
07331         pCaps->CanDoAll();
07332     }
07333 }
07334 
07335 /********************************************************************************************
07336 
07337 >   virtual void GRenderRegion::SetSimulatePrinting(UINT32 PrintType)
07338 
07339     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
07340     Created:    23/01/2004
07341     Inputs:     PrintType - 0=Not simulating, 1=Normal printer, 2=Postscript
07342     Purpose:    This function tells a GRenderRegion to simulate printing
07343                 This allows us to pretend to be a simple render region
07344                 when doing onscreen print previews.
07345 
07346 ********************************************************************************************/
07347 
07348 void GRenderRegion::SetSimulatePrinting(UINT32 PrintType)
07349 {
07350     m_ForcePrintingCaps = PrintType;
07351     if (PrintType)
07352         RenderFlags.Printing = TRUE;
07353 
07354     // Set the render caps up again
07355     GetRenderRegionCaps(&Caps);
07356 }
07357 
07358 
07359 /********************************************************************************************
07360 
07361 >   SlowJobResult GRenderRegion::DrawMaskedBitmap(const DocRect &Rect, KernelBitmap* pBitmap, 
07362                                   MaskedRenderRegion* pMask, Progress *Progress)
07363 
07364     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
07365     Created:    23/01/2004
07366     Inputs:     Point - the position to plot the bitmap
07367                 pBitmap - The bitmap that needs plotting
07368                 pMask - The mask render region to use to indicate which bits of pBitmap
07369                 needs to be plotted
07370     Purpose:    Plots the bitmap using the mask supplied.
07371 
07372 ********************************************************************************************/
07373 
07374 SlowJobResult GRenderRegion::DrawMaskedBitmap(const DocRect &Rect, KernelBitmap* pBitmap, 
07375                                       MaskedRenderRegion* pMask, ProgressDisplay *Progress)
07376 {
07377 //  RELTRACE( _T("In GRenderRegion::DrawMaskedBitmap\n"));
07378     
07379     // Make sure the world is in one piece
07380     if ((pBitmap==NULL) || (pMask==NULL))
07381         return SLOWJOB_FAILURE;
07382 
07383     // If mask coverage is 0% we do not need to do anything. The TRUE param indicates
07384     // that we don't care about exact coverage, which makes it return as soon as it realises
07385     // that there are pixel(s) that we'll have to plot
07386     if (pMask->FindCoverage(TRUE) == 0)
07387         return SLOWJOB_SUCCESS;
07388 
07389     // Guess we will need to be doing something...
07390     if (pBitmap->ActualBitmap == NULL)
07391         return SLOWJOB_FAILURE;
07392 
07393     // Get the 'Actual' windows Bitmap
07394     CWxBitmap *WinBM = (CWxBitmap*)pBitmap->ActualBitmap;
07395 
07396     // Is it valid ?
07397     if ((WinBM->BMInfo==NULL) || (WinBM->BMBytes==NULL))
07398         return SLOWJOB_FAILURE;
07399 
07400     // Remember the Size of the Bitmap (in pixels)
07401     INT32 Width  = WinBM->GetWidth();
07402     INT32 Height = WinBM->GetHeight();
07403 
07404     if ((Width == 0) || (Height == 0))
07405         // Error - bitmap has no dimension
07406         return SLOWJOB_FAILURE;
07407 
07408     // Setup the Gavin control points
07409     POINT PGram[3];
07410     PGram[0].x = Rect.lo.x; PGram[0].y = Rect.lo.y;
07411     PGram[1].x = Rect.hi.x; PGram[1].y = Rect.lo.y;
07412     PGram[2].x = Rect.lo.x; PGram[2].y = Rect.hi.y;
07413 
07414     // --- Colour-correct and/or Contone the bitmap as necessary
07415     RGBQUAD *Palette = NULL;
07416 
07417     // Do the colour correction. This may produce a new pointer in Palette,
07418     // which we should CCFree() when we are done with it - see the end of this function
07419 //  ColourCorrectBitmap(NULL, WinBM->BMInfo, &Palette);
07420 
07421     // If it didn't create a new palette for us, then we'll use the original one
07422 //  if (Palette == NULL)
07423         Palette = WinBM->BMInfo->bmiColors;
07424 
07425     DWORD Style = 0x0040;       // GDraw bitmap-plotting style flagword
07426 
07427     BOOL bForceToWhite = FALSE;
07428     BOOL bClearBitmapConv = FALSE;
07429     BYTE* pSepTables = NULL;
07430 //  BGR *pCyanSepTable = NULL;
07431 //  BGR *pMagentaSepTable = NULL;
07432 //  BGR *pYellowSepTable = NULL;
07433 //  BGR *pBlackSepTable = NULL;
07434 //  BYTE *pUnderColourRemovalTable = NULL;
07435 //  BYTE *pBlackGenerationTable = NULL;
07436 //  BGR* pTable = NULL;
07437 
07438     // --- Add Separation Style bits as approriate to the current colour separation mode
07439     // Currently, the only "separation" option we use is composite print preview
07440     // SepStyle for the SetBitmapFill functions are always in the MS byte of Style
07441     if (WinBM->GetBPP() > 8)    // Only needed for deep bitmaps
07442     {
07443         // If we've got a valid colour plate and it is a composite preview
07444         if (RenderView->GetColourPlate() != NULL &&
07445             !RenderView->GetColourPlate()->IsDisabled())
07446         {
07447             if (RenderView->GetColourPlate()->GetType() == COLOURPLATE_COMPOSITE)
07448             {
07449                 // Find the colour manager (if there is one), and ask it for the 15-bit RGB
07450                 // printer colour matching lookup table
07451 PORTNOTE("cms", "Disabled XaraCMS")
07452 #ifndef EXCLUDE_FROM_XARALX
07453                 XaraCMS* lpCMSMan = GetApplication()->GetCMSManager();
07454                 if (lpCMSMan != NULL)
07455                 {
07456                     DWORD *MatchTable = lpCMSMan->GetPaperViewTable();
07457                     ERROR3IF(MatchTable == NULL, "Can't create/find colour matching table");
07458                     if (MatchTable != NULL)
07459                     {
07460                         GetDrawContext()->SetBitmapConversionTable((BGR *)MatchTable);
07461                         bClearBitmapConv = TRUE;
07462                         // Bits 3 and 4 of bits 16-23 of Style specifies the conversion algorithm
07463                         // Make sure it only affects the 2 bits
07464                         Style |= (BitmapConversion & 3) << 19;
07465                     }
07466                 }
07467 #endif
07468             }
07469             else if (RenderView->GetColourPlate()->GetType() == COLOURPLATE_SPOT)
07470             {
07471                 bForceToWhite = TRUE;
07472             }
07473             else if (RenderView->GetColourPlate()->GetType() != COLOURPLATE_NONE)
07474             {
07475 //              DWORD Plate = RenderView->GetColourPlate()->GetType() - COLOURPLATE_CYAN;
07476                 pSepTables = (BYTE *) CCMalloc(5 * 256 * sizeof(BYTE));
07477                 if (pSepTables != NULL)
07478                 {
07479                     String_256 PrintProfile;
07480 PORTNOTE("cms", "Disabled XaraCMS")
07481 #ifndef EXCLUDE_FROM_XARALX
07482                     XaraCMS* lpCMSMan = GetApplication()->GetCMSManager();
07483                     if (lpCMSMan)
07484                         lpCMSMan->GetPrinterProfile(&PrintProfile);
07485 #endif
07486                     ColourContextCMYK *cc = new ColourContextCMYK(RenderView, &PrintProfile);
07487                     if (cc->GetProfileTables(pSepTables))
07488                     {
07489                         WinBM->ColourSeparate32to32(RenderView->GetColourPlate(), pSepTables);
07490                     }
07491                     delete cc;
07492                 }
07493             }
07494         }
07495     }
07496 
07497     if (bForceToWhite)
07498     {
07499         // First we need to set all the pixels as transparent white
07500         DWORD* pPixel = (DWORD*)WinBM->BMBytes;
07501         for (INT32 y = 0; y < Height; y++)
07502         {
07503             for (INT32 x = 0; x < Width; x++)
07504             {
07505                 *(pPixel++) = 0xFFFFFFFF;
07506             }
07507         }
07508 
07509         // Then we copy the mask information in
07510         MaskRegion MaskInfo;
07511         pMask->GetFirstMaskRegion(&MaskInfo);
07512         while (MaskInfo.Length != 0)
07513         {
07514 //          MaskInfo.Length; // What was this meant to do? AMB
07515             pPixel = ((DWORD*)WinBM->BMBytes) + (MaskInfo.y * Width) + MaskInfo.x;
07516             for (INT32 x = 0; x < MaskInfo.Length; x++)
07517             {
07518                 *(pPixel++) = 0xFFFFFF;
07519             }
07520 
07521             // Find the next bit of scan line to plot
07522             pMask->GetNextMaskRegion(&MaskInfo);
07523         }
07524     }
07525     else
07526     {
07527         const RGBQUAD TOnly = {0, 0, 0, 0xFF}; ; // 0xFF000000 on LittleEndian;
07528         const DWORD DTOnly = *(DWORD *)(&TOnly);
07529         // First we need to set all the pixels as transparent
07530         DWORD* pPixel = (DWORD*)WinBM->BMBytes;
07531         for (INT32 y = 0; y < Height; y++)
07532         {
07533             for (INT32 x = 0; x < Width; x++)
07534             {
07535                 *(pPixel++) |= DTOnly;
07536             }
07537         }
07538 
07539         // Then we copy the mask information in
07540         MaskRegion MaskInfo;
07541         pMask->GetFirstMaskRegion(&MaskInfo);
07542         while (MaskInfo.Length != 0)
07543         {
07544 //          MaskInfo.Length; // What was this meant to do?
07545             pPixel = ((DWORD*)WinBM->BMBytes) + (MaskInfo.y * Width) + MaskInfo.x;
07546             for (INT32 x = 0; x < MaskInfo.Length; x++)
07547             {
07548                 *(pPixel++) &= 0xFFFFFF;
07549             }
07550 
07551             // Find the next bit of scan line to plot
07552             pMask->GetNextMaskRegion(&MaskInfo);
07553         }
07554     }
07555 
07556     BYTE *BitmapBits = WinBM->BMBytes;
07557 
07558 //  GetDrawContext()->SetColour(0x00FF0000);
07559 //  WinRect DrawRect;
07560 //  DrawRect.left = Rect.lox;
07561 //  DrawRect.right = Rect.hix;
07562 //  DrawRect.top = Rect.hiy;
07563 //  DrawRect.bottom = Rect.loy;
07564 //  GetDrawContext()->FillRectangle(&DrawRect);
07565 
07566     // Plot the Bitmap
07567     GetDrawContext()->PlotBitmap(   &(WinBM->BMInfo->bmiHeader),
07568                     BitmapBits,
07569                     Style,
07570                     PGram,
07571                     Palette,
07572                     NULL, NULL, NULL,
07573                     NULL
07574                     );
07575 
07576     HaveRenderedSomething = TRUE;
07577 
07578     // Free any memory used for colour-corrected bitmap palettes.
07579     // If this pointer doesn't point at the original palette, then it has
07580     // been temporarily allocated by ColourCorrectBitmap, above.
07581     if (Palette != WinBM->BMInfo->bmiColors)
07582         CCFree(Palette);
07583 
07584     if (bClearBitmapConv)
07585     {
07586         GetDrawContext()->SetBitmapConversionTable(NULL);
07587     }
07588 
07589     if (pSepTables)
07590     {
07591         GetDrawContext()->SetSeparationTables();    // Defaults to setting everything to NULL
07592         CCFree(pSepTables);
07593     }
07594 /*
07595     if (pCyanSepTable)
07596         CCFree(pCyanSepTable);
07597     if (pMagentaSepTable)
07598         CCFree(pMagentaSepTable);
07599     if (pYellowSepTable)
07600         CCFree(pYellowSepTable);
07601     if (pBlackSepTable)
07602         CCFree(pBlackSepTable);
07603     if (pUnderColourRemovalTable)
07604         CCFree(pUnderColourRemovalTable);
07605     if (pBlackGenerationTable)
07606         CCFree(pBlackGenerationTable);
07607 */
07608     return SLOWJOB_SUCCESS;
07609 }
07610 
07611 
07612 
07613 
07614 /********************************************************************************************
07615 
07616 >   virtual CCachedBitmap GRenderRegion::GrabBitmap(DocRect* rectGrab, LPBITMAPINFO* plpBitmapInfo, LPBYTE* plpBits)
07617 
07618     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
07619     Created:    17/06/2004
07620     Inputs:     rectGrab        - the rectangle to grab as a new bitmap
07621     Outputs:    plpBitmapInfo   - address of pointer to BITMAPINFO structure
07622                 plpBits         - address of pointer to bitmap data
07623     Returns:    TRUE            if grab worked
07624                 FALSE           otherwise
07625     Purpose:    Plots the bitmap using the mask supplied.
07626 
07627 ********************************************************************************************/
07628 
07629 BOOL GRenderRegion::GrabBitmap(DocRect* rectGrab, LPBITMAPINFO* plpBitmapInfo, LPBYTE* plpBits)
07630 {
07631     //                          Alloc bitmap mem
07632     LPBITMAPINFO    bmInfo = NULL;
07633     LPBYTE          bmBits = NULL;
07634 
07635     // calculate their intersection.
07636     *rectGrab   = rectGrab->Intersection(CurrentClipRect);
07637     if (rectGrab->IsEmpty() || !rectGrab->IsValid())
07638         return FALSE;
07639 
07640     WinRect Rect = CalculateWinRect(RenderMatrix, *rectGrab, PixelsPerInch);
07641     UINT32 PixelWidth = Rect.width;
07642     UINT32 PixelHeight = Rect.height;
07643 
07644     bmInfo = AllocDIB( PixelWidth, PixelHeight, 32, &bmBits, NULL, FALSE); // don't use limited mem manager
07645 //  bmInfo = AllocDIB( PixelWidth, PixelHeight, 32, &bmBits, NULL, TRUE); // use limited mem manager
07646 
07647     if(!bmInfo || !bmBits)
07648     {
07649         ENSURE(FALSE,"GRenderRegion::GrabBitmap couldn't create bitmap.");
07650         return FALSE;
07651     }
07652 
07653     LPBITMAPINFOHEADER bh = &bmInfo->bmiHeader;
07654     bh->biCompression   = BI_RGB;                                               // see GDraw docs on GDraw_SetDIBitmap
07655     bh->biXPelsPerMeter = PixelsPerMeterAtCurrentViewScale(ScaleFactor);        // Not used by GDraw - just for completeness sake
07656     bh->biYPelsPerMeter = PixelsPerMeterAtCurrentViewScale(ScaleFactor);        // Not used by GDraw
07657 
07658     // Blit the current bitmap data into the new bitmap
07659     WinRect rectBack = CalculateWinRect(CurrentClipRect);
07660     WinRect rectWinGrab = CalculateWinRect(*rectGrab);
07661     INT32 left = rectWinGrab.x - rectBack.x;
07662     INT32 top = rectBack.GetBottom() - rectWinGrab.GetBottom();
07663     DIBUtil::CopyBitmapSection(pBitmapInfo, pBits, bmInfo, bmBits, top, left);
07664 
07665     *plpBitmapInfo = bmInfo;
07666     *plpBits = bmBits;
07667 
07668     // This code gets the pixelised version of the capture rect
07669     // and returns it to the caller to ensure ULTIMATE accuracy when blitting the bitmap
07670     // using RenderBits
07671     DocRect rectPix = OSRenderRegion::WinRectToDoc(RenderMatrix, Rect, PixelsPerInch);
07672     ENSURE(rectPix.IsValid(), "Pixelised rect is not valid in GrabBitmap");
07673     *rectGrab = rectPix;
07674 
07675     return TRUE;
07676 }
07677 
07678 
07679 
07680 
07681 /********************************************************************************************
07682 
07683 >   DocRect GRenderRegion::GetChangedRect()
07684 
07685     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
07686     Created:    24/06/2004
07687     Inputs:     -
07688     Outputs:    -
07689     Returns:    DocRect containing changed rect so far in this RenderRegion
07690     Purpose:    To get the changed rectangle so far
07691     SeeAlso:    OSRenderRegion::DocRectToWin;
07692 
07693 ********************************************************************************************/
07694 
07695 DocRect GRenderRegion::GetChangedRect()
07696 {
07697     RECT UsedRect;
07698     DocRect dr;
07699 
07700     // Gavin returns his rectangles the right way up - the mathematical way up!
07701     // he returns x1,y1,x2,y2
07702     //
07703     BOOL ok = GetDrawContext()->GetChangedBBox(&UsedRect);
07704     if (!(ok &&
07705         (UsedRect.right > UsedRect.left) &&
07706         (UsedRect.bottom > UsedRect.top)
07707         )
07708        )
07709     {
07710         WinRect winr = WinRect(UsedRect.left, UsedRect.top, UsedRect.right, UsedRect.bottom);
07711         OilRect oilr = winr.ToOil( GetRenderView() );
07712         dr = oilr.ToDoc( GetRenderSpread(), GetRenderView() );
07713     }
07714 
07715     dr = OSRenderRegion::WinRectToDoc(RenderMatrix, WinRect(UsedRect.left, UsedRect.top, UsedRect.right, UsedRect.bottom), PixelsPerInch);
07716 
07717     return dr;
07718 }
07719 
07720 
07721 
07722 
07723 /********************************************************************************************
07724 
07725 >   Capture* GRenderRegion::StartCapture(CCObject* pOwner,
07726                                  DocRect CaptureRect,
07727                                  CAPTUREINFO cinfo,
07728                                  BOOL bTransparent,
07729                                  BOOL bCaptureBackground,
07730                                  double dPPI,
07731                                  NodeRenderableInk* pDirectSupplier = NULL,
07732                                  )
07733 
07734     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
07735     Created:    30/06/2004
07736     Inputs:     pOwnerNode      - Node in tree which "owns" this capture
07737                 CaptureRect     - The rectangle to capture
07738                 ctype           - The type of capture required
07739                 bTransparent    - The capture could be transparent RGBT
07740                 bCaptureBackground  - The capture should include the state of the background
07741                 dPPI            - The resolution at which capture should be done
07742                 pDirectSupplier - Node in tree which supplies a bitmap directly into this capture
07743     Outputs:    -
07744     Returns:    TRUE if a Capture was successfully set up
07745     Purpose:    To start a bitmap capture of whatever is subsequently rendered
07746     SeeAlso:    GRenderRegion::StopCapture
07747 
07748 ********************************************************************************************/
07749 
07750 Capture* GRenderRegion::StartCapture(CCObject* pOwner,
07751                                  DocRect CaptureRect,
07752                                  CAPTUREINFO cinfo,
07753                                  BOOL bTransparent,
07754                                  BOOL bCaptureBackground,
07755                                  double dPPI,
07756                                  NodeRenderableInk* pDirectSupplier
07757                                  )
07758 {
07759     ENSURE(cinfo.caType==ctNESTABLE, "We only support nestable captures at the moment\n");
07760 
07761     // 1) alloc new mem, and setup state variables for new offscreen rendering
07762         // mem alloced = bmp
07763         // vars setup = docrect, gmatrix
07764     // 2) save current
07765     // 3) change to new offscreen state
07766 
07767     // If there's already a capture running and this one is nested but wants to change 
07768     // the transparency type then we must notify existing captures of the change...
07769     Capture* pCurrentCapture = GetTopCapture();
07770     if (pCurrentCapture!=NULL && cinfo.caType==ctNESTABLE && !cinfo.caFlags.GrabRendered && pCurrentCapture->IsTransparent() && !bTransparent)
07771     {
07772         ChangeCapture(cinfo, bTransparent, bCaptureBackground);
07773     }
07774 
07775     // If the caller didn't specify the capture resolution in pixels per inch
07776     // Then set it to the default value of the render region
07777     // And use the default matrix in our setup calculations
07778     Matrix CaptureMatrix;
07779     if (dPPI==0)
07780     {
07781 //      dPPI = PixelsPerInch;
07782 
07783         // Find current top bitmap capture and copy its res and res scale control flag
07784         Capture* pCap = GetTopCaptureBitmap();
07785         ERROR2IF(pCap==NULL, NULL, "There MUST be a bitmap capture in the stack - the master capture at least");
07786         dPPI = pCap->dPixelsPerInch;
07787         cinfo.caFlags.CalcScaledPixWidth = pCap->info.caFlags.CalcScaledPixWidth;
07788 
07789         CaptureMatrix = RenderMatrix;
07790     }
07791     else
07792     {
07793         // If the caller specified a particular DPI we will assume he wants the capture
07794         // to grab the rendered objects at 100% scale...
07795         // No need to construct a new matrix in a complex way - the clip rect and
07796         // object are all stored in doccoords.
07797 //      CaptureMatrix = Identity;
07798     }
07799 
07800     ERROR3IF(cinfo.caFlags.CalcScaledPixWidth && dPPI!=GetTopCaptureBitmap()->dPixelsPerInch,
07801                 "StartCapture asked to calc ScaledPixelWidth when PPI differs from base PPI - are you sure about this?");
07802 
07803     ERROR3IF(cinfo.caFlags.CalcScaledPixWidth && dPPI!=GetTopCaptureBitmap()->dPixelsPerInch,
07804                 "StartCapture asked to compute scaled pixel width in capture when res differs from current res");
07805 
07806     // In non-Master Captures, make sure that we use a default colour context
07807     // to prevent multiple colour corrections when rendering bitmaps in "print preview"
07808     // type modes...
07809     ColourContext* pColContext = NULL;
07810     if (!cinfo.caFlags.Master)
07811     {
07812         BOOL bOldForce = RenderView->SetForceDefaultColourContexts();
07813         pColContext = RenderView->GetColourContext(COLOURMODEL_RGBT);
07814         RenderView->SetForceDefaultColourContexts(bOldForce);
07815     }
07816     else
07817     {
07818         // Must get RenderRegion's current colour context for Master Capture
07819         pColContext = CurrentColContext;
07820     }
07821 
07822     // Create a new capture instance...
07823     Capture* pNewCapture = new Capture(pOwner, cinfo, CaptureMatrix, CaptureRect, dPPI, pColContext);
07824     ENSURE(!pNewCapture->IsMaster(), "Can only have one master capture!");
07825 
07826     // ------------------------------------
07827     // If we only want to grab the rendering when it's complete then we don't need to make a bitmap
07828     if (pNewCapture && pNewCapture->info.caFlags.GrabRendered)
07829     {
07830         // Put this new capture on the top of the capture stack
07831         ENSURE(pNewCapture->lpBitmapInfo==NULL && pNewCapture->lpBits==NULL, "GrabRendered capture owns a bitmap!");
07832         m_CaptureStack.Push(pNewCapture);
07833         return pNewCapture;
07834     }
07835 
07836     // ------------------------------------
07837     // Optimisation to cut down the number of separate capture bitmaps that are used:
07838     //
07839     // If the caller thinks that a node can supply a bitmap directly then use that
07840     // instead of capturing
07841     if (pNewCapture && pNewCapture->info.caFlags.AllowDirect && pDirectSupplier)
07842     {
07843         BOOL bDirectCapture = SetupDirectCapture(pNewCapture, pDirectSupplier);
07844         if (bDirectCapture)
07845         {
07846             ENSURE(pNewCapture->lpBitmapInfo==NULL && pNewCapture->lpBits==NULL, "AllowDirectCapture capture owns a bitmap!");
07847             m_CaptureStack.Push(pNewCapture);
07848             return pNewCapture;
07849         }
07850     }
07851 
07852     // ------------------------------------
07853     // Grab a bitmap for the capture...
07854     LPBITMAPINFO    bmInfo = NULL;
07855     LPBYTE          bmBits = NULL;
07856 
07857     // NB Millipoint endpoints don't necessarily fall on exact pixel boundaries.
07858     // Hence use following function to find out which pixels the millipoints fall on
07859     WinRect Rect = CalculateWinRect(CaptureMatrix, CaptureRect, dPPI);
07860     UINT32 PixelWidth = Rect.width;
07861     UINT32 PixelHeight = Rect.height;
07862     if (PixelWidth==0 || PixelHeight==0 || 
07863         PixelWidth*PixelHeight>256*1024*1024 ||
07864         PixelWidth >GetDrawContext()->GetMaxBitmapWidth() ||
07865         PixelHeight>GetDrawContext()->GetMaxBitmapDepth())
07866     {
07867         delete pNewCapture;
07868         return NULL;
07869     }
07870 
07871     // This code gets the pixelised version of the capture rect
07872     // and stores that in the Capture to ensure ULTIMATE accuracy when blitting the bitmap
07873     // using RenderBits
07874     DocRect rectPix = OSRenderRegion::WinRectToDoc(CaptureMatrix, Rect, dPPI);
07875     ENSURE(rectPix.IsValid(), "Pixelised rect is not valid in StopCapture");
07876     pNewCapture->CaptureRect = rectPix;
07877 
07878     bmInfo = AllocDIB(PixelWidth, PixelHeight, 32, &bmBits, NULL, FALSE);
07879     if (bmInfo==NULL || bmBits==NULL)
07880     {
07881         ENSURE(FALSE,"Couldn't create bitmap for offscreen rendering.");
07882         return NULL;
07883     }
07884 
07885 if (dPPI!=PixelsPerInch)
07886 {
07887     ENSURE(!bCaptureBackground, "Sorry StartCapture can't scale blit background into capture yet\n");
07888 
07889     double xppm = dPPI * INCHES_PER_METRE;
07890     double yppm = dPPI * INCHES_PER_METRE;
07891     bmInfo->bmiHeader.biXPelsPerMeter = (INT32)(xppm + 0.5);
07892     bmInfo->bmiHeader.biYPelsPerMeter = (INT32)(yppm + 0.5);
07893 }
07894 
07895     if (bTransparent)
07896         bmInfo->bmiHeader.biCompression = 0x80000001;
07897 
07898 //  pNewCapture->AllocateDIB(bTransparent);
07899     pNewCapture->SetDIB(bmInfo, bmBits);
07900 
07901     // Initialise the bitmap contents...
07902     if (bCaptureBackground && dPPI==PixelsPerInch)
07903     {
07904         // Blit the background from the main bitmap
07905         WinRect rectBack = CalculateWinRect(CurrentClipRect);
07906         WinRect rectOffs = CalculateWinRect(CaptureRect);
07907         INT32 left = rectOffs.x - rectBack.x;
07908         INT32 top = rectBack.GetBottom() - rectOffs.GetBottom();
07909         DIBUtil::CopyBitmapSection(pBitmapInfo, pBits, pNewCapture->lpBitmapInfo, pNewCapture->lpBits, top, left);
07910     }
07911     else
07912     {
07913         BYTE* pSetBits = (BYTE*)pNewCapture->lpBits;
07914 
07915         // ensure all bitmap memory is initialised (ie don't use the 
07916         // bogus info from the bmp header dimensions)
07917         UINT32 BmpSize = GetDIBBitsSize( &(pNewCapture->lpBitmapInfo->bmiHeader) );
07918         UINT32 Index = 0;
07919 
07920         ENSURE(pNewCapture->lpBitmapInfo->bmiHeader.biBitCount==32,"Non-32bpp bitmap in offscreen rendering!");
07921 
07922         if (bTransparent)
07923             while (Index < BmpSize)
07924             {
07925                 // initial values for using internal alpha channelled format
07926                 // fully transparent black bacground
07927 
07928                 pSetBits[Index++] = 0x00;
07929                 pSetBits[Index++] = 0x00;
07930                 pSetBits[Index++] = 0x00;
07931                 pSetBits[Index++] = 0xFF;
07932             }
07933         else
07934             while (Index < BmpSize)
07935             {
07936                 // fully opaque white background
07937                 pSetBits[Index++] = 0xFF;
07938                 pSetBits[Index++] = 0xFF;
07939                 pSetBits[Index++] = 0xFF;
07940                 pSetBits[Index++] = 0x00;
07941             }
07942     }
07943 
07944     // Put this new capture on the top of the capture stack
07945     m_CaptureStack.Push(pNewCapture);
07946 
07947     // Switch rendering to work into this new capture
07948     SetRenderToCapture(pNewCapture);
07949 
07950     // We need to clear the current clipregion here because when the capture is stopped
07951     // and plotted into the parent capture it will itself be clipped
07952     // If the cached bitmap is to be used to speed up dragging then we want the cached
07953     // image to be unclipped
07954     if (cinfo.caFlags.UnClip)
07955     {
07956         SaveContext();
07957         ClipRegionAttribute* pClipRegion = new ClipRegionAttribute();   // Default ClipRegion has no path, thus infinite
07958         if (pClipRegion)
07959         {
07960 // Don't try to record clip region attr because during forced deletion
07961 // it will be deleted before the destructor tries to restore all attributes
07962 // contexts down to the ground.
07963 // Instead mark the attr as Temporary so that it will be deleted when
07964 // StopCapture calls RestoreContext below.
07965 //          pNewCapture->SetClipRegionAttrValue(pClipRegion);
07966 //          SetClipRegion(pClipRegion, FALSE);
07967             SetClipRegion(pClipRegion, TRUE);       // Delete automatically when it goes out of scope
07968         }
07969     }
07970 
07971     return pNewCapture;
07972 }
07973 
07974 
07975 
07976 
07977 /********************************************************************************************
07978 
07979 >   BOOL GRenderRegion::StopCapture(CCObject* pOwner,
07980                                     BOOL bRender = TRUE,
07981                                     BOOL bReleaseBitmap = FALSE,
07982                                     LPBITMAPINFO* plpBitmapInfo = NULL,
07983                                     LPBYTE* plpBits = NULL,
07984                                     DocRect* pCaptureRect = NULL,
07985                                     Matrix* pmatTransform = NULL,
07986                                     double* pdResolution = NULL)
07987 
07988     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
07989     Created:    30/06/2004
07990     Inputs:     pEndNode    - Node in tree which "owns" this capture
07991     Outputs:    -
07992     Returns:    TRUE if the Capture resulted in a bitmap being usefully created
07993     Purpose:    To stop a bitmap capture
07994     SeeAlso:    GRenderRegion::StartCapture
07995 
07996 ********************************************************************************************/
07997 
07998 BOOL GRenderRegion::StopCapture(CCObject* pOwner,
07999                                 BOOL bRender,
08000                                 BOOL bReleaseBitmap,
08001                                 LPBITMAPINFO* plpBitmapInfo,
08002                                 LPBYTE* plpBits,
08003                                 DocRect* pCaptureRect,
08004                                 Matrix* pmatTransform,
08005                                 double* pdResolution)
08006 {
08007     Capture* pCapture = GetTopCapture();
08008     if (pCapture==NULL)
08009         return FALSE;
08010 
08011     if (pCapture->IsMaster())
08012     {
08013         ERROR2(FALSE, "StopCapture called on the master capture!\n");
08014         return FALSE;
08015     }
08016 
08017     // If we own the current rendering bitmap then we can do useful things with it...
08018     BOOL bOK = TRUE;
08019     if (pCapture->OwnsBitmap())
08020     {
08021         // We may need to restore the previous clipping state
08022         if (pCapture->IsUnclipped())
08023         {
08024             RestoreContext();
08025         }
08026 
08027         // Ensure output values are cleared before we go any further
08028         if (plpBitmapInfo && plpBits)
08029         {
08030             *plpBitmapInfo = NULL;
08031             *plpBits = NULL;
08032         }
08033 
08034         if (pCaptureRect)
08035         {
08036             *pCaptureRect = DocRect(0,0,0,0);
08037         }
08038 
08039         // Pop this capture off the stack
08040         m_CaptureStack.Pop();
08041 
08042         // And Return rendering to the previous capture
08043         SetRenderToCapture(GetTopCaptureBitmap(), TRUE);
08044 
08045         // Get convenient access to capture details
08046         LPBITMAPINFO lpCapturedBitmapInfo = pCapture->lpBitmapInfo;
08047         LPBYTE lpCapturedBits = pCapture->lpBits;
08048         DocRect rectCaptured = pCapture->CaptureRect;
08049         ENSURE(rectCaptured.IsValid(), "Invalid rect in StopCapture");
08050 
08051         // We have to normalise the bitmap if it was transparent because GDraw
08052         // produces a pre-multiplied format that it CAN'T render!
08053         if (lpCapturedBitmapInfo && lpCapturedBits && lpCapturedBitmapInfo->bmiHeader.biCompression==0x80000001)
08054         {
08055             GetDrawContext()->ConvertBitmap(
08056                                         &lpCapturedBitmapInfo->bmiHeader, lpCapturedBits,
08057                                         &lpCapturedBitmapInfo->bmiHeader, lpCapturedBits,
08058                                         0
08059                                     );
08060             // Leave biCompression as 80000001... Otherwise cache system won't know a transp from a non-transp
08061         }
08062 
08063         // If the caller wants the resulting bitmap back then give it to him...
08064         if (plpBitmapInfo && plpBits && pCaptureRect && !bReleaseBitmap)
08065         {
08066             *plpBitmapInfo = lpCapturedBitmapInfo;
08067             *plpBits = lpCapturedBits;
08068             *pCaptureRect = rectCaptured;
08069         }
08070 
08071         // If required, render the captured bitmap back to the main rendering bitmap
08072         if (bRender && lpCapturedBitmapInfo && lpCapturedBits)
08073         {
08074             // Assume that a capture is always offscreen and will always want to
08075             // blit back to screen at the moment...
08076             RenderBits(lpCapturedBitmapInfo, lpCapturedBits, rectCaptured);
08077         }
08078 
08079         // If required, release the captured bitmap because no one needs to hold on to it...
08080         if (bReleaseBitmap)
08081             pCapture->FreeDIB();
08082 
08083         delete pCapture;
08084     }
08085     else
08086     {
08087         // Ensure output values are cleared before we go any further
08088         if (plpBitmapInfo && plpBits)
08089         {
08090             *plpBitmapInfo = NULL;
08091             *plpBits = NULL;
08092         }
08093 
08094         // Else return a 24bpp grab to the caller (if he wants a bitmap)...
08095         if (pCaptureRect && plpBitmapInfo && plpBits && pCapture->info.caFlags.GrabRendered)
08096         {
08097             ENSURE(pCaptureRect->IsValid(), "Invalid rect in StopCapture");
08098 
08099             // Semi-bodge:
08100             // If we capture colour corrected bitmap then things will go wrong when
08101             // the plot this bitmap in future because it will get colour corrceted
08102             // again.
08103             // If we knew that the stored bitmap had been corrceted we could avoid further
08104             // correction - but we don't store that info with cached bitmaps
08105             // So, for simplicity we will just prevent cacheing in that situation
08106             //
08107             Capture* pMasterCapture = GetMasterCapture();
08108             ENSURE(pMasterCapture, "Can't find master capture!");
08109             if (pMasterCapture->pColContext == ColourContext::GetGlobalDefault(COLOURMODEL_RGBT))
08110                 bOK = GrabBitmap(pCaptureRect, plpBitmapInfo, plpBits);         // NOTE! may change CaptureRect!
08111             else
08112                 bOK = FALSE;
08113         }
08114 
08115         NodeRenderableInk* pSupplier = pCapture->GetDirectSupplier();
08116         if (pCapture->info.caFlags.Direct && pSupplier)
08117         {
08118             bOK = pSupplier->GetDirectBitmap(this, plpBitmapInfo, plpBits, pCaptureRect, pmatTransform, pdResolution);
08119         }
08120 
08121         // Pop the capture off the stack now
08122         // (If it doesn't own the current bitmap then it must have already released it)
08123         m_CaptureStack.Pop();
08124 
08125         delete pCapture;
08126     }
08127 
08128 #ifdef DEBUG_ATTACH_CAPTURED_BMP
08129 {
08130     if (*plpBitmapInfo && *plpBits)
08131     {
08132         // Create a Kernel bitmap from the bmp data.
08133         CWxBitmap* wBitmap          = new CWxBitmap(*plpBitmapInfo, *plpBits);
08134         KernelBitmap* OffscreenBitmap   = new KernelBitmap(wBitmap,TRUE);
08135         OffscreenBitmap->AttachDebugCopyToCurrentDocument("Captured Bitmap");
08136         wBitmap->BMBytes = ((CWxBitmap*)OILBitmap::Default)->BMBytes;
08137         delete OffscreenBitmap;
08138     }
08139 }
08140 #endif
08141 
08142     // reset the ChangedBBox
08143     if (MasterCaptureIsCurrent())
08144     {
08145         // Restored from rendering into offscreen bmp to GRenderRegions orignal invalid bmp
08146         // Reset the ChangedBBox so full blitting occurs to update invalid region
08147         RECT bbox;
08148         bbox.left = 0;
08149         bbox.right = WRect.width;
08150         bbox.top = 0;
08151         bbox.bottom = WRect.height; // NB upside down (GDI coords)
08152 
08153         if (!GetDrawContext()->SetChangedBBox(&bbox))
08154         {
08155             ERROR3("GDraw_SetChangedBBox failed");
08156         }
08157     }
08158 
08159     return bOK;
08160 }
08161 
08162     
08163     
08164     
08165 /********************************************************************************************
08166 
08167 >   BOOL GRenderRegion::ChangeCapture(CAPTUREINFO cinfo,
08168                                     BOOL bTransparent,
08169                                     BOOL bCaptureBackground)
08170 
08171     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
08172     Created:    09/07/2004
08173     Inputs:     -
08174     Outputs:    -
08175     Purpose:    To inform the capture stack that things (transparency) have changed
08176 
08177 ********************************************************************************************/
08178 
08179 BOOL GRenderRegion::ChangeCapture(CAPTUREINFO cinfo,
08180                                 BOOL bTransparent,
08181                                 BOOL bCaptureBackground)
08182 {
08183     // If there's a current RGBT capture active and we are changing to a non-transparent capture
08184     // Then mark that Capture as no longer being transparent
08185     // Blit whatever we have so far into the parent bitmap
08186     // Tell all enclosing captures (further up the stack) that they can no longer be transparent
08187     // either
08188     Capture* pCurrentCapture = GetTopCapture();
08189     if (pCurrentCapture==NULL)
08190         return FALSE;
08191 
08192     if (pCurrentCapture->IsMaster())
08193     {
08194         ENSURE(m_CaptureStack.Size()==1, "Master Capture not bottom capture in ChangeCapture");
08195         return FALSE;
08196     }
08197 
08198     // If the current capture has same transparency setting than that requested
08199     // we can just exit as if we succeeded...
08200     if (bTransparent == pCurrentCapture->IsTransparent())
08201         return TRUE;
08202 
08203     ERROR2IF(bTransparent, FALSE, "ChangeCapture doesn't cope with changing UP to transparency yet");
08204 
08205     // Mark the current capture as being no longer transparent...
08206     ListT<Capture*>* pList = m_CaptureStack.GetListT();
08207 
08208     {
08209         // If any capture in the stack is locked to be transparent, no matter what, then
08210         // we should not change any of the existing captures...
08211         Capture* pCapture = NULL;
08212         ListT<Capture*>::Iterator it = pList->End();
08213         INT32 nListSize = pList->Size();
08214         for (INT32 i = 0; i < nListSize; i++)
08215         {
08216             pCapture = *(--it);
08217 
08218             // If the capture is locked transparent then we can stop all further processing
08219             if (pCapture->IsTransparent() && pCapture->info.caFlags.LockedTransparent)
08220                 return TRUE;
08221 
08222             // If the master capture is transparent, treat as if it has LockedTransparent set
08223             if (pCapture->IsMaster() && pCapture->IsTransparent())
08224                 return TRUE;
08225         }
08226     }
08227 
08228     {
08229         // We are allowed to remove this capture and others from the stack until we reach
08230         // an opaque capture...
08231         Capture* pCapture = NULL;
08232         ListT<Capture*>::Iterator it = pList->End();
08233         INT32 nListSize = pList->Size();
08234         for (INT32 i = 0; i < nListSize; i++)
08235         {
08236             pCapture = *(--it);
08237 
08238             // If the captured bitmap is non-transparent then we can stop changing captures now
08239             if (pCapture->IsMaster())
08240                 break;
08241             if (!pCapture->IsTransparent())
08242                 break;
08243 
08244             // If this capture can be collapsed
08245             if (pCapture->info.caFlags.CollapseToMaster)
08246             {
08247                 // First restore the previous state (so we can draw into the original bitmap inside the GoingOutOfScope function)
08248                 // and free the offscreen state stack memory which held this info
08249                 Capture* pPrevCapture = GetTopCaptureBitmap(pCapture);
08250                 ENSURE(pPrevCapture, "Failed to find parent capture with bitmap!");
08251                 ENSURE(pPrevCapture->OwnsBitmap(), "At least one parent capture should own a bitmap!");
08252 
08253                 // We may need to restore the previous clipping state
08254                 if (pCapture->info.caFlags.UnClip)
08255                 {
08256                     RestoreContext();
08257                     pCapture->info.caFlags.UnClip = FALSE;
08258                 }
08259 
08260                 SetRenderToCapture(pPrevCapture);
08261 
08262                 LPBITMAPINFO lpCapturedBitmapInfo = pCapture->lpBitmapInfo;
08263                 LPBYTE lpCapturedBits = pCapture->lpBits;
08264                 DocRect rectCaptured = pCapture->CaptureRect;
08265 
08266                 // We have to normalise the bitmap if it was transparent because GDraw
08267                 // produces a pre-multiplied format that it CAN'T render!
08268                 if (lpCapturedBitmapInfo && lpCapturedBits && lpCapturedBitmapInfo->bmiHeader.biCompression==0x80000001)
08269                 {
08270                     GetDrawContext()->ConvertBitmap(
08271                                                 &lpCapturedBitmapInfo->bmiHeader, lpCapturedBits,
08272                                                 &lpCapturedBitmapInfo->bmiHeader, lpCapturedBits,
08273                                                 0
08274                                             );
08275                 }
08276 
08277                 // Render the captured bitmap back to the main rendering bitmap
08278                 if (lpCapturedBitmapInfo && lpCapturedBits)
08279                 {
08280                     RenderBits(lpCapturedBitmapInfo, lpCapturedBits, rectCaptured);
08281                 }
08282 
08283                 // Release this bitmap (marks capture as no longer owning a bitmap)
08284                 pCapture->FreeDIB();
08285             }
08286             else if (pCapture->info.caFlags.LockedTransparent)
08287             {
08288                 // Do nothing - we want to retain 32BPP even though someone wants less!
08289                 // Rely on GDraw to make it's best attempt from now on!
08290                 //
08291                 // Break the loop here because since this capture is going to remain 32BPP
08292                 // there's no point fiddling around with any of the others
08293                 ERROR3("Shouldn't get here!");
08294                 break;
08295             }
08296             else
08297             {
08298                 // We must convert this capture into a non-transparent bitmap but we are not allowed
08299                 // to collapse it back to the master bitmap.
08300                 // To achieve this we will:
08301                 // 1. Create a new bitmap with the same parameters as the current capture, except opaque
08302                 // 2. Grab the background (and current nested capture state) into it
08303                 // 3. Remove current capture from stack and replace it with the new one
08304 
08305                 // 1.
08306                 Capture* pNewCapture = new Capture(pCapture, TRUE);
08307                 pNewCapture->SetTransparent(FALSE);
08308 
08309                 // 2.
08310                 SetRenderToCapture(pNewCapture);
08311                 RenderCurrentCaptureState(TRUE);
08312 
08313 #ifdef DEBUG_ATTACH_TCHANGE_BMP
08314 {
08315     // Create a Kernel bitmap from the bmp data.
08316     CWxBitmap* wBitmap          = new CWxBitmap(pNewCapture->lpBitmapInfo, pNewCapture->lpBits);
08317     KernelBitmap* OffscreenBitmap   = new KernelBitmap(wBitmap,TRUE);
08318     OffscreenBitmap->AttachDebugCopyToCurrentDocument("Transp Change Capture Bitmap");
08319     wBitmap->BMBytes = ((CWxBitmap*)OILBitmap::Default)->BMBytes;
08320     delete OffscreenBitmap;
08321 }
08322 #endif
08323                 // 3.
08324                 ENSURE(!pNewCapture->IsMaster(), "Can only have one master capture!");
08325                 ListT<Capture*>::Iterator itCap = it;       // Get temp iterator pointing at position of pCapture
08326                 it = pList->Insert(itCap, pNewCapture);         // Insert new capture before pCapture
08327                 pList->Erase(itCap);                        // Remove pCapture from stack
08328 
08329                 pCapture->FreeDIB();
08330                 delete pCapture;
08331             }
08332         }
08333     }
08334 
08335     SetRenderToCapture(GetTopCaptureBitmap());
08336 
08337     // reset the ChangedBBox
08338     if (MasterCaptureIsCurrent())
08339     {
08340         // Restored from rendering into offscreen bmp to GRenderRegions orignal invalid bmp
08341         // Reset the ChangedBBox so full blitting occurs to update invalid region
08342         RECT bbox;
08343         bbox.left = 0;
08344         bbox.right = WRect.width;
08345         bbox.top = 0;
08346         bbox.bottom = WRect.height; // NB upside down (GDI coords)
08347 
08348         if (!GetDrawContext()->SetChangedBBox(&bbox))
08349         {
08350             ERROR3("GDraw_SetChangedBBox failed");
08351         }
08352     }
08353 
08354     return TRUE;
08355 }
08356 
08357 
08358 
08359 
08360 /********************************************************************************************
08361 
08362 >   BOOL GRenderRegion::SetupDirectCapture(Capture* pNewCapture, NodeRenderableInk* pSupplier)
08363 
08364     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
08365     Created:    05/05/2005
08366     Inputs:     -
08367     Outputs:    -
08368     Returns:    TRUE if the Direct capture was setup successfully
08369     Purpose:    To setup a direct capture if that is possible
08370     SeeAlso:    GRenderRegion::StartCapture
08371 
08372 ********************************************************************************************/
08373 
08374 BOOL GRenderRegion::SetupDirectCapture(Capture* pNewCapture, NodeRenderableInk* pSupplier)
08375 {
08376     // Checks:
08377     ERROR2IF(pNewCapture->info.caFlags.Master, FALSE, "Can't set Master capture for Direct capturing!");
08378 
08379     if (pSupplier==NULL || !pSupplier->CanSupplyDirectBitmap())
08380         return FALSE;
08381 
08382     // All checks passed OK, so allow this capture to be Direct!
08383     pNewCapture->info.caFlags.Direct = TRUE;
08384     pNewCapture->SetDirectSupplier(pSupplier);
08385     return TRUE;
08386 }
08387 
08388 
08389 
08390 
08391 /********************************************************************************************
08392 
08393 >   BOOL GRenderRegion::RenderCurrentCaptureState(BOOL bStartFromMaster)
08394 
08395     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
08396     Created:    12/07/2004
08397     Inputs:     -
08398     Outputs:    -
08399     Purpose:    Render the current state of the capture stack into the specified bitmap
08400                 (For use when rendering is interrupted)
08401                 (For use when capture must be collapsed from 32BPP to 24BPP without affecting
08402                 the master bitmap)
08403 
08404 ********************************************************************************************/
08405 
08406 BOOL GRenderRegion::RenderCurrentCaptureState(BOOL bStartFromMaster)
08407 {
08408     if (MasterCaptureIsCurrent() && !TopCaptureIsDirect())
08409     {
08410         return FALSE;
08411     }
08412 
08413     // First, temporarilly capture rendering by
08414     // setting up a local capture referring to the DisplayBitmap
08415     // so that RenderBits operates into it - not the master bitmap
08416 //  SetRenderToCapture(pDisplayCapture);
08417     {
08418         // In this scope we are rendering into the Display bitmap...
08419         LPBITMAPINFO lpCapturedBitmapInfo = pBitmapInfo;
08420         LPBYTE lpCapturedBits = pBits;
08421         DocRect rectCaptured = CurrentClipRect;
08422 
08423         // Iterate through the capture stack from bottom to top, rendering whatever bitmap
08424         // state they have reached so far into the specified display bitmap
08425         //
08426         Capture* pCapture = NULL;
08427         ListT<Capture*>* pList = m_CaptureStack.GetListT();
08428 
08429         ListT<Capture*>::Iterator it = pList->Begin();
08430         INT32 nListSize = pList->Size();
08431         for (INT32 i = 0; i < nListSize; i++)
08432         {
08433             pCapture = *(it++);
08434 
08435             NodeRenderableInk* pSupplier = pCapture->GetDirectSupplier();
08436             if (pCapture->info.caFlags.Direct && pSupplier /*&& pCapture->info.caFlags.HasBeenSuppliedWithBitmap*/)
08437             {
08438                 // This capture gets its bitmap directly from a supplier node
08439                 // The fact that this capture exists means that the owner node
08440                 // hasn't done it own processing yet but the supplier node
08441                 // may have a bitmap ready to plot...
08442                 pSupplier->RenderDirectBitmapState(this);
08443             }
08444             else
08445             {
08446                 if (pCapture && pCapture->OwnsBitmap() && (i>0 || bStartFromMaster))
08447                 {
08448                     lpCapturedBitmapInfo = pCapture->lpBitmapInfo;
08449                     lpCapturedBits = pCapture->lpBits;
08450                     rectCaptured = pCapture->CaptureRect;
08451 
08452                     // We have to normalise the bitmap if it was transparent because GDraw
08453                     // produces a pre-multiplied format that it CAN'T render!
08454                     // The bitmap is stil in use so we have to normalise a copy...
08455                     if (lpCapturedBitmapInfo && lpCapturedBits && lpCapturedBitmapInfo->bmiHeader.biCompression==0x80000001)
08456                     {
08457                         // Make a temp copy
08458                         DIBUtil::CopyBitmap(lpCapturedBitmapInfo, lpCapturedBits, &lpCapturedBitmapInfo, &lpCapturedBits);
08459                         lpCapturedBitmapInfo->bmiHeader.biCompression = 0x80000001;     // CopyBitmap corrupts biCompression!
08460 
08461                         GetDrawContext()->ConvertBitmap(
08462                                                     &lpCapturedBitmapInfo->bmiHeader, lpCapturedBits,
08463                                                     &lpCapturedBitmapInfo->bmiHeader, lpCapturedBits,
08464                                                     0
08465                                                 );
08466                         // Render the captured bitmap to the supplied display bitmap
08467                         if (lpCapturedBitmapInfo && lpCapturedBits)
08468                         {
08469 TRACEUSER( "Phil", _T("RCCS: Rendering Collapsed %x %s\n"), pCapture, pCapture->GetRuntimeClass()->m_lpszClassName);
08470                             RenderBits(lpCapturedBitmapInfo, lpCapturedBits, rectCaptured);
08471                         }
08472 
08473                         // Release the temp copy
08474 						::FreeDIB(lpCapturedBitmapInfo, lpCapturedBits, NULL, FALSE);
08475                     }
08476                     else
08477                     {
08478                         // Render the captured bitmap to the supplied display bitmap
08479                         if (lpCapturedBitmapInfo && lpCapturedBits)
08480                         {
08481 TRACEUSER( "Phil", _T("RCCS: Rendering non-transp %x %s\n"), pCapture, pCapture->GetRuntimeClass()->m_lpszClassName);
08482                             RenderBits(lpCapturedBitmapInfo, lpCapturedBits, rectCaptured);
08483                         }
08484                     }
08485                 }
08486             }
08487         }
08488     }
08489 
08490     // Reset the state back to normal
08491 //  SetRenderToCapture(GetTopCapture());
08492 
08493     // Update changed Bounding Box
08494     RECT bbox;
08495     bbox.left = 0;
08496     bbox.right = WRect.width;
08497     bbox.top = 0;
08498     bbox.bottom = WRect.height; // NB upside down (GDI coords)
08499 
08500     if (!GetDrawContext()->SetChangedBBox(&bbox))
08501     {
08502         ERROR3("GDraw_SetChangedBBox failed");
08503     }
08504 
08505     return TRUE;
08506 }
08507 
08508 
08509 
08510 
08511 /********************************************************************************************
08512 
08513 >   Capture* GRenderRegion::GetTopCaptureBitmap(Capture* pFromCapture = NULL) const
08514 
08515     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
08516     Created:    27/07/2004
08517     Inputs:     -
08518     Outputs:    -
08519     Purpose:    Search down the Capture stack from the top or from the capture specified
08520                 until we find one that owns a bitmap. The master capture at the bottom
08521                 of the stack should ALWAYS own a bitmap!
08522 
08523 ********************************************************************************************/
08524 
08525 Capture* GRenderRegion::GetTopCaptureBitmap(Capture* pFromCapture) const
08526 {
08527     const ListT<Capture*>* pList = m_CaptureStack.GetListT();
08528 
08529     Capture* pCapture = NULL;
08530     ListT<Capture*>::ConstIterator it = pList->End();
08531     INT32 nListSize = pList->Size();
08532     INT32 i=0;
08533 
08534     if (pFromCapture)
08535     {
08536         for (i = 0; i < nListSize; i++)
08537         {
08538             pCapture = *(--it);
08539             if (pCapture == pFromCapture)
08540                 break;
08541         }
08542     }
08543 
08544     for (/*use i from above*/; i < nListSize; i++)
08545     {
08546         pCapture = *(--it);
08547         if (pCapture->OwnsBitmap())
08548             return pCapture;
08549     }
08550 
08551     return NULL;
08552 }
08553 
08554 
08555 
08556 
08557 /********************************************************************************************
08558 
08559 >   BOOL GRenderRegion::DumpCaptureStack()
08560 
08561     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
08562     Created:    13/07/2004
08563     Inputs:     -
08564     Outputs:    -
08565     Purpose:    Render the current state of the capture stack into the specified bitmap
08566                 (For use when rendering is interrupted)
08567 
08568 ********************************************************************************************/
08569 
08570 #ifdef _DEBUG
08571 BOOL GRenderRegion::DumpCaptureStack()
08572 {
08573     if (m_CaptureStack.Empty())
08574     {
08575         return FALSE;
08576     }
08577 
08578     TRACE( _T("Capture stack:\n"));
08579 
08580 //  LPBITMAPINFO lpCapturedBitmapInfo = pBitmapInfo;
08581 //  LPBYTE lpCapturedBits = pBits;
08582     DocRect rectCaptured = CurrentClipRect;
08583 
08584     Capture* pCapture = m_CaptureStack.Top();
08585     ListT<Capture*>* pList = m_CaptureStack.GetListT();
08586 
08587     ListT<Capture*>::Iterator it = pList->End();
08588     INT32 nListSize = pList->Size();
08589     for (INT32 i = 0; i < nListSize; i++)
08590     {
08591         pCapture = *(--it);
08592 
08593 //      CCObject* pOwner = pCapture->GetOwner();
08594 
08595 //      TRACE( _T("  %x Capture %x %s %d\n"), pCapture, pOwner, pOwner->GetRuntimeClass()->m_lpszClassName, pCapture->IsTransparent());
08596     }
08597 
08598     return TRUE;
08599 }
08600 #endif
08601 
08602 
08603 
08604 
08605 /********************************************************************************************
08606 
08607 >   BOOL GRenderRegion::SetRenderToCapture(Capture* pCapture, BOOL ApplyClipRegion = FALSE, BOOL bSetBitmap = TRUE)
08608 
08609     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
08610     Created:    01/07/2004
08611     Inputs:     pCapture - Pointer to capture object which is to receiev all further rendering
08612     Outputs:    -
08613     Returns:    TRUE if worked
08614     Purpose:    To connect this renderregion to a bitmap along with clipping and view
08615                 transformation information
08616                 (a "capture")
08617     SeeAlso:    GRenderRegion::StartCapture
08618 
08619 ********************************************************************************************/
08620 
08621 BOOL GRenderRegion::SetRenderToCapture(Capture* pCapture, BOOL ApplyClipRegion, BOOL bSetBitmap)
08622 {
08623     ERROR2IF(pCapture==NULL, FALSE, "SetRenderToCapture passed NULL capture pointer");
08624     // We may be called on captures that don't own a bitmap to restore
08625     // their other settings into the RenderRegion.
08626     // So we must cope with the bitmap pointers being NULL
08627     if (pCapture->lpBitmapInfo && pCapture->lpBits && bSetBitmap)
08628     {
08629         LPBITMAPINFOHEADER pbmiHeader = &(pCapture->lpBitmapInfo->bmiHeader);
08630 
08631         // This test just here to notify developers of old legacy use of GDraw
08632         // at anything less than 24BPP
08633 //      if (pbmiHeader->biBitCount < 24)
08634 //      {
08635 //          TRACE( _T("FYI: Attempt to use < 24BPP bitmap with GDraw\n"));
08636 //      }
08637 
08638         if (pbmiHeader->biWidth!=0 && pbmiHeader->biHeight!=0 && pbmiHeader->biBitCount!=0)
08639         {
08640             // default is 2 - see gdrawcon.h, gconsts.h
08641 //          DWORD Format = (pbmiHeader->biBitCount == 8) ? 0 : 2;
08642 //          if (!GetDrawContext()->SetBitmap(pbmiHeader, pCapture->lpBits, Format))
08643             if (!GetDrawContext()->SetBitmap(pbmiHeader, pCapture->lpBits))
08644             {
08645                 ERROR3("GDraw_SetDIBitmap failed");
08646                 return FALSE;
08647             }
08648         }
08649     }
08650 
08651     // Set GRenderRegion member variables as well
08652     //
08653     // Only set clip rect if bitmap actually changes
08654     // This allows routines that fiddle with the cliprect (RenderOptimalBitmapPhase)
08655     // to retain their fiddles while calling StartRender.
08656     if (pBitmapInfo != pCapture->lpBitmapInfo || pBits != pCapture->lpBits)
08657         CurrentClipRect = pCapture->CaptureRect;
08658 
08659     RenderMatrix    = pCapture->CaptureMatrix;
08660     GMATRIX gmat = MakeGavinMatrix(RenderMatrix, CurrentClipRect, pCapture->dPixelsPerInch, pCapture->IsMaster());
08661     SetGavinMatrix(&gmat);
08662 
08663     if (!GetDrawContext()->SetMatrix(&gmat))
08664     {
08665         ERROR3("GDraw_SetMatrix failed");
08666         return FALSE;
08667     }
08668 
08669     pBitmapInfo     = pCapture->lpBitmapInfo;
08670     pBits           = pCapture->lpBits;
08671     CurrentColContext = pCapture->pColContext;
08672     RenderView->SetForceDefaultColourContexts(!pCapture->IsMaster());
08673     PixelsPerInch   = pCapture->dPixelsPerInch;
08674 
08675     // Calc new values for the stored pixel width members based on PixelsPerInch
08676     // (First set all values to unscaled version)
08677     PixelWidth      = CalcPixelWidth();
08678     ScaledPixelWidth = PixelWidth;
08679     dScaledPixelWidth = CalcPixelWidthDouble();
08680 
08681     // Only set ScaledPixelWidth to its true value for bitmaps
08682     // Otherwise it's set identically to PixelWidth so that nested captures
08683     if (pCapture->lpBitmapInfo && pCapture->lpBits && bSetBitmap)
08684     {
08685         if (pCapture->info.caFlags.CalcScaledPixWidth || pCapture->info.caFlags.Master)
08686         {
08687             ScaledPixelWidth = CalcScaledPixelWidth();
08688             dScaledPixelWidth = CalcScaledPixelWidthDouble();
08689         }
08690     }
08691 
08692     // Update the Windows rectangle version of the current clip rect
08693 // Nope, don't do that, leave WRect referring to Windows version of Master Capture at all times...
08694 //  WRect           = CalculateWinRect(RenderMatrix, CurrentClipRect, PixelsPerInch);
08695 
08696     // we must do this after we've changed CurrentClipRect.
08697     SetupFuzzyClipRects();
08698 
08699     // set gdraw REGION or RECT for new GDraw context
08700 //  if (!ApplyClipRegion)
08701 //  {
08702         // general case is to draw offscreen bmp without clip region applied
08703         // We apply the clip region when restoring so that it is in place
08704         // if we draw the offscreen bitmap to the original bmp (where the 
08705         // clipregion was applied)
08706         if ( !GetDrawContext()->ClipRectangle((LPRECT)&pCapture->CaptureRect) )
08707         {
08708             ERROR3("GDraw_ClipRectangle failed");
08709             return FALSE;
08710         }
08711 //  }
08712 //  else
08713 //  {
08714         // placed after CurrentClipRect reset
08715         ApplyCurrentClipRegion();
08716 //  }
08717 
08718     // Following code from StartRender()
08719     BOOL bHintStrokedLines = (pCapture->info.caFlags.Master || pCapture->dPixelsPerInch==GetMasterCapture()->dPixelsPerInch);
08720 //TRACEUSER( "Phil", _T("Hint flag = %d, IsMaster = %d\n"), bHintStrokedLines, pCapture->info.caFlags.Master);
08721     SetQualityLevel();
08722     GetDrawContext()->SetHintingFlag(bHintStrokedLines);
08723     GetDrawContext()->SetDashAdjustmentFlag(FALSE);
08724 
08725     // work out the brush alignment
08726     // algorithm based on code from OSRenderRegion::InitAttributes
08727     POINT DocOrigin, OSOrigin;
08728     DocOrigin.x = 0;
08729     DocOrigin.y = 0;
08730 
08731     // Then we transform it into OSCoords
08732     GetDrawContext()->TransformPath( &DocOrigin, &OSOrigin, 1, &gmat );
08733 
08734     // Once we've shifted then right by FX, they're in pixel co-ords, which is what
08735     // SetHalftoneOrigin is expecting them to be in
08736     const INT32 BrushX = OSOrigin.x >> FX;
08737     const INT32 BrushY = -(OSOrigin.y >> FX);                   // has to be negated to work
08738 
08739     GetDrawContext()->SetHalftoneOrigin( BrushX, BrushY );
08740 
08741     if (pCapture->info.caFlags.QualityNormal)
08742     {
08743         // TODO: Set normal quality, maybe only if current quality is >= NORMAL
08744         this->SetDefaultQuality();
08745     }
08746 
08747     // Set smoothing flags according to cfBITMAPSMOOTHING and cfTILFILTERING
08748     SetSmoothingFlags(NULL);
08749 
08750     return TRUE;
08751 }
08752 
08753 
08754 
08755 
08756 /********************************************************************************************
08757 
08758 >   BOOL GRenderRegion::TranspTypeIsRGBTCompatible(UINT32 ttype) const
08759 
08760     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
08761     Created:    02/02/2005
08762     Inputs:     ttype - Camelot-style transparency type
08763     Outputs:    -
08764     Returns:    TRUE if the transparency type can be rendered accurately into RGBT bitmap
08765                 by GDraw
08766     Purpose:    Discover whether this transparency type can be rendered into RGBT bitmap
08767                 by GDraw. (Things like stain and bleach cannot be accurately captured in
08768                 the T channel of the RGBT bitmap.)
08769     SeeAlso:    GRenderRegion::ChangeCapture
08770     Notes:      Gavin says (02/02/2005):
08771                 The following are I think OK: 0,1,4,7,19,20,21,22,23,24,25,26,27
08772                 and, I think, the bevel types 34,35,36,37,38,39.
08773 
08774 ********************************************************************************************/
08775 
08776 static BOOL TC[40] = {
08777                         TRUE,       // 0
08778                         TRUE,       // 1
08779                         FALSE,      // 2
08780                         FALSE,      // 3
08781                         TRUE,       // 4
08782                         FALSE,      // 5
08783                         FALSE,      // 6
08784                         TRUE,       // 7
08785                         FALSE,      // 8
08786                         FALSE,      // 9
08787                         FALSE,      // 10
08788                         FALSE,      // 11
08789                         FALSE,      // 12
08790                         FALSE,      // 13
08791                         FALSE,      // 14
08792                         FALSE,      // 15
08793                         FALSE,      // 16
08794                         FALSE,      // 17
08795                         FALSE,      // 18
08796                         TRUE,       // 19
08797                         TRUE,       // 20
08798                         TRUE,       // 21
08799                         TRUE,       // 22
08800                         TRUE,       // 23
08801                         TRUE,       // 24
08802                         TRUE,       // 25
08803                         TRUE,       // 26
08804                         TRUE,       // 27
08805                         FALSE,      // 28
08806                         FALSE,      // 29
08807                         FALSE,      // 30
08808                         FALSE,      // 31
08809                         FALSE,      // 32
08810                         FALSE,      // 33
08811                         TRUE,       // 34
08812                         TRUE,       // 35
08813                         TRUE,       // 36
08814                         TRUE,       // 37
08815                         TRUE,       // 38
08816                         TRUE,       // 39
08817                       };
08818 
08819 BOOL GRenderRegion::TranspTypeIsRGBTCompatible(UINT32 ttype) const
08820 {
08821     // First we must map the internal transparency type to GDraw's type
08822     TransparencyEnum gType = MapTranspTypeToGDraw(ttype, FALSE);        // Assume flat fill...
08823     return TC[gType];
08824 }
08825 
08826 
08827 
08828 
08829 /********************************************************************************************
08830 
08831 >   TransparencyEnum GRenderRegion::MapTranspTypeToGDraw(UINT32 ttype, BOOL bGraduated) const
08832 
08833     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
08834     Created:    02/02/2005
08835     Inputs:     ttype - Camelot-style transparency type
08836     Outputs:    -
08837     Returns:    GDraw's TransparencyEnum
08838     Purpose:    Map Camelot's internal transp type to GDraw's transp type
08839     Notes:      This function only understands FLAT and GRAD - it will never map a Camelot
08840                 transparency type to one of GDraw's "Colour and transp" values
08841 
08842 ********************************************************************************************/
08843 
08844 TransparencyEnum GRenderRegion::MapTranspTypeToGDraw(UINT32 ttype, BOOL bGraduated) const
08845 {
08846     if (ttype == 0)
08847         return T_NONE;
08848 
08849     if (bGraduated)
08850     {
08851         if (RenderFlags.HitDetect)
08852             return (enum TransparencyEnum) (T_GRAD_REFLECTIVE);
08853 
08854         if (ttype <= TT_Bleach)
08855         {
08856             // These are the old style for
08857             // Solid = 0, Mix = 1, Bleach = 2 and Stainedglass = 3
08858             return (enum TransparencyEnum) (ttype-TT_Mix + T_GRAD_REFLECTIVE);
08859         }
08860 
08861         if (ttype >= TT_CONTRAST && ttype <= TT_BEVEL)
08862         {
08863             // These are the new Transparency types Contrast = 13, Saturation = 16, Darken = 19,
08864             // Lighten = 22, Brightness = 25, Luminosity = 28, Hue = 31, Bevel = 34
08865             return (enum TransparencyEnum) (ttype-TT_CONTRAST + T_GRAD_CONTRAST);
08866         }
08867     }
08868     else
08869     {
08870         if (RenderFlags.HitDetect)
08871             return (enum TransparencyEnum) (T_FLAT_REFLECTIVE);
08872 
08873         if (ttype <= TT_Bleach)
08874         {
08875             // These are the old style for
08876             // Solid = 0, Mix = 1, Bleach = 2 and Stainedglass = 3
08877             return (enum TransparencyEnum) (ttype-TT_Mix + T_FLAT_REFLECTIVE);
08878         }
08879 
08880         if (ttype >= TT_CONTRAST && ttype <= TT_BEVEL)
08881         {
08882             // These are the new Transparency types Contrast = 13, Saturation = 16, Darken = 19,
08883             // Lighten = 22, Brightness = 25, Luminosity = 28, Hue = 31, Bevel = 34
08884             return (enum TransparencyEnum) (ttype-TT_CONTRAST + T_FLAT_CONTRAST);
08885         }
08886     }
08887 
08888     ERROR3("Invalid transp type");
08889     return T_NONE;
08890 }
08891 
08892 
08893 
08894 
08895 #ifdef _DEBUG
08896 void GRenderRegion::DebugTrace()
08897 {
08898 //  DIBUtil::FillColour24(lpBitmapInfo, lpBits);
08899 }
08900 #endif
08901 
08902 
08903 
08904 
08905 /********************************************************************************************
08906 
08907 >   void GRenderRegion::SetBitmapPointers(LPBITMAPINFO bi, LPBYTE by)
08908 
08909     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
08910     Created:    23/07/2004
08911     Inputs:     bi - new BITMAPINFO pointer
08912                 by - new BYTES pointer
08913     Outputs:    -
08914     Returns:    -
08915     Purpose:    To set the bitmap pointers for the master capture only, updating both the
08916                 working members and the versions stored in the master capture.
08917     SeeAlso:    GRenderRegion::StartCapture
08918 
08919 ********************************************************************************************/
08920 
08921 void GRenderRegion::SetBitmapPointers(LPBITMAPINFO bi, LPBYTE by)
08922 {
08923     Capture* pCapture = GetTopCaptureBitmap();
08924     ENSURE(pCapture, "SetBitmapPointers being called while there are no captures!\n");
08925     if (pCapture)
08926     {
08927         ENSURE(pCapture->IsMaster(), "SetBitmapPointers being called while child Captures are running\n");
08928         if (pCapture->IsMaster())
08929         {
08930             pCapture->SetDIB(bi, by);
08931         }
08932     }
08933 
08934     pBitmapInfo = bi;
08935     pBits = by;
08936 }
08937     
08938     
08939     
08940 /********************************************************************************************
08941 
08942 >   BOOL GRenderRegion::GetBitmapPointers(LPBITMAPINFO* ppInfo, LPBYTE* ppBits, BOOL bCorrectTransparency = TRUE)
08943 
08944     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
08945     Created:    14/06/2005
08946     Inputs:     -
08947     Outputs:    -
08948     Returns:    -
08949     Purpose:    To get the bitmap pointers for the master capture only.
08950     SeeAlso:    GRenderRegion::SetBitmapPointers
08951 
08952 ********************************************************************************************/
08953 
08954 BOOL GRenderRegion::GetBitmapPointers(LPBITMAPINFO* ppInfo, LPBYTE* ppBits, BOOL bCorrectTransparency)
08955 {
08956     Capture* pCapture = GetMasterCapture();
08957     ERROR2IF(!pCapture || !pCapture->IsMaster(), FALSE, "GetBitmapPointers can't find master capture!\n");
08958 
08959     if (bCorrectTransparency && pBitmapInfo->bmiHeader.biCompression==0x80000001)
08960     {
08961         GetDrawContext()->ConvertBitmap(&pBitmapInfo->bmiHeader, pBits,
08962                                         &pBitmapInfo->bmiHeader, pBits,
08963                                         0);
08964     }
08965 
08966     *ppInfo = pBitmapInfo;
08967     *ppBits = pBits;
08968 
08969     return TRUE;
08970 }
08971     
08972     
08973     
08974 // Operations to control GDraw options
08975 // (will probably be in a dialog at some point)
08976 
08977 
08978 
08979 /*******************************************************************
08980 
08981 >   void OpGDraw::Do(OpDescriptor*)
08982 
08983     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
08984     Created:    3/2/94
08985     Inputs:     None
08986     Outputs:    None
08987     Returns:    None
08988     Purpose:    Toggles state of gdraw flag then forces a redraw.
08989     Errors:     None
08990 
08991 *******************************************************************/
08992 
08993 void OpGDraw::Do(OpDescriptor*)
08994 {
08995     GRenderRegion::WantDoGDraw ^= TRUE;
08996 
08997     // Iterate over all the documents, forcing a redraw of all the views.
08998     ListItem* pItem = Camelot.Documents.GetHead();
08999     while (pItem != NULL)
09000     {
09001         ((Document*) pItem)->ForceRedraw();
09002         pItem = Camelot.Documents.GetNext(pItem);
09003     }
09004 
09005     End();
09006 }
09007 
09008 
09009 /*******************************************************************
09010 
09011 >   OpGDraw::OpGDraw()
09012 
09013     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
09014     Created:    14/10/93
09015     Inputs:
09016     Outputs:
09017     Returns:
09018     Purpose:    Constructor for OpGDraw operation. It is not undoable.
09019     Errors:     None
09020 
09021 *******************************************************************/
09022 
09023 OpGDraw::OpGDraw()
09024 {
09025 }
09026 
09027 
09028 /*******************************************************************
09029 
09030 >   OpState OpGDraw::GetState(String_256*, OpDescriptor*)
09031 
09032     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
09033     Created:    14/10/93
09034     Inputs:
09035     Outputs:
09036     Returns:
09037     Purpose:    This item is always available when GDraw is available.
09038     Errors:     None
09039 
09040 *******************************************************************/
09041 
09042 OpState OpGDraw::GetState(String_256*, OpDescriptor*)
09043 {
09044     OpState OpSt;
09045 
09046     if (!GRenderRegion::CanDoGDraw)
09047     {
09048         OpSt.Greyed = TRUE;
09049         return OpSt;
09050     }
09051 
09052     if (GRenderRegion::WantDoGDraw)
09053         OpSt.Ticked = TRUE;
09054 
09055     return OpSt;
09056 }

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