beveler.cpp

Go to the documentation of this file.
00001 // $Id: beveler.cpp 1282 2006-06-09 09:46:49Z alex $
00003 // the bitmap beveler (for inner bevels)
00004 // DMc 2/6/98
00005 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00006 ================================XARAHEADERSTART===========================
00007  
00008                Xara LX, a vector drawing and manipulation program.
00009                     Copyright (C) 1993-2006 Xara Group Ltd.
00010        Copyright on certain contributions may be held in joint with their
00011               respective authors. See AUTHORS file for details.
00012 
00013 LICENSE TO USE AND MODIFY SOFTWARE
00014 ----------------------------------
00015 
00016 This file is part of Xara LX.
00017 
00018 Xara LX is free software; you can redistribute it and/or modify it
00019 under the terms of the GNU General Public License version 2 as published
00020 by the Free Software Foundation.
00021 
00022 Xara LX and its component source files are distributed in the hope
00023 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00024 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00025 See the GNU General Public License for more details.
00026 
00027 You should have received a copy of the GNU General Public License along
00028 with Xara LX (see the file GPL in the root directory of the
00029 distribution); if not, write to the Free Software Foundation, Inc., 51
00030 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00031 
00032 
00033 ADDITIONAL RIGHTS
00034 -----------------
00035 
00036 Conditional upon your continuing compliance with the GNU General Public
00037 License described above, Xara Group Ltd grants to you certain additional
00038 rights. 
00039 
00040 The additional rights are to use, modify, and distribute the software
00041 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00042 library and any other such library that any version of Xara LX relased
00043 by Xara Group Ltd requires in order to compile and execute, including
00044 the static linking of that library to XaraLX. In the case of the
00045 "CDraw" library, you may satisfy obligation under the GNU General Public
00046 License to provide source code by providing a binary copy of the library
00047 concerned and a copy of the license accompanying it.
00048 
00049 Nothing in this section restricts any of the rights you have under
00050 the GNU General Public License.
00051 
00052 
00053 SCOPE OF LICENSE
00054 ----------------
00055 
00056 This license applies to this program (XaraLX) and its constituent source
00057 files only, and does not necessarily apply to other Xara products which may
00058 in part share the same code base, and are subject to their own licensing
00059 terms.
00060 
00061 This license does not apply to files in the wxXtra directory, which
00062 are built into a separate library, and are subject to the wxWindows
00063 license contained within that directory in the file "WXXTRA-LICENSE".
00064 
00065 This license does not apply to the binary libraries (if any) within
00066 the "libs" directory, which are subject to a separate license contained
00067 within that directory in the file "LIBS-LICENSE".
00068 
00069 
00070 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00071 ----------------------------------------------
00072 
00073 Subject to the terms of the GNU Public License (see above), you are
00074 free to do whatever you like with your modifications. However, you may
00075 (at your option) wish contribute them to Xara's source tree. You can
00076 find details of how to do this at:
00077   http://www.xaraxtreme.org/developers/
00078 
00079 Prior to contributing your modifications, you will need to complete our
00080 contributor agreement. This can be found at:
00081   http://www.xaraxtreme.org/developers/contribute/
00082 
00083 Please note that Xara will not accept modifications which modify any of
00084 the text between the start and end of this header (marked
00085 XARAHEADERSTART and XARAHEADEREND).
00086 
00087 
00088 MARKS
00089 -----
00090 
00091 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00092 designs are registered or unregistered trademarks, design-marks, and/or
00093 service marks of Xara Group Ltd. All rights in these marks are reserved.
00094 
00095 
00096       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00097                         http://www.xara.com/
00098 
00099 =================================XARAHEADEREND============================
00100  */
00101 
00102 #include "camtypes.h"
00103 // camconfig.h must be included immediately after camtypes.h
00104 #include "camconfig.h"
00105 //#include "app.h"
00106 //#include "bmanip.h"
00107 //#include "paths.h"
00108 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 //#include "wincoord.h"
00110 //#include "bitmap.h"
00111 //#include "rndrgn.h"
00112 //#include "xadrwold.h"
00113 //#include "dibutil.h"
00114 
00115 #include "beveler.h"
00116 //#include "gclips.h"
00117 //#include "bshadow.h"
00118 //#include "biasgain.h"
00119 
00120 #include "gdraw2.h"
00121 //#include "errors.h"
00122 //#include "mario.h"
00123 
00124 #include "cstroke.h"
00125 
00126 //#include "gdrawasm.h"
00127 #include "grndrgn.h"
00128 
00129 #include "camprofile.h"
00130 
00131 #include <math.h>
00132 #include <stdio.h>
00133 
00134 #define new CAM_DEBUG_NEW
00135 
00137 // These two defines are the max width and height values for the beveling block sizes!
00138 // They are both pixel sizes and DO NOT represent the scaled values!
00139 #define BEVELMAXBITMAPWIDTH     1024
00140 #define BEVELMAXBITMAPHEIGHT    128
00141 
00142 // 256 * 16 = 4096 pixels and scaled by 4 = 1024 * 64 = 65536 pixels!!!
00143 
00144 CC_IMPLEMENT_DYNAMIC(CBeveler, CCObject)
00145 
00146 /********************************************************************************************
00147 
00148 >   CBeveler::CBeveler
00149 
00150     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00151     Created:    15/9/98
00152     Purpose:    Constructor for the beveling tool
00153                 Sets up the class read to do beveling
00154     SeeAlso:    -
00155 
00156 ********************************************************************************************/
00157 
00158 CBeveler::CBeveler()
00159 {
00160     // draw out the path to bevel from the selection
00161     m_pBevelPath = NULL;
00162     m_Width  =
00163     m_Height = 0;
00164     m_bOuter = FALSE;
00165     m_JointType = RoundJoin;
00166     m_pFaceList = NULL;
00167     m_NumFaces = 0;
00168     m_pBevelPoints = NULL ;
00169     m_pBevelTypes = NULL ;
00170     m_nBevelLength = 0 ;
00171     m_Tilt = 32.0;
00172     m_pStrip32 = NULL;
00173     m_pMaskBitmap = NULL;
00174     m_pNewMask = NULL;
00175     m_Indent = 750;
00176     m_Contrast = 50;
00177     m_BevelType = 1;
00178     m_LightAngle = 45;
00179     m_Transparency = 0;
00180     m_dBmpToWinX = 300;
00181     m_dBmpToWinY = 300;
00182 }
00183 
00184 
00185 CBeveler::CBeveler(Path * pPath)
00186 {
00187     // draw out the path to bevel from the selection
00188     m_pBevelPath = pPath;
00189     m_Width  =
00190     m_Height = 0;
00191     m_bOuter = FALSE;
00192     m_JointType = RoundJoin;
00193     m_pFaceList = NULL;
00194     m_NumFaces = 0;
00195     m_pBevelPoints = NULL ;
00196     m_pBevelTypes = NULL ;
00197     m_nBevelLength = 0 ;
00198     m_Tilt = 45.0;
00199     m_pStrip32 = NULL;
00200     m_pMaskBitmap = NULL;
00201     m_pNewMask = NULL;
00202     m_Indent = 750;
00203     m_Contrast = 50;
00204     m_BevelType = 1;
00205     m_LightAngle = 45;
00206     m_Tilt = 45;
00207     m_Transparency = 0;
00208     m_dBmpToWinX = 300;
00209     m_dBmpToWinY = 300;
00210 }
00211 
00212 /********************************************************************************************
00213 
00214 >   CBeveler::~CBeveler
00215 
00216     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00217     Created:    15/9/98
00218     Purpose:    Destructor
00219     SeeAlso:    -
00220 
00221 ********************************************************************************************/
00222 CBeveler::~CBeveler()
00223 {
00224     if (m_pFaceList)
00225     {
00226         delete [] m_pFaceList;
00227         m_pFaceList = NULL;
00228     }
00229 
00230     if(m_pStrip32)
00231     {
00232         delete m_pStrip32;
00233         m_pStrip32 = NULL;
00234     }
00235 
00236     if(m_pMaskBitmap)
00237     {
00238         delete m_pMaskBitmap;
00239         m_pMaskBitmap = NULL;
00240     }
00241 
00242     if(m_pNewMask)
00243     {
00244         delete m_pNewMask;
00245         m_pNewMask = NULL;
00246     }
00247 
00248     CCFree(m_pBevelPoints);
00249     CCFree(m_pBevelTypes);
00250 }
00251 
00252 /********************************************************************************************
00253 
00254 >   BOOL SetUpBeveler(MILLIPOINT Indent, JointType jtype, NormCoord * lightVec, BOOL bOuter,
00255                       INT32 Contrast, RenderRegion * pRegion, MILLIPOINT Flatness)
00256 
00257     Author:     Mark_Howitt (Xara Group Ltd) <camelotdev@xara.com>
00258     Created:    14/07/00 - Re-write of david code
00259     Purpose:    Sets up the beveler with the new bevel details
00260     Returns:    TRUE for success, FALSE if something went wrong!
00261 
00262 ********************************************************************************************/
00263 BOOL CBeveler::SetUpBeveler(MILLIPOINT Indent, JointType jtype,
00264                             NormCoord * lightVec, BOOL bOuter,
00265                             INT32 Contrast, RenderRegion * pRegion,
00266                             MILLIPOINT Flatness)
00267 {   
00268     // Check to see if the indent is zero. This is not bad, but just means there`s no bitmap needed!
00269     if (Indent == 0)
00270         return TRUE;
00271 
00272     m_Contrast = Contrast;
00273     m_JointType = jtype;
00274     m_Indent = Indent;
00275     m_bOuter = bOuter;
00276 
00277     // draw the bevel
00278     BEVEL_FACE* pFaces = NULL;
00279     GenBevelFaces gbf;
00280 
00281     m_pBevelPath->GetTrueBoundingRect(&m_BevelBounds);
00282 
00283     // Calculate the face list
00284     UINT32 nFaces = gbf.BevelPath(
00285         (POINT*)m_pBevelPath->GetCoordArray(),
00286         m_pBevelPath->GetVerbArray(),
00287         m_pBevelPath->GetNumCoords(),
00288         &pFaces,
00289         Indent<<1,
00290         10<<16,
00291         Flatness>>3,
00292         (JoinStyles)jtype,
00293         bOuter==TRUE
00294     ) ;
00295 
00296     // Check to see if we had an error!
00297     if ( nFaces<0 || pFaces == NULL)
00298         return FALSE;
00299 
00300     // Copy the return pointer into the member variable
00301     m_pFaceList = pFaces;
00302     m_NumFaces = nFaces;
00303 
00304     // Work out the size of the bevel
00305     CalcSelectionBounds();
00306 
00307     return TRUE;
00308 }
00309 
00310 BOOL CBeveler::SetBevelerSize(INT32 Width, INT32 Height)
00311 {
00312     m_Width  = Width *BEVELBITMAPSCALE;
00313     m_Height = Height*BEVELBITMAPSCALE;
00314 
00315     SetUpMapping() ;
00316 
00317     BEVEL_FACE* pFace = m_pFaceList ;
00318     for ( UINT32 i=0 ; i<m_NumFaces ; i++ )
00319     {
00320         UINT32 n = pFace->bTriangle ? 3 : 4 ;
00321         for ( UINT32 j=0 ; j<n ; j++ )
00322             ToWinCoord((DocCoord*)&(pFace->aFace[j]),(WinCoord*)&(pFace->aFace[j])) ;
00323         pFace++ ;
00324     }
00325 
00326     // Now work out the inner path
00327     CalcInnerPath() ;
00328 
00329     m_Width  = Width;
00330     m_Height = Height;
00331 
00332     return TRUE;
00333 }
00334 
00335 /********************************************************************************************
00336 
00337 >   BOOL CBeveler::RenderInStripsToBitmap(KernelBitmap * pBitmap)
00338 
00339     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00340     Created:    17/10/99
00341 
00342     Inputs:     
00343     Returns:    
00344                 
00345     Purpose:    Renders the bitmap in strips
00346     Errors:     FALSE for failure
00347     SeeAlso:    -
00348 
00349 ********************************************************************************************/
00350 BOOL CBeveler::RenderInStripsToBitmap(KernelBitmap * pBitmap, DocCoord* pSubPixOffSet)
00351 {
00352     DocCoord SubPixOffset(0,0);
00353 
00354     if(pSubPixOffSet != NULL)
00355         SubPixOffset = *pSubPixOffSet;
00356     else
00357         ERROR3("Got a NULL DocCoord pointer! Using 0,0 coords!");
00358 
00359     if(m_pStrip32)
00360     {
00361         delete m_pStrip32;
00362         m_pStrip32 = NULL;
00363     }
00364 
00365     if(m_pMaskBitmap)
00366     {
00367         delete m_pMaskBitmap;
00368         m_pMaskBitmap = NULL;
00369     }
00370 
00371     if(m_pNewMask)
00372     {
00373         delete m_pNewMask;
00374         m_pNewMask = NULL;
00375     }
00376 
00377     INT32 width  = pBitmap->GetWidth();
00378     INT32 height = pBitmap->GetHeight();
00379 
00380     TRACEUSER( "GerryX", _T("RenderInStripsToBitmap: Beveler Width = %d, Height = %d\n"),width * 4,height * 4);
00381 
00382     // Now lets do some optimization!
00383     KernelBitmap* pRemainderStripBitmap = NULL;
00384     KernelBitmap* pFullStripBitmap = NULL;
00385     INT32 LargestBevelWidth = 0;
00386     INT32 LargestBevelHeight = BEVELMAXBITMAPHEIGHT;
00387     INT32 LeftOverWidth = width % BEVELMAXBITMAPWIDTH;
00388     
00389     // At this point we have a destination bitmap which is larger than the max size bmp for GDraw2!
00390     // What we need to do is render in strips. For this we require two bitmaps to be setup.
00391     // Bitmap 1 is of MaxBevelWidthin width and Bitmap2 is the modulus left over in width.
00392     if(width > BEVELMAXBITMAPWIDTH)
00393     {
00394         LargestBevelWidth = BEVELMAXBITMAPWIDTH;
00395 //      INT32 DivideSize = 2;
00396 
00397         while(LeftOverWidth < (0.5 * LargestBevelWidth))
00398         {
00399             // Graeme (20/9/00) - Replaced the original calculation with one using integers, so
00400             // as to avoid the double -> INT32 warning message. Speedwise, there may be a bit of
00401             // a hit, as this version will take ~30 cycles, but there might be a win due to the
00402             // loss of an implicit conversion from a floating point number to an integer.
00403             //
00404             // The original calculation was LargestBevelWidth * 0.9
00405             LargestBevelWidth = ( ( LargestBevelWidth * 9 ) + 5 ) / 10;
00406             LeftOverWidth = width % LargestBevelWidth;
00407         }
00408 
00409         if(LeftOverWidth > 0)
00410             pRemainderStripBitmap = new KernelBitmap(LeftOverWidth, LargestBevelHeight, 8, 0, TRUE);
00411     }
00412     else
00413     {
00414         LeftOverWidth = 0;
00415         LargestBevelWidth = width;
00416     }
00417 
00418     pFullStripBitmap = new KernelBitmap(LargestBevelWidth, LargestBevelHeight, 8, 0, TRUE);
00419 
00420     ERROR2IF(pFullStripBitmap == NULL,FALSE,"Failed to create a strip bitmap pointer!");
00421 
00422     // we have to render to areas of the whole bitmap to then merge in
00423     for ( INT32 y = 0 ; y < height; y += LargestBevelHeight )
00424     {
00425         if(m_pStrip32 == NULL)
00426             m_pStrip32 = new KernelBitmap(LargestBevelWidth * BEVELBITMAPSCALE, LargestBevelHeight * BEVELBITMAPSCALE, 32, 96, TRUE);
00427         if(m_pMaskBitmap == NULL)
00428             m_pMaskBitmap = new KernelBitmap(LargestBevelWidth, LargestBevelHeight, 8, 96, TRUE);
00429         if(m_pNewMask == NULL)
00430             m_pNewMask = new KernelBitmap(LargestBevelWidth, LargestBevelHeight, 8, 96, TRUE);
00431 
00432         ERROR2IF(m_pStrip32 == NULL,FALSE,"Failed to create a m_pStrip32 pointer!");
00433         ERROR2IF(m_pMaskBitmap == NULL,FALSE,"Failed to create a m_pMaskBitmap pointer!");
00434         ERROR2IF(m_pNewMask == NULL,FALSE,"Failed to create a m_pNewMask pointer!");
00435 
00436         INT32 x;
00437         for( x = 0; x < width; x += LargestBevelWidth )
00438         {
00439             if (!RenderWithResampling(pFullStripBitmap, x, y, &SubPixOffset))
00440             {
00441                 delete pFullStripBitmap;
00442                 delete pRemainderStripBitmap;
00443                 return FALSE;           
00444             }
00445             
00446             // copy the source bitmap into the destination bitmap at the correct place
00447             CopyBitmapIntoBitmap(pFullStripBitmap, pBitmap, x, y);
00448         }
00449 
00450         x -= LargestBevelWidth;
00451 
00452         if((width - x) == LeftOverWidth && pRemainderStripBitmap)
00453         {
00454             delete m_pStrip32;
00455             delete m_pMaskBitmap;
00456             delete m_pNewMask;
00457 
00458             m_pStrip32 = new KernelBitmap(LeftOverWidth * BEVELBITMAPSCALE, LargestBevelHeight * BEVELBITMAPSCALE, 32, 96, TRUE);
00459             ERROR2IF(m_pStrip32 == NULL,FALSE,"Failed to create a m_pStrip32 pointer!");
00460             m_pMaskBitmap = new KernelBitmap(LeftOverWidth, LargestBevelHeight, 8, 96, TRUE);
00461             ERROR2IF(m_pMaskBitmap == NULL,FALSE,"Failed to create a m_pMaskBitmap pointer!");
00462             m_pNewMask = new KernelBitmap(LeftOverWidth, LargestBevelHeight, 8, 96, TRUE);
00463             ERROR2IF(m_pNewMask == NULL,FALSE,"Failed to create a m_pNewMask pointer!");
00464 
00465             if (!RenderWithResampling(pRemainderStripBitmap, x, y, &SubPixOffset))
00466             {
00467                 delete pFullStripBitmap;
00468                 delete pRemainderStripBitmap;
00469                 return FALSE;           
00470             }
00471             
00472             // copy the source bitmap into the destination bitmap at the correct place
00473             CopyBitmapIntoBitmap(pRemainderStripBitmap, pBitmap, x, y);
00474 
00475             delete m_pStrip32;
00476             m_pStrip32 = NULL;
00477             delete m_pMaskBitmap;
00478             m_pMaskBitmap = NULL;
00479             delete m_pNewMask;
00480             m_pNewMask = NULL;
00481         }
00482     }
00483 
00484     delete m_pStrip32;
00485     m_pStrip32 = NULL;
00486     delete m_pMaskBitmap;
00487     m_pMaskBitmap = NULL;
00488     delete m_pNewMask;
00489     m_pNewMask = NULL;
00490 
00491     // Now delete any memory we used
00492     delete pFullStripBitmap;
00493 
00494     if(pRemainderStripBitmap)
00495         delete pRemainderStripBitmap;
00496 
00497     return TRUE;
00498 }
00499 
00500 /********************************************************************************************
00501 
00502 >   void CBeveler::ToWinCoord(const DocCoord * dc, WinCoord * wc)
00503 
00504     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00505     Created:    15/9/98
00506     Purpose:    Converts a win coord to a doc coord depending on current spread and view
00507     SeeAlso:    -
00508 
00509 ********************************************************************************************/
00510 void CBeveler::ToWinCoord(const DocCoord * dc, WinCoord * wc)
00511 {
00512     if(m_bOuter)
00513     {
00514         wc->x = (INT32)(m_dBmpToWinX*(dc->x-m_SelectionBounds.lo.x)) ;
00515         wc->y = (INT32)(m_dBmpToWinY*(dc->y-m_SelectionBounds.lo.y)) ;
00516     }
00517     else
00518     {
00519         wc->x = (INT32)(m_dBmpToWinX*(dc->x-m_BevelBounds.lo.x)) ;
00520         wc->y = (INT32)(m_dBmpToWinY*(dc->y-m_BevelBounds.lo.y)) ;
00521     }
00522     
00523     return ;
00524 }
00525 
00526 /********************************************************************************************
00527 
00528 >   void CBeveler::SetUpMapping()
00529 
00530     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00531     Created:    15/9/98
00532     Purpose:    Sets up the scale factors used to change doc coordinates into bitmap coordinates
00533                 and vice-versa
00534     SeeAlso:    -
00535 
00536 ********************************************************************************************/
00537 void CBeveler::SetUpMapping()
00538 {
00539     if(m_bOuter)
00540     {
00541         if(m_SelectionBounds.IsEmpty())
00542         {
00543             m_dBmpToWinX = 1.0;
00544             m_dBmpToWinY = 1.0;
00545         }
00546         else
00547         {
00548             m_dBmpToWinX = (double)(m_Width <<16)/m_SelectionBounds.Width () ;
00549             m_dBmpToWinY = (double)(m_Height<<16)/m_SelectionBounds.Height() ;
00550         }
00551     }
00552     else
00553     {
00554         if(m_BevelBounds.IsEmpty())
00555         {
00556             m_dBmpToWinX = 1.0;
00557             m_dBmpToWinY = 1.0;
00558         }
00559         else
00560         {
00561             m_dBmpToWinX = (double)(m_Width <<16)/m_BevelBounds.Width () ;
00562             m_dBmpToWinY = (double)(m_Height<<16)/m_BevelBounds.Height() ;
00563         }
00564     }
00565 }
00566 
00567 void CBeveler::CalcSelectionBounds()
00568 {
00569     m_SelectionBounds.lo.x =
00570     m_SelectionBounds.lo.y = INT_MAX ;
00571     m_SelectionBounds.hi.x =
00572     m_SelectionBounds.hi.y = INT_MIN ;
00573 
00574     UINT32 i ;
00575     BEVEL_FACE* pFace = (BEVEL_FACE*)m_pFaceList ;
00576     if ( m_bOuter )
00577         for ( i=0 ; i<m_NumFaces ; i++ )
00578         {
00579             m_SelectionBounds.lo.x = min(m_SelectionBounds.lo.x,pFace->aFace[2].X) ;
00580             m_SelectionBounds.lo.y = min(m_SelectionBounds.lo.y,pFace->aFace[2].Y) ;
00581             m_SelectionBounds.hi.x = max(m_SelectionBounds.hi.x,pFace->aFace[2].X) ;
00582             m_SelectionBounds.hi.y = max(m_SelectionBounds.hi.y,pFace->aFace[2].Y) ;
00583             if ( !pFace->bTriangle )
00584             {
00585                 m_SelectionBounds.lo.x = min(m_SelectionBounds.lo.x,pFace->aFace[3].X) ;
00586                 m_SelectionBounds.lo.y = min(m_SelectionBounds.lo.y,pFace->aFace[3].Y) ;
00587                 m_SelectionBounds.hi.x = max(m_SelectionBounds.hi.x,pFace->aFace[3].X) ;
00588                 m_SelectionBounds.hi.y = max(m_SelectionBounds.hi.y,pFace->aFace[3].Y) ;
00589             }
00590             pFace++ ;
00591         }
00592     else
00593         for ( i=0 ; i<m_NumFaces ; i++ )
00594         {
00595             m_SelectionBounds.lo.x = min(m_SelectionBounds.lo.x,pFace->aFace[0].X) ;
00596             m_SelectionBounds.lo.y = min(m_SelectionBounds.lo.y,pFace->aFace[0].Y) ;
00597             m_SelectionBounds.hi.x = max(m_SelectionBounds.hi.x,pFace->aFace[0].X) ;
00598             m_SelectionBounds.hi.y = max(m_SelectionBounds.hi.y,pFace->aFace[0].Y) ;
00599             m_SelectionBounds.lo.x = min(m_SelectionBounds.lo.x,pFace->aFace[1].X) ;
00600             m_SelectionBounds.lo.y = min(m_SelectionBounds.lo.y,pFace->aFace[1].Y) ;
00601             m_SelectionBounds.hi.x = max(m_SelectionBounds.hi.x,pFace->aFace[1].X) ;
00602             m_SelectionBounds.hi.y = max(m_SelectionBounds.hi.y,pFace->aFace[1].Y) ;
00603             pFace++ ;
00604         }
00605 }
00606 
00607 void CBeveler::CalcInnerPath()
00608 {
00609     CCFree(m_pBevelPoints);
00610     m_pBevelPoints = NULL;
00611     CCFree(m_pBevelTypes);
00612     m_pBevelTypes = NULL;
00613 
00614     if (m_NumFaces == 0)
00615     {
00616         ERROR3("CBeveler::CalcInnerPath has empty face list");
00617         return;
00618     }
00619     
00620     m_pBevelPoints = (POINT*)CCMalloc(sizeof(POINT) * m_NumFaces);
00621     m_pBevelTypes  = (BYTE*)CCMalloc(sizeof(BYTE) * m_NumFaces);
00622 
00623     GPOINT* pPoints = (GPOINT*)m_pBevelPoints ;
00624     BYTE*   pTypes  =          m_pBevelTypes  ;
00625 
00626     GPOINT LastPoint(INT_MAX,INT_MAX) ;
00627     BEVEL_FACE* pFace = (BEVEL_FACE*)m_pFaceList ;
00628     for ( UINT32 i=0 ; i<m_NumFaces ; i++ )
00629     {
00630         if ( !pFace->bTriangle )
00631             if ( LastPoint!=pFace->aFace[0] )
00632             {
00633                 *pTypes++ = PT_MOVETO ;
00634                 *pPoints++ = LastPoint = pFace->aFace[1] ;
00635             }
00636             else if ( LastPoint!=pFace->aFace[1] )
00637             {
00638                 *pTypes++ = PT_LINETO ;
00639                 *pPoints++ = LastPoint = pFace->aFace[1] ;
00640             }
00641         pFace++ ;
00642     }
00643     m_nBevelLength = pTypes-m_pBevelTypes ;
00644 }
00645 
00646 /********************************************************************************************
00647 
00648 >   BOOL CBeveler::RenderToBitmap(KernelBitmap * pBitmap, BOOL bResample)
00649 
00650     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00651     Created:    15/10/98
00652     Purpose:    Renders the bevel bitmap (after the initial render by CreateBevelBitmap)
00653                 to a given bitmap (thus changes in light angle, type etc don't cause the
00654                 beveler to regenerate the normal list etc). 
00655     Inputs:     The bitmap to render to - MUST be of the same size as m_Width and m_Height and
00656                 8-bit
00657                 Also Whether to resample the bitmap
00658     Returns:    TRUE for success
00659     SeeAlso:    -
00660 
00661 ********************************************************************************************/
00662 BOOL CBeveler::RenderToBitmap(KernelBitmap * pRetnBitmap, BOOL bResample, DocCoord* pSubPixOffSet)
00663 {
00664     TRACEUSER( "GerryX", _T("(Beveller) Entering Render To Bitmap ------- \n"));
00665     DocCoord SubPixOffset(0,0);
00666 
00667     if(m_Width == 0 || m_Height == 0)
00668         return FALSE;
00669 
00670 #ifdef DEBUG
00671     DWORD Time = GetTickCount();
00672 #endif
00673     if (m_NumFaces == 0)
00674     {
00675         ERROR3("Face list is empty");
00676         return FALSE;
00677     }
00678 
00679     if (pRetnBitmap->GetBPP() != 8)
00680     {
00681         ERROR3("Bitmap isn't 8 bit !");
00682         return FALSE;
00683     }
00684 
00685     if ( pRetnBitmap->GetWidth ()!=(UINT32)m_Width ||
00686          pRetnBitmap->GetHeight()!=(UINT32)m_Height )
00687     {
00688         // we need to change the render list
00689         double XScale = (double)pRetnBitmap->GetWidth ()/m_Width  ;
00690         double YScale = (double)pRetnBitmap->GetHeight()/m_Height ;
00691         m_Width  = pRetnBitmap->GetWidth ();
00692         m_Height = pRetnBitmap->GetHeight();
00693 
00694         BEVEL_FACE* pFace = (BEVEL_FACE*)m_pFaceList ;
00695         for ( UINT32 i=0 ; i<m_NumFaces ; i++ )
00696         {
00697             UINT32 n = pFace->bTriangle ? 3 : 4 ;
00698             for ( UINT32 j=0 ; j<n ; j++ )
00699             {
00700                 pFace->aFace[j].X = (INT32)(pFace->aFace[j].X*XScale);
00701                 pFace->aFace[j].Y = (INT32)(pFace->aFace[j].Y*YScale);
00702             }
00703             pFace++ ;
00704         }
00705         CalcInnerPath() ;
00706     }
00707 
00708     // set up GDraw2
00709     // if we're not resampling, then deal with the 8 bit DIB directly
00710     if ( !bResample )
00711     {
00712         KernelBitmap* pBitmap = new KernelBitmap( m_Width, m_Height, 32, 96, TRUE );
00713         
00714         ERRORIF(pBitmap == NULL, _R(IDE_NOMORE_MEMORY), FALSE);
00715         
00716         UINT32 nLength = m_Width*m_Height;
00717         DWORD* pBits = (DWORD*)pBitmap->GetBitmapBits() ;
00718         UINT32 i ;
00719         for ( i=0 ; i<nLength ; i++ )
00720 #if defined(WORDS_BIGENDIAN)
00721             pBits[i] = 0xffff007f ;
00722 #else
00723             pBits[i] = 0x7f00ffff ;
00724 #endif  
00725     
00726         BITMAPINFOHEADER Header;
00727         Header.biWidth       = m_Width ;
00728         Header.biHeight      = m_Height ;
00729         Header.biPlanes      = 1 ;
00730         Header.biBitCount    = 32 ;
00731         Header.biCompression = BI_RGB ;
00732         
00733         INT32 Error = SetDIBitmap( &Header, (BYTE*)pBits ) ;
00734         if (Error != GERROR_NO_ERROR)
00735         {
00736             delete pBitmap;
00737             ERROR(_R(IDE_NOMORE_MEMORY), FALSE);
00738         }
00739         
00740         BEVEL_FACE* pFace = (BEVEL_FACE*)m_pFaceList ;
00741         for ( i=0 ; i<m_NumFaces ; i++ )
00742         {
00743             POINT Points[4] ;
00744             Points[0].x = pFace->aFace[0].X>>BEVELBITMAPSHIFT ;
00745             Points[0].y = pFace->aFace[0].Y>>BEVELBITMAPSHIFT ;
00746             Points[1].x = pFace->aFace[1].X>>BEVELBITMAPSHIFT ;
00747             Points[1].y = pFace->aFace[1].Y>>BEVELBITMAPSHIFT ;
00748             Points[2].x = pFace->aFace[2].X>>BEVELBITMAPSHIFT ;
00749             Points[2].y = pFace->aFace[2].Y>>BEVELBITMAPSHIFT ;
00750             if (pFace->bTriangle)
00751             {
00752                 if ( Points[1].x!=Points[2].x ||
00753                      Points[1].y!=Points[2].y )
00754                 {
00755                     CamProfile cp(CAMPROFILE_GDRAW);
00756                     GDraw2_FillTriangle(Points,pFace->Normal.X,pFace->Normal.Y);
00757                 }
00758             }
00759             else
00760             {
00761                 Points[3].x = pFace->aFace[3].X>>BEVELBITMAPSHIFT ;
00762                 Points[3].y = pFace->aFace[3].Y>>BEVELBITMAPSHIFT ;
00763                 CamProfile cp(CAMPROFILE_GDRAW);
00764                 GDraw2_FillTrapezium(Points,pFace->Normal.X,pFace->Normal.Y);
00765             }
00766             pFace++ ;
00767         }
00768 
00769         // Create a new GDraw context to use as this is much quicker than
00770         // saving and restoring the static context
00771         GDrawAsm* pGD = new GDrawAsm;
00772         if (pGD)
00773         {
00774             if (pGD->Init() && pGD->SetupBitmap(Header.biWidth, Header.biHeight, 32, pBitmap->GetBitmapBits(), 0))
00775             {
00776                 GMATRIX GMatrix ;
00777                 GMatrix.AX = 1<<(FX-BEVELBITMAPSHIFT) ;
00778                 GMatrix.AY = 0 ;
00779                 GMatrix.BX = 0 ;
00780                 GMatrix.BY = 1<<(FX-BEVELBITMAPSHIFT) ;
00781                 GMatrix.CX = SubPixOffset.x ;   // Surely this is wrong!
00782                 GMatrix.CY = SubPixOffset.y ;   // Convert to WinCoord and <<FX-BEVELBITMAPSHIFT.
00783                 pGD->SetMatrix(&GMatrix) ;
00784                 pGD->SetAntialiasFlag(FALSE) ;
00785 #if defined(WORDS_BIGENDIAN)
00786                 pGD->SetWordColour(0xffff007f) ;
00787 #else
00788                 pGD->SetWordColour(0x7f00ffff) ;
00789 #endif
00790 //              pGD->FillPath(m_pBevelPoints,m_pBevelTypes,m_nBevelLength,ALTERNATE|!m_bOuter<<1);
00791                 pGD->FillPath(m_pBevelPoints,m_pBevelTypes,m_nBevelLength,!m_bOuter<<1);
00792             }
00793             delete pGD;
00794         }
00795 
00796         BYTE* pSrcPtr  = pBitmap->GetBitmapBits()+3 ;
00797         BYTE* pDestPtr = pRetnBitmap->GetBitmapBits() ;
00798         UINT32 nSize = DIBUtil::ScanlineSize(m_Width,8)-m_Width ;
00799         for ( UINT32 j=0 ; j<(UINT32)m_Height ; j++ )
00800         {
00801             for ( i=0 ; i<(UINT32)m_Width ; i++ )
00802             {       
00803                 *pDestPtr++ = *pSrcPtr;
00804                 pSrcPtr += 4;
00805             }
00806             pDestPtr += nSize ;
00807         }
00808         delete pBitmap;
00809     }
00810     else
00811     {
00812         // render with sampling
00813         if ( !RenderInStripsToBitmap(pRetnBitmap, &SubPixOffset) )
00814             return FALSE;       
00815     }
00816 
00817 #ifdef DEBUG
00818     TRACEUSER( "GerryX", _T("Last Bevel Bitmap render = %dms\n"),GetTickCount() - Time);
00819 #endif
00820 
00821     return TRUE;
00822 }
00823 
00824 
00825 /********************************************************************************************
00826 
00827 >   INT32 CBeveler::SetDIBitmap( BITMAPINFOHEADER* pHeader, BYTE* pBits )
00828 
00829     Author:     Gavin_Theobald (Xara Group Ltd) <camelotdev@xara.com>
00830     Created:    5/7/00
00831     Purpose:    Passes parameters to GDraw2_SetDIBitmap adjusted for inner bevelling.
00832     Inputs:     pHeader - pointer to bitmap info header
00833                 pBits   - pointer to bitmap bytes
00834     Returns:    
00835     SeeAlso:    -
00836 
00837 ********************************************************************************************/
00838 
00839 INT32 CBeveler::SetDIBitmap( BITMAPINFOHEADER* pHeader, BYTE* pBits )
00840 {
00841     if ( m_bOuter )
00842     {
00843         CamProfile cp(CAMPROFILE_GDRAW);
00844         return GDraw2_SetDIBitmap(
00845             pHeader,
00846             pBits,
00847             (eBevelStyle)m_BevelType,
00848             (float)m_LightAngle,
00849             (float)(90-m_Tilt)
00850         ) ;
00851     }
00852     else
00853     {
00854         static const bool aFlipLightAngle[] = {
00855             false,  // BEVEL_FLAT
00856             true,   // BEVEL_ROUND
00857             true,   // BEVEL_HALFROUND
00858             true,   // BEVEL_FRAME
00859             false,  // BEVEL_MESA_1
00860             false,  // BEVEL_MESA_2
00861             false,  // BEVEL_SMOOTH_1
00862             false,  // BEVEL_SMOOTH_2
00863             true,   // BEVEL_POINT_1
00864             true,   // BEVEL_POINT_2a
00865             true,   // BEVEL_POINT_2b
00866             true,   // BEVEL_RUFFLE_1
00867             true    // BEVEL_RUFFLE_2
00868         } ;
00869         static const eBevelStyle aFlipBevels[] = {
00870             BEVEL_FLAT,     // BEVEL_FLAT
00871             BEVEL_ROUND,    // BEVEL_ROUND
00872             BEVEL_HALFROUND,// BEVEL_HALFROUND
00873             BEVEL_FRAME,    // BEVEL_FRAME
00874             BEVEL_SMOOTH_1, // BEVEL_MESA_1
00875             BEVEL_SMOOTH_2, // BEVEL_MESA_2
00876             BEVEL_MESA_1,   // BEVEL_SMOOTH_1
00877             BEVEL_MESA_2,   // BEVEL_SMOOTH_2
00878             BEVEL_POINT_1,  // BEVEL_POINT_1
00879             BEVEL_POINT_2b, // BEVEL_POINT_2a
00880             BEVEL_POINT_2a, // BEVEL_POINT_2b
00881             BEVEL_RUFFLE_2a,// BEVEL_RUFFLE_2a
00882             BEVEL_RUFFLE_2b,// BEVEL_RUFFLE_2b
00883             BEVEL_RUFFLE_3a,// BEVEL_RUFFLE_3a
00884             BEVEL_RUFFLE_3b // BEVEL_RUFFLE_3b
00885         } ;
00886         CamProfile cp(CAMPROFILE_GDRAW);
00887         return GDraw2_SetDIBitmap(
00888             pHeader,
00889             pBits,
00890             aFlipBevels[m_BevelType],
00891             (float)(aFlipLightAngle[m_BevelType] ? 180+m_LightAngle : m_LightAngle),
00892             (float)(90-m_Tilt)
00893         ) ;
00894     }
00895     return 0;
00896 }
00897 
00898 /********************************************************************************************
00899 
00900 >   void CBeveler::ResampleBitmap(BYTE * p32BitDIB, UINT32 Width, UINT32 Height, BYTE * pDestBits,
00901                                 BYTE * pMaskBitmap)
00902 
00903     Author:     Gavin_Theobald (Xara Group Ltd) <camelotdev@xara.com>
00904     Created:    3/11/99
00905     Purpose:    Resamples the 32 bit DIB given into the bits specified by pKB
00906                 and pMaskBitmap
00907     Inputs:     p32BitDIB       - pointer to the DIB bits to resample
00908                 Width, Height   - The width & height of the 32 bit DIB 
00909                 pDestBits       - The bitmap to sample into
00910                 pMaskBitmap     - Optional mask bitmap pointer (can be NULL)
00911 
00912                 NB The mask bitmap returns with 0x00 indicating no pixel written to,
00913                 and 0xff indicating pixel written to. This is to speed up the emboldening
00914                 process
00915 
00916                 Also, the memory allocation of pDestBits and pMaskBits must be
00917                 Width * Height / (BEVELBITMAPSCALE * BEVELBITMAPSCALE)
00918                 i.e. the width & height of the destination bitmaps are Width/BEVELBITMAPSCALE,
00919                 Height/BEVELBITMAPSCALE
00920     Returns:    
00921     SeeAlso:    -
00922 
00923 ********************************************************************************************/
00924 void CBeveler::ResampleBitmap(BYTE * p32BitDIB, UINT32 SrcWidth, UINT32 SrcHeight, BYTE *pDestBits,
00925                               BYTE * pMaskBits)
00926 {
00927     CamProfile cp(CAMPROFILE_BEVEL);
00928 
00929     UINT32 Width  = SrcWidth /BEVELBITMAPSCALE;
00930     UINT32 Height = SrcHeight/BEVELBITMAPSCALE;
00931     
00932     UINT32 Scanline8  = DIBUtil::ScanlineSize(Width,8);
00933     UINT32 Scanline32 = Width*4 * BEVELBITMAPSCALE;
00934 
00935     static CONST UINT32 ScaleTable[17] = {
00936         0,
00937         0x101010/1,
00938         0x101010/2,
00939         0x101010/3,
00940         0x101010/4,
00941         0x101010/5,
00942         0x101010/6,
00943         0x101010/7,
00944         0x101010/8,
00945         0x101010/9,
00946         0x101010/10,
00947         0x101010/11,
00948         0x101010/12,
00949         0x101010/13,
00950         0x101010/14,
00951         0x101010/15,
00952         0x101010/16
00953     };
00954 
00955     BYTE*  pSrcPtr = p32BitDIB;
00956     BYTE* pDestPtr = pDestBits;
00957     BYTE* pMaskPtr = pMaskBits;
00958 
00959     for ( UINT32 j=0 ; j<Height ; j++ )
00960     {
00961         for ( UINT32 i=0 ; i<Width ; i++ )
00962         {
00963             UINT32 uCount = 0;
00964             UINT32 uTotal = 0;
00965             BYTE* pSrc = pSrcPtr;
00966             for ( UINT32 k=0 ; k<4 ; k++ )
00967             {
00968 #if defined(WORDS_BIGENDIAN)
00969                 if ( pSrc[0*4]!=0xff ) { uCount++; uTotal += pSrc[0*4+3]; }
00970                 if ( pSrc[1*4]!=0xff ) { uCount++; uTotal += pSrc[1*4+3]; }
00971                 if ( pSrc[2*4]!=0xff ) { uCount++; uTotal += pSrc[2*4+3]; }
00972                 if ( pSrc[3*4]!=0xff ) { uCount++; uTotal += pSrc[3*4+3]; }
00973 #else
00974                 if ( pSrc[0*4+1]!=0xff ) { uCount++; uTotal += pSrc[0*4+3]; }
00975                 if ( pSrc[1*4+1]!=0xff ) { uCount++; uTotal += pSrc[1*4+3]; }
00976                 if ( pSrc[2*4+1]!=0xff ) { uCount++; uTotal += pSrc[2*4+3]; }
00977                 if ( pSrc[3*4+1]!=0xff ) { uCount++; uTotal += pSrc[3*4+3]; }
00978 #endif
00979                 pSrc += Scanline32 ;
00980             }
00981             if ( uCount==0 )
00982             {
00983                 pDestPtr[i] = 0x7f;
00984                 pMaskPtr[i] = 0x00;
00985             }
00986             else
00987             {
00988                 pDestPtr[i] = uTotal*ScaleTable[uCount]>>20;
00989                 pMaskPtr[i] = 0xff;
00990             }
00991             pSrcPtr += 16;
00992         }
00993         // move down by 1 scanline
00994         pSrcPtr  += Scanline32*(BEVELBITMAPSCALE-1);
00995         pDestPtr += Scanline8;
00996         pMaskPtr += Scanline8;
00997     }
00998 }       
00999 
01000 /********************************************************************************************
01001 
01002 >   BOOL CBeveler::EmboldenBitmap(KernelBitmap * pImgBitmap, KernelBitmap * pMaskBitmap)
01003 
01004     Author:     Gavin_Theobald (Xara Group Ltd) <camelotdev@xara.com>
01005     Created:    3/11/99
01006     Purpose:    'Bleeds' the bitmap into the mask to cover up any inconsistancies
01007                 between the screen paths and the bitmap
01008     Inputs:     The image bitmap to embolden, and the mask bitmap to use.
01009     Outputs:    New mask bitmap.
01010     Returns:    
01011     SeeAlso:    -
01012 
01013 ********************************************************************************************/
01014 
01015 BOOL CBeveler::EmboldenBitmap(KernelBitmap * pImgBitmap, KernelBitmap * pMaskBitmap, KernelBitmap * pNewMaskBitmap)
01016 {
01017     CamProfile cp(CAMPROFILE_BEVEL);
01018 
01019     static CONST UINT32 ScaleTable[8] = {
01020         0x101010/8,     // uCount==FF*8
01021         0x101010/7,     // uCount==FF*7
01022         0x101010/6,     // uCount==FF*6
01023         0x101010/5,     // uCount==FF*5
01024         0x101010/4,     // uCount==FF*4
01025         0x101010/3,     // uCount==FF*3
01026         0x101010/2,     // uCount==FF*2
01027         0x101010/1      // uCount==FF*1
01028     } ;
01029 
01030     UINT32 Width = pMaskBitmap->GetWidth ();
01031     UINT32 Depth = pMaskBitmap->GetHeight();
01032     // Best check that we`ve got valid widths and heights!
01033     if ( Width < 1 || Depth <= 2 )
01034     {
01035         ERROR3("Got a width or height of 2 or smaller in beveler EmboldenBitmap!");
01036         return TRUE;
01037     }
01038     if ( Width!=pNewMaskBitmap->GetWidth() || Depth!=pNewMaskBitmap->GetHeight() )
01039     {
01040         ERROR3("pMaskBitmap and pNewMask have different sizes in beveler EmboldenBitmap!");
01041         return FALSE;
01042     }
01043 
01044     UINT32 W = DIBUtil::ScanlineSize(Width,8);
01045     BYTE* pILine =     pImgBitmap->GetBitmapBits();
01046     BYTE* pMLine =    pMaskBitmap->GetBitmapBits();
01047     BYTE* pNLine = pNewMaskBitmap->GetBitmapBits();
01048     UINT32 uCount;
01049     UINT32 i;
01050     //
01051     // First scanline
01052     //
01053     BYTE* pIPtr = pILine;
01054     BYTE* pMPtr = pMLine;
01055     BYTE* pNPtr = pNLine;
01056     *pNPtr = *pMPtr;
01057     if ( *pMPtr==0x00 )
01058     {
01059         uCount = pMPtr[ +1]+
01060                  pMPtr[W  ]+
01061                  pMPtr[W+1];
01062         if ( uCount )
01063         {
01064             *pIPtr = ((pMPtr[ +1] & pIPtr[ +1])+
01065                       (pMPtr[W  ] & pIPtr[W  ])+
01066                       (pMPtr[W+1] & pIPtr[W+1]))*ScaleTable[uCount & 7]>>20;
01067             *pNPtr = 0xff;
01068         }
01069     }
01070     pIPtr++; pMPtr++; pNPtr++;
01071     for ( i=2 ; i<Width ; i++ )
01072     {
01073         *pNPtr = *pMPtr;
01074         if ( *pMPtr==0x00 )
01075         {
01076             uCount = pMPtr[ -1]+
01077                      pMPtr[ +1]+
01078                      pMPtr[W-1]+
01079                      pMPtr[W  ]+
01080                      pMPtr[W+1];
01081             if ( uCount )
01082             {
01083                 *pIPtr = ((pMPtr[ -1] & pIPtr[ -1])+
01084                           (pMPtr[ +1] & pIPtr[ +1])+
01085                           (pMPtr[W-1] & pIPtr[W-1])+
01086                           (pMPtr[W  ] & pIPtr[W  ])+
01087                           (pMPtr[W+1] & pIPtr[W+1]))*ScaleTable[uCount & 7]>>20;
01088                 *pNPtr = 0xff;
01089             }
01090         }
01091         pIPtr++; pMPtr++; pNPtr++;
01092     }
01093     *pNPtr = *pMPtr;
01094     if ( *pMPtr==0x00 )
01095     {
01096         uCount = pMPtr[ -1]+
01097                  pMPtr[W  ]+
01098                  pMPtr[W-1];
01099         if ( uCount )
01100         {
01101             *pIPtr = ((pMPtr[ -1] & pIPtr[ -1])+
01102                       (pMPtr[W  ] & pIPtr[W  ])+
01103                       (pMPtr[W-1] & pIPtr[W-1]))*ScaleTable[uCount & 7]>>20;
01104             *pNPtr = 0xff;
01105         }
01106     }
01107     //
01108     // Second to penultimate scanline
01109     //
01110     for ( UINT32 j=2 ; j<Depth ; j++ )
01111     {
01112         pIPtr = pILine;
01113         pMPtr = pMLine;
01114         pNPtr = pNLine;
01115         pNPtr[W] = pMPtr[W];
01116         if ( pMPtr[W]==0x00 )
01117         {
01118             uCount = pMPtr[    0]+
01119                      pMPtr[   +1]+
01120                      pMPtr[W  +1]+
01121                      pMPtr[W*2  ]+
01122                      pMPtr[W*2+1];
01123             if ( uCount )
01124             {
01125                 pIPtr[W] = ((pMPtr[    0] & pIPtr[    0])+
01126                             (pMPtr[   +1] & pIPtr[   +1])+
01127                             (pMPtr[W  +1] & pIPtr[W  +1])+
01128                             (pMPtr[W*2  ] & pIPtr[W*2  ])+
01129                             (pMPtr[W*2+1] & pIPtr[W*2+1]))*ScaleTable[uCount & 7]>>20;
01130                 pNPtr[W] = 0xff;
01131             }
01132         }
01133         pIPtr++; pMPtr++; pNPtr++;
01134         for ( i=2 ; i<Width ; i++ )
01135         {
01136             pNPtr[W] = pMPtr[W];
01137             if ( pMPtr[W]==0x00 )
01138             {
01139                 uCount = pMPtr[   -1]+
01140                          pMPtr[    0]+
01141                          pMPtr[   +1]+
01142                          pMPtr[W  -1]+
01143                          pMPtr[W  +1]+
01144                          pMPtr[W*2-1]+
01145                          pMPtr[W*2  ]+
01146                          pMPtr[W*2+1];
01147                 if ( uCount )
01148                 {
01149                     pIPtr[W] = ((pMPtr[   -1] & pIPtr[   -1])+
01150                                 (pMPtr[    0] & pIPtr[    0])+
01151                                 (pMPtr[   +1] & pIPtr[   +1])+
01152                                 (pMPtr[W  -1] & pIPtr[W  -1])+
01153                                 (pMPtr[W  +1] & pIPtr[W  +1])+
01154                                 (pMPtr[W*2-1] & pIPtr[W*2-1])+
01155                                 (pMPtr[W*2  ] & pIPtr[W*2  ])+
01156                                 (pMPtr[W*2+1] & pIPtr[W*2+1]))*ScaleTable[uCount & 7]>>20;
01157                     pNPtr[W] = 0xff;
01158                 }
01159             }
01160             pIPtr++; pMPtr++; pNPtr++;
01161         }
01162         pNPtr[W] = pMPtr[W];
01163         if ( pMPtr[W]==0x00 )
01164         {
01165             uCount = pMPtr[   -1]+
01166                      pMPtr[    0]+
01167                      pMPtr[W  -1]+
01168                      pMPtr[W*2-1]+
01169                      pMPtr[W*2  ];
01170             if ( uCount )
01171             {
01172                 pIPtr[W] = ((pMPtr[   -1] & pIPtr[   -1])+
01173                             (pMPtr[    0] & pIPtr[    0])+
01174                             (pMPtr[W  -1] & pIPtr[W  -1])+
01175                             (pMPtr[W*2-1] & pIPtr[W*2-1])+
01176                             (pMPtr[W*2  ] & pIPtr[W*2  ]))*ScaleTable[uCount & 7]>>20;
01177                 pNPtr[W] = 0xff;
01178             }
01179         }
01180         pILine += W;
01181         pMLine += W;
01182         pNLine += W;
01183     }
01184     //
01185     // Last scanline
01186     //
01187     pIPtr = pILine;
01188     pMPtr = pMLine;
01189     pNPtr = pNLine;
01190     pNPtr[W] = pMPtr[W];
01191     if ( pMPtr[W]==0x00 )
01192     {
01193         uCount = pMPtr[  0]+
01194                  pMPtr[ +1]+
01195                  pMPtr[W+1];
01196         if ( uCount )
01197         {
01198             pIPtr[W] = ((pMPtr[  0] & pIPtr[  0])+
01199                         (pMPtr[ +1] & pIPtr[ +1])+
01200                         (pMPtr[W+1] & pIPtr[W+1]))*ScaleTable[uCount & 7]>>20;
01201             pNPtr[W] = 0xff;
01202         }
01203     }
01204     pIPtr++; pMPtr++; pNPtr++;
01205     for ( i=2 ; i<Width ; i++ )
01206     {
01207         pNPtr[W] = pMPtr[W];
01208         if ( pMPtr[W]==0x00 )
01209         {
01210             uCount = pMPtr[ -1]+
01211                      pMPtr[  0]+
01212                      pMPtr[ +1]+
01213                      pMPtr[W-1]+
01214                      pMPtr[W+1];
01215             if ( uCount )
01216             {
01217                 pIPtr[W] = ((pMPtr[ -1] & pIPtr[ -1])+
01218                             (pMPtr[  0] & pIPtr[  0])+
01219                             (pMPtr[ +1] & pIPtr[ +1])+
01220                             (pMPtr[W-1] & pIPtr[W-1])+
01221                             (pMPtr[W+1] & pIPtr[W+1]))*ScaleTable[uCount & 7]>>20;
01222                 pNPtr[W] = 0xff;
01223             }
01224         }
01225         pIPtr++; pMPtr++; pNPtr++;
01226     }
01227     pNPtr[W] = pMPtr[W];
01228     if ( pMPtr[W]==0x00 )
01229     {
01230         uCount = pMPtr[ -1]+
01231                  pMPtr[  0]+
01232                  pMPtr[W-1];
01233         if ( uCount )
01234         {
01235             pIPtr[W] = ((pMPtr[ -1] & pIPtr[ -1])+
01236                         (pMPtr[  0] & pIPtr[  0])+
01237                         (pMPtr[W-1] & pIPtr[W-1]))*ScaleTable[uCount & 7]>>20;
01238             pNPtr[W] = 0xff;
01239         }
01240     }
01241 
01242     return TRUE;
01243 }
01244 
01245 /********************************************************************************************
01246 
01247 >   BOOL CBeveler::RenderWithResampling(KernelBitmap * pBitmap, INT32 OffsetX, INT32 OffsetY)
01248 
01249     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
01250     Created:    3/11/99
01251     Purpose:    Renders the points list in strips to the given 8 bit DIB
01252     Inputs:     pBitmap - 8 bit bitmap to render to
01253                 OffsetX - the x offset to add to the x coords of the areas to be rendered
01254                             (in pixels)
01255                 OffsetY - the y offset to add to the y coords of the areas to be rendered
01256                             (in pixels)
01257                 
01258     Returns:    TRUE for success, FALSE for failure
01259     Notes:      OffsetX & OffsetY denote the origin of the super-bitmap where the bitmap 
01260                 which this fn creates is to be placed
01261                 This is so that this function can create an area in a larger bitmap to
01262                 avoid the maximum width & height of bitmap that GDraw2 can cope with
01263     SeeAlso:    -
01264 
01265 ********************************************************************************************/
01266 
01267 void memset32(DWORD* pMem, DWORD Val, DWORD Len)
01268 {
01269     for (DWORD i=0; i < Len; i++)
01270         *pMem++ = Val;
01271 }
01272 
01273 
01274 BOOL CBeveler::RenderWithResampling(KernelBitmap * pBitmap, INT32 OrigOffsetX, INT32 OrigOffsetY, DocCoord* pSubPixOffSet)
01275 {
01276     TRACEUSER( "GerryX", _T("(Beveller) Entering Render With Resampling ------- \n"));
01277 
01278 #ifdef DEBUG
01279     DWORD Time = GetTickCount();
01280 #endif
01281 
01282     DocCoord SubPixOffset(0,0);
01283 
01284     if(pSubPixOffSet != NULL)
01285         SubPixOffset = *pSubPixOffSet;
01286     else
01287         ERROR3("Got a NULL DocCoord pointer! Using 0,0 coords!");
01288 
01289     // alter the offsets into coordinates that gdraw2 recognises
01290     OrigOffsetX *= BEVELBITMAPSCALE<<16;
01291     OrigOffsetY *= BEVELBITMAPSCALE<<16;
01292 
01293     // NEW BIT! This now adds the subpixel offsets of the coordinates
01294     FIXED16 XOff = SubPixOffset.x * BEVELBITMAPSCALE * 0.001;
01295     FIXED16 YOff = SubPixOffset.y * BEVELBITMAPSCALE * 0.001;
01296     OrigOffsetX -= XOff.GetShifted16();
01297     OrigOffsetY -= YOff.GetShifted16();
01298 
01299     // set up the bitmap in GDraw and GDraw2
01300     BITMAPINFOHEADER Header;
01301     Header.biWidth       = m_pStrip32->GetWidth ();
01302     Header.biHeight      = m_pStrip32->GetHeight();
01303     Header.biPlanes      = 1;
01304     Header.biBitCount    = 32;
01305     Header.biCompression = BI_RGB ;
01306 
01307     INT32 Error = SetDIBitmap( &Header,(BYTE*)m_pStrip32->GetBitmapBits() ) ;
01308     if ( Error!=GERROR_NO_ERROR )
01309         ERROR2(FALSE, "GDraw2 can't initialise");
01310 
01311     // set up the strip first
01312     UINT32 i;
01313     DWORD* pBits = (DWORD*)m_pStrip32->GetBitmapBits() ;
01314     UINT32 nLength = m_pStrip32->GetWidth()*m_pStrip32->GetHeight() ;
01315 #if defined(WORDS_BIGENDIAN)
01316     memset32(pBits, 0xffff007f, nLength);
01317 #else
01318     memset32(pBits, 0x7f00ffff, nLength);
01319 #endif
01320 
01321     // draw the points list at this scanline position
01322     // pixel size in point units of the bitmap strip
01323     BEVEL_FACE* pFace = (BEVEL_FACE*)m_pFaceList ;
01324     for ( i=0 ; i<m_NumFaces ; i++ )
01325     {
01326         POINT Points[4];
01327         Points[0].x = pFace->aFace[0].X-OrigOffsetX ;
01328         Points[0].y = pFace->aFace[0].Y-OrigOffsetY ;
01329         Points[1].x = pFace->aFace[1].X-OrigOffsetX ;
01330         Points[1].y = pFace->aFace[1].Y-OrigOffsetY ;
01331         Points[2].x = pFace->aFace[2].X-OrigOffsetX ;
01332         Points[2].y = pFace->aFace[2].Y-OrigOffsetY ;
01333         if ( pFace->bTriangle )
01334         {
01335             if ( Points[1].x!=Points[2].x ||
01336                  Points[1].y!=Points[2].y )
01337             {
01338                 CamProfile cp(CAMPROFILE_GDRAW);
01339                 GDraw2_FillTriangle(Points,pFace->Normal.X,pFace->Normal.Y);
01340             }
01341         }
01342         else
01343         {
01344             Points[3].x = pFace->aFace[3].X-OrigOffsetX ;
01345             Points[3].y = pFace->aFace[3].Y-OrigOffsetY ;
01346             CamProfile cp(CAMPROFILE_GDRAW);
01347             GDraw2_FillTrapezium(Points,pFace->Normal.X,pFace->Normal.Y);
01348         }
01349         pFace++ ;
01350     }
01351     //
01352     // Blank out invalid parts of bitmap. For inner contours we blank out
01353     // outside of the path and for outer contours we blank out inside of
01354     // the path.
01355     //
01356     // We create our own GDrawAsm context to do this as it is much quicker than
01357     // saving and restoring the static one
01358     GDrawAsm* pGD = new GDrawAsm;
01359     if (pGD)
01360     {
01361         if (pGD->Init() && pGD->SetupBitmap(Header.biWidth, Header.biHeight, 32, m_pStrip32->GetBitmapBits(), 0))
01362         {
01363             GMATRIX GMatrix ;
01364             GMatrix.AX = 1<<FX ;
01365             GMatrix.AY = 0 ;
01366             GMatrix.BX = 0 ;
01367             GMatrix.BY = 1<<FX ;
01368             GMatrix.CX = -(__int64)OrigOffsetX<<FX ;
01369             GMatrix.CY = -(__int64)OrigOffsetY<<FX ;
01370             pGD->SetMatrix(&GMatrix) ;
01371             pGD->SetAntialiasFlag(FALSE) ;
01372 #if defined(WORDS_BIGENDIAN)
01373             pGD->SetWordColour(0xffff007f) ;
01374 #else
01375             pGD->SetWordColour(0x7f00ffff) ;
01376 #endif
01377 //          pGD->FillPath(m_pBevelPoints,m_pBevelTypes,m_nBevelLength,ALTERNATE|!m_bOuter<<1);
01378             pGD->FillPath(m_pBevelPoints,m_pBevelTypes,m_nBevelLength,!m_bOuter<<1);
01379         }
01380         delete pGD;
01381     }
01382 
01383     // now we've rendered to the scanline, resample into the correct place in the
01384     // bitmap
01385     //
01386     // create the mask bitmap
01387     BYTE* pMaskBits = m_pMaskBitmap->GetBitmapBits() ;
01388     BYTE* pDestBits = pBitmap->GetBitmapBits() ;
01389     ERROR2IF(!pMaskBits,FALSE,"NULL MaskBits Pointer in Beveler!");
01390     ERROR2IF(!pDestBits,FALSE,"NULL DestBits Pointer in Beveler!");
01391     ResampleBitmap(m_pStrip32->GetBitmapBits(), m_pStrip32->GetWidth (),
01392                    m_pStrip32->GetHeight(), pDestBits, pMaskBits);
01393 
01394     if(pBitmap->GetWidth() > 4 && pBitmap->GetHeight() > 4)
01395     {
01396         // embolden the bitmap
01397         if ( !EmboldenBitmap(pBitmap,m_pMaskBitmap,m_pNewMask) ||
01398              !EmboldenBitmap(pBitmap,m_pNewMask,m_pMaskBitmap) )
01399         {
01400             return FALSE ;
01401         }
01402     }
01403 
01404 #ifdef DEBUG
01405     TRACEUSER( "GerryX", _T("Last Bevel Bitmap render resampling = %dms\n"),GetTickCount() - Time);
01406 #endif
01407 
01408     return TRUE;
01409 }
01410 
01411 /********************************************************************************************
01412 
01413 >   void CBeveler::CopyBitmapIntoBitmap(const KernelBitmap * pSrcBitmap, KernelBitmap * pDestBitmap,
01414                         INT32 DestX, INT32 DestY)
01415 
01416     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
01417     Created:    3/11/99
01418     Purpose:    Copies the original bitmap into the destination bitmap given the origin to
01419                 start the copy in the destination
01420     Inputs:     pSrcBitmap  - the bitmap to copy
01421                 pDestBitmap - the destination bitmap to copy into
01422                 DestX       - the pixel X position to start the copy
01423                 DestY       - the pixel Y position to start the copy
01424 
01425     Returns:    
01426     Notes:      Accounts for overshoots i.e. if
01427                     pSrcBitmap->GetWidth () > pDestBitmap->GetWidth ()+DestX or
01428                     pSrcBitmap->GetHeight() > pDestBitmap->GetHeight()+DestY
01429 
01430                 then this is ok.
01431 
01432                 Both bitmaps MUST be 8-bit
01433     SeeAlso:    -
01434 
01435 ********************************************************************************************/
01436 void CBeveler::CopyBitmapIntoBitmap(const KernelBitmap * pSrcBitmap, KernelBitmap * pDestBitmap,
01437                         INT32 DestX, INT32 DestY)
01438 {
01439     // start out by calculating how many pixels across & down we are to copy (takes
01440     // into account overshoots of the source on the destination)
01441     INT32 SrcWidth = (INT32)pSrcBitmap->GetWidth ();
01442     INT32 SrcDepth = (INT32)pSrcBitmap->GetHeight();
01443 //  INT32 DstWidth = SrcWidth;
01444 //  INT32 DstDepth = SrcDepth;
01445     INT32 DstWidth = (INT32)pDestBitmap->GetWidth ();
01446     INT32 DstDepth = (INT32)pDestBitmap->GetHeight();
01447     if ( DestX+SrcWidth>DstWidth ) SrcWidth = DstWidth-DestX;
01448     if ( DestY+SrcDepth>DstDepth ) SrcDepth = DstDepth-DestY;
01449     if ( SrcWidth>0 && SrcDepth>0 )
01450     {
01451         // the increase for the scanline in the source bitmap
01452         INT32  SrcScanlineInc = DIBUtil::ScanlineSize(SrcWidth,8);
01453         INT32 DestScanlineInc = DIBUtil::ScanlineSize(DstWidth,8);
01454 
01455         // ok, all variables set up so lets do the transfer !
01456         BYTE*  pSrcPtr =  pSrcBitmap->GetBitmapBits() ;
01457         BYTE* pDestPtr = pDestBitmap->GetBitmapBits()+DestX+DestY*DestScanlineInc ;
01458         while ( SrcDepth>0 )
01459         {
01460             memcpy( pDestPtr,pSrcPtr,SrcWidth ) ;
01461              pSrcPtr +=  SrcScanlineInc ;
01462             pDestPtr += DestScanlineInc ;
01463             SrcDepth-- ;
01464         }
01465     }
01466 }

Generated on Sat Nov 10 03:44:19 2007 for Camelot by  doxygen 1.4.4