maskedrr.cpp

Go to the documentation of this file.
00001 // $Id: maskedrr.cpp 1288 2006-06-09 13:16:24Z 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 // The Masked Render region
00099 
00100 /*
00101 */
00102 
00103 #include "camtypes.h"
00104 #include "maskedrr.h"
00105 //#include "doccolor.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 #include "nodebmp.h"
00109 //#include "view.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 
00111 // An implement to match the Declare in the .h file.
00112 CC_IMPLEMENT_DYNAMIC(MaskedRenderRegion, GRenderBitmap)
00113 
00114 // This will get Camelot to display the filename and linenumber of any memory allocations
00115 // that are not released at program exit
00116 #define new CAM_DEBUG_NEW
00117 
00118 
00119 // This table holds the number of bits set for each of the byte values 0 to 255. This table is
00120 // used to help speed up the counting of the number of set pixels in the mask
00121 INT32 MaskedRenderRegion::BitCountTable[256] =
00122 {
00123     0,  /* 0x0 */   1,  /* 0x1 */   1,  /* 0x2 */   2,  /* 0x3 */   1,  /* 0x4 */
00124     2,  /* 0x5 */   2,  /* 0x6 */   3,  /* 0x7 */   1,  /* 0x8 */   2,  /* 0x9 */
00125     2,  /* 0xA */   3,  /* 0xB */   2,  /* 0xC */   3,  /* 0xD */   3,  /* 0xE */
00126     4,  /* 0xF */   1,  /* 0x10 */  2,  /* 0x11 */  2,  /* 0x12 */  3,  /* 0x13 */
00127     2,  /* 0x14 */  3,  /* 0x15 */  3,  /* 0x16 */  4,  /* 0x17 */  2,  /* 0x18 */
00128     3,  /* 0x19 */  3,  /* 0x1A */  4,  /* 0x1B */  3,  /* 0x1C */  4,  /* 0x1D */
00129     4,  /* 0x1E */  5,  /* 0x1F */  1,  /* 0x20 */  2,  /* 0x21 */  2,  /* 0x22 */
00130     3,  /* 0x23 */  2,  /* 0x24 */  3,  /* 0x25 */  3,  /* 0x26 */  4,  /* 0x27 */
00131     2,  /* 0x28 */  3,  /* 0x29 */  3,  /* 0x2A */  4,  /* 0x2B */  3,  /* 0x2C */
00132     4,  /* 0x2D */  4,  /* 0x2E */  5,  /* 0x2F */  2,  /* 0x30 */  3,  /* 0x31 */
00133     3,  /* 0x32 */  4,  /* 0x33 */  3,  /* 0x34 */  4,  /* 0x35 */  4,  /* 0x36 */
00134     5,  /* 0x37 */  3,  /* 0x38 */  4,  /* 0x39 */  4,  /* 0x3A */  5,  /* 0x3B */
00135     4,  /* 0x3C */  5,  /* 0x3D */  5,  /* 0x3E */  6,  /* 0x3F */  1,  /* 0x40 */
00136     2,  /* 0x41 */  2,  /* 0x42 */  3,  /* 0x43 */  2,  /* 0x44 */  3,  /* 0x45 */
00137     3,  /* 0x46 */  4,  /* 0x47 */  2,  /* 0x48 */  3,  /* 0x49 */  3,  /* 0x4A */
00138     4,  /* 0x4B */  3,  /* 0x4C */  4,  /* 0x4D */  4,  /* 0x4E */  5,  /* 0x4F */
00139     2,  /* 0x50 */  3,  /* 0x51 */  3,  /* 0x52 */  4,  /* 0x53 */  3,  /* 0x54 */
00140     4,  /* 0x55 */  4,  /* 0x56 */  5,  /* 0x57 */  3,  /* 0x58 */  4,  /* 0x59 */
00141     4,  /* 0x5A */  5,  /* 0x5B */  4,  /* 0x5C */  5,  /* 0x5D */  5,  /* 0x5E */
00142     6,  /* 0x5F */  2,  /* 0x60 */  3,  /* 0x61 */  3,  /* 0x62 */  4,  /* 0x63 */
00143     3,  /* 0x64 */  4,  /* 0x65 */  4,  /* 0x66 */  5,  /* 0x67 */  3,  /* 0x68 */
00144     4,  /* 0x69 */  4,  /* 0x6A */  5,  /* 0x6B */  4,  /* 0x6C */  5,  /* 0x6D */
00145     5,  /* 0x6E */  6,  /* 0x6F */  3,  /* 0x70 */  4,  /* 0x71 */  4,  /* 0x72 */
00146     5,  /* 0x73 */  4,  /* 0x74 */  5,  /* 0x75 */  5,  /* 0x76 */  6,  /* 0x77 */
00147     4,  /* 0x78 */  5,  /* 0x79 */  5,  /* 0x7A */  6,  /* 0x7B */  5,  /* 0x7C */
00148     6,  /* 0x7D */  6,  /* 0x7E */  7,  /* 0x7F */  1,  /* 0x80 */  2,  /* 0x81 */
00149     2,  /* 0x82 */  3,  /* 0x83 */  2,  /* 0x84 */  3,  /* 0x85 */  3,  /* 0x86 */
00150     4,  /* 0x87 */  2,  /* 0x88 */  3,  /* 0x89 */  3,  /* 0x8A */  4,  /* 0x8B */
00151     3,  /* 0x8C */  4,  /* 0x8D */  4,  /* 0x8E */  5,  /* 0x8F */  2,  /* 0x90 */
00152     3,  /* 0x91 */  3,  /* 0x92 */  4,  /* 0x93 */  3,  /* 0x94 */  4,  /* 0x95 */
00153     4,  /* 0x96 */  5,  /* 0x97 */  3,  /* 0x98 */  4,  /* 0x99 */  4,  /* 0x9A */
00154     5,  /* 0x9B */  4,  /* 0x9C */  5,  /* 0x9D */  5,  /* 0x9E */  6,  /* 0x9F */
00155     2,  /* 0xA0 */  3,  /* 0xA1 */  3,  /* 0xA2 */  4,  /* 0xA3 */  3,  /* 0xA4 */
00156     4,  /* 0xA5 */  4,  /* 0xA6 */  5,  /* 0xA7 */  3,  /* 0xA8 */  4,  /* 0xA9 */
00157     4,  /* 0xAA */  5,  /* 0xAB */  4,  /* 0xAC */  5,  /* 0xAD */  5,  /* 0xAE */
00158     6,  /* 0xAF */  3,  /* 0xB0 */  4,  /* 0xB1 */  4,  /* 0xB2 */  5,  /* 0xB3 */
00159     4,  /* 0xB4 */  5,  /* 0xB5 */  5,  /* 0xB6 */  6,  /* 0xB7 */  4,  /* 0xB8 */
00160     5,  /* 0xB9 */  5,  /* 0xBA */  6,  /* 0xBB */  5,  /* 0xBC */  6,  /* 0xBD */
00161     6,  /* 0xBE */  7,  /* 0xBF */  2,  /* 0xC0 */  3,  /* 0xC1 */  3,  /* 0xC2 */
00162     4,  /* 0xC3 */  3,  /* 0xC4 */  4,  /* 0xC5 */  4,  /* 0xC6 */  5,  /* 0xC7 */
00163     3,  /* 0xC8 */  4,  /* 0xC9 */  4,  /* 0xCA */  5,  /* 0xCB */  4,  /* 0xCC */
00164     5,  /* 0xCD */  5,  /* 0xCE */  6,  /* 0xCF */  3,  /* 0xD0 */  4,  /* 0xD1 */
00165     4,  /* 0xD2 */  5,  /* 0xD3 */  4,  /* 0xD4 */  5,  /* 0xD5 */  5,  /* 0xD6 */
00166     6,  /* 0xD7 */  4,  /* 0xD8 */  5,  /* 0xD9 */  5,  /* 0xDA */  6,  /* 0xDB */
00167     5,  /* 0xDC */  6,  /* 0xDD */  6,  /* 0xDE */  7,  /* 0xDF */  3,  /* 0xE0 */
00168     4,  /* 0xE1 */  4,  /* 0xE2 */  5,  /* 0xE3 */  4,  /* 0xE4 */  5,  /* 0xE5 */
00169     5,  /* 0xE6 */  6,  /* 0xE7 */  4,  /* 0xE8 */  5,  /* 0xE9 */  5,  /* 0xEA */
00170     6,  /* 0xEB */  5,  /* 0xEC */  6,  /* 0xED */  6,  /* 0xEE */  7,  /* 0xEF */
00171     4,  /* 0xF0 */  5,  /* 0xF1 */  5,  /* 0xF2 */  6,  /* 0xF3 */  5,  /* 0xF4 */
00172     6,  /* 0xF5 */  6,  /* 0xF6 */  7,  /* 0xF7 */  5,  /* 0xF8 */  6,  /* 0xF9 */
00173     6,  /* 0xFA */  7,  /* 0xFB */  6,  /* 0xFC */  7,  /* 0xFD */  7,  /* 0xFE */
00174     8   /* 0xFF */
00175 };
00176 
00177 
00178 
00179 
00180 /********************************************************************************************
00181 
00182 >   MaskedRenderRegion::MaskedRenderRegion( DocRect ClipRegion, Matrix ConvertMatrix,
00183                                         FIXED16 ViewScale, UINT32 Depth, double dpi)
00184 
00185     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00186     Created:    11/4/95
00187     Inputs:     ClipRect - the Clipping rectangle
00188                 ConvertMatrix - the Matrix to render through
00189                 ViewScale - The Scale Factor
00190                 dpi - Dots per inch
00191     Purpose:    Constructor. Sends everything on to the base class.
00192                 INT32 dpi changed to FIXED16 dpi (12/12/95) to improve the range of values allowed
00193                 at the < 1000dpi settings that we will be using.
00194 
00195 ********************************************************************************************/
00196 
00197 MaskedRenderRegion::MaskedRenderRegion( DocRect ClipRegion, Matrix ConvertMatrix,
00198                                         FIXED16 ViewScale, double dpi)
00199                                         : GRenderBitmap(ClipRegion, ConvertMatrix, ViewScale, 1, dpi)
00200 {
00201     // Some attrs we use. NULL by default
00202     pFillAttr = NULL;
00203     pStrokeAttr = NULL;
00204     Black = DocColour(0,0,0);
00205     White = DocColour(255,255,255);
00206 }
00207 
00208 
00209 /********************************************************************************************
00210 
00211 >   MaskedRenderRegion::~MaskedRenderRegion()
00212 
00213     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00214     Created:    11/4/95
00215     Purpose:    Default destructor
00216 
00217 ********************************************************************************************/
00218 
00219 MaskedRenderRegion::~MaskedRenderRegion()
00220 {
00221     // Kill the fill attr
00222     if (pFillAttr!=NULL)
00223     {
00224         delete pFillAttr;
00225         pFillAttr = NULL;
00226     }
00227 
00228     // kill the stroke attr
00229     if (pStrokeAttr!=NULL)
00230     {
00231         delete pStrokeAttr;
00232         pStrokeAttr = NULL;
00233     }
00234 }
00235 
00236 
00237 /********************************************************************************************
00238 
00239 >   BOOL MaskedRenderRegion::StartRender()
00240 
00241     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00242     Created:    20/4/95
00243     Returns:    TRUE if it worked, FALSE if it failed
00244     Purpose:    Starts the render region up. This version just calls the base class and
00245                 allocates a couple of attributes used during the rendering.
00246 
00247 ********************************************************************************************/
00248 
00249 BOOL MaskedRenderRegion::StartRender()
00250 {
00251     // Call the base class
00252     if (!GRenderBitmap::StartRender())
00253         return FALSE;
00254 
00255     // If we got a bitmap, then clear it
00256     if (pBits!=NULL && pBitmapInfo!=NULL)
00257     {
00258         // Find out how many bytes there are to look at
00259         INT32 TotalBytes = pBitmapInfo->bmiHeader.biSizeImage;
00260         
00261         // clear it all out - a Set pixels is transparent, an Unset pixel is not
00262         memset(pBits, 0xFF, TotalBytes);
00263     }
00264         
00265     // Do our own thing - We need some attrs
00266     if (pFillAttr==NULL)
00267         pFillAttr = new FlatTranspFillAttribute(0);
00268 
00269     if (pStrokeAttr==NULL)
00270         pStrokeAttr = new StrokeTranspAttribute(0);
00271 
00272     // See if we got the ram we wanted
00273     if ((pFillAttr==NULL) || (pStrokeAttr==NULL))
00274         return FALSE;
00275 
00276     // if we get here, everything has worked
00277     return TRUE;
00278 }
00279 
00280 
00281 
00282 /********************************************************************************************
00283 
00284 >   void MaskedRenderRegion::SetHostCaps(RenderCaps* pCaps)
00285 
00286     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00287     Created:    24/4/95
00288     Inputs:     pCaps - pointer to the render caps for the host render region
00289     Purpose:    Tells the mask region what attributes are considered complex.
00290 
00291 ********************************************************************************************/
00292 
00293 void MaskedRenderRegion::SetHostCaps(RRCaps* pCaps)
00294 {
00295     // Make a copy of the host regions caps
00296     HostCaps = *pCaps;
00297 }
00298 
00299 
00300 
00301 /********************************************************************************************
00302 
00303 >   virtual void MaskedRenderRegion::DrawPathToOutputDevice(Path* pPath)
00304 
00305     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00306     Created:    24/4/95
00307     Inputs:     pPath - The path that needs rendering
00308     Purpose:    Renders the path into the mask. It makes sure that all the attributes are
00309                 set up correctly first though
00310 
00311 ********************************************************************************************/
00312 
00313 void MaskedRenderRegion::DrawPathToOutputDevice(Path* pPath, PathShape)
00314 {
00315     // Save the context
00316     SaveContext();
00317 
00318     BOOL RenderFill = FALSE;
00319 
00320     // Get the current fill attr
00321     FillGeometryAttribute* pFillAttr = (FillGeometryAttribute*) CurrentAttrs[ATTR_FILLGEOMETRY].pAttr;
00322 
00323     if (pFillAttr->GetBitmap() != NULL && pFillAttr->GetBitmap()->GetBPP() <= 8)
00324     {
00325         INT32 TranspIndex;
00326 
00327         // If it's a masked bitmap fill, then we'll need to actually render it
00328         // (but we'll force all the non-masked pixels to be rendered black)
00329         if (pFillAttr->GetBitmap()->GetTransparencyIndex(&TranspIndex))
00330             RenderFill = TRUE;
00331     }
00332 
00333     if (RenderFill)
00334     {
00335         BOOL OldVMState = RenderFlags.VeryMono;
00336         RenderFlags.VeryMono = TRUE;    // Forces non-masked pixels to be plotted black
00337 
00338         // Draw the path, with the bitmap fill
00339         GRenderBitmap::DrawPathToOutputDevice(pPath);
00340 
00341         RenderFlags.VeryMono = OldVMState;
00342     }
00343     else
00344     {
00345         // Does this shape make use of complex things
00346         if (TestForComplexShape(&HostCaps))
00347             SetNextShapeColour(Black);
00348         else
00349             SetNextShapeColour(White);
00350 
00351         // Draw the path
00352         GRenderBitmap::DrawPathToOutputDevice(pPath);
00353     }
00354 
00355     // restore the context
00356     RestoreContext();
00357 }
00358 
00359 
00360 /********************************************************************************************
00361 
00362 >   virtual void MaskedRenderRegion::DrawRect(DocRect* pRectToRender)
00363 
00364     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00365     Created:    6/4/95
00366     Inputs:     pRectToRender - The Rectangle that we need to render
00367     Purpose:    This function will examine the attributes etc to see if this represents a
00368                 simple or compex shape. It will set up the attributes according to the result
00369                 of this and then call the base class version of the function.
00370 
00371 ********************************************************************************************/
00372 
00373 void MaskedRenderRegion::DrawRect(DocRect* pRectToRender)
00374 {
00375     // Save the context
00376     SaveContext();
00377 
00378     // Does this shape make use of complex things
00379     if (TestForComplexShape(&HostCaps))
00380         SetNextShapeColour(Black);
00381     else
00382         SetNextShapeColour(White);
00383 
00384     // Draw the path
00385     GRenderBitmap::DrawRect(pRectToRender);
00386 
00387     // restore the context
00388     RestoreContext();
00389 }
00390 
00391 
00392 /********************************************************************************************
00393 
00394 >   virtual void MaskedRenderRegion::DrawLine(const DocCoord &StartPoint,
00395                                                 const DocCoord &EndPoint)
00396 
00397     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00398     Created:    6/4/95
00399     Inputs:     StartPoint, EndPoint - the coords to draw a line between
00400     Purpose:    This function will examine the attributes etc to see if this represents a
00401                 simple or compex shape. It will set up the attributes according to the result
00402                 of this and then call the base class version of the function.
00403 
00404 ********************************************************************************************/
00405 
00406 void MaskedRenderRegion::DrawLine(const DocCoord &StartPoint, const DocCoord &EndPoint)
00407 {
00408     // Save the context
00409     SaveContext();
00410 
00411     // Does this shape make use of complex things
00412     if (TestForComplexShape(&HostCaps))
00413         SetNextShapeColour(Black);
00414     else
00415         SetNextShapeColour(White);
00416 
00417     // Draw the path
00418     GRenderBitmap::DrawLine(StartPoint, EndPoint);
00419 
00420     // restore the context
00421     RestoreContext();
00422 }
00423 
00424 
00425 /********************************************************************************************
00426 
00427 >   virtual void MaskedRenderRegion::DrawPixel(const DocCoord &Point)
00428 
00429     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00430     Created:    6/4/95
00431     Inputs:     Point - the coord to draw the pixel in
00432     Purpose:    This function will examine the attributes etc to see if this represents a
00433                 simple or compex shape. It will set up the attributes according to the result
00434                 of this and then call the base class version of the function.
00435 
00436 ********************************************************************************************/
00437 
00438 void MaskedRenderRegion::DrawPixel(const DocCoord &Point)
00439 {
00440     // Save the context
00441     SaveContext();
00442 
00443     // Does this shape make use of complex things
00444     if (TestForComplexShape(&HostCaps))
00445         SetNextShapeColour(Black);
00446     else
00447         SetNextShapeColour(White);
00448 
00449     // Draw the path
00450     GRenderBitmap::DrawPixel(Point);
00451 
00452     // restore the context
00453     RestoreContext();
00454 }
00455 
00456 
00457 /********************************************************************************************
00458 
00459 >   virtual void MaskedRenderRegion::DrawBitmap(const DocCoord &Point, KernelBitmap* pBitmap)
00460 
00461     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00462     Created:    6/4/95
00463     Inputs:     Point - The position to draw the bitmap at
00464                 pBitmap - the bitmap that needs drawing
00465     Purpose:    This function will examine the attributes etc to see if this represents a
00466                 simple or compex shape. It will set up the attributes according to the result
00467                 of this and then call the base class version of the function.
00468 
00469 ********************************************************************************************/
00470 
00471 void MaskedRenderRegion::DrawBitmap(const DocCoord &Point, KernelBitmap* pBitmap)
00472 {
00473     // Save the context
00474     SaveContext();
00475 
00476     // Does this shape make use of complex things
00477     if (TestForComplexShape(&HostCaps))
00478         SetNextShapeColour(Black);
00479     else
00480         SetNextShapeColour(White);
00481 
00482     // Draw the path
00483     GRenderBitmap::DrawBitmap(Point, pBitmap);
00484 
00485     // restore the context
00486     RestoreContext();
00487 }
00488 
00489 
00490 /********************************************************************************************
00491 
00492 >   virtual void MaskedRenderRegion::DrawBitmap(const DocCoord &Point, UINT32 BitmapID,
00493                                                 UINT32 ToolID)
00494 
00495     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00496     Created:    6/4/95
00497     Inputs:     Point - the position to draw the bitmap at
00498                 BitmapID - The ID of the bitmap to render
00499                 ToolID - the ID of the tool that the bitmap belongs to
00500     Purpose:    This function will examine the attributes etc to see if this represents a
00501                 simple or compex shape. It will set up the attributes according to the result
00502                 of this and then call the base class version of the function.
00503 
00504 ********************************************************************************************/
00505 
00506 void MaskedRenderRegion::DrawBitmap(const DocCoord &Point, UINT32 BitmapID, UINT32 ToolID)
00507 {
00508     // Save the context
00509     SaveContext();
00510 
00511     // Does this shape make use of complex things
00512     if (TestForComplexShape(&HostCaps))
00513         SetNextShapeColour(Black);
00514     else
00515         SetNextShapeColour(White);
00516 
00517     // Draw the path
00518     GRenderBitmap::DrawBitmap(Point, BitmapID, ToolID);
00519 
00520     // restore the context
00521     RestoreContext();
00522 }
00523 
00524 BOOL MaskedRenderRegion::DrawTransformedBitmap(NodeBitmap *pNodeBitmap)
00525 {
00526     // Save the context
00527     SaveContext();
00528 
00529     // Work out if we can do this bitmap directly
00530     BOOL CanDoBitmap = FALSE;
00531 
00532     // Does this shape make use of complex things
00533     if (!(TestForComplexShape(&HostCaps) || pNodeBitmap->NeedsTransparency()))
00534     {
00535         // See what kind of bitmaps this render region can do
00536         if (HostCaps.ArbitraryBitmaps)
00537         {
00538             // We can do anything...
00539             CanDoBitmap = TRUE;
00540         }
00541         else
00542         {
00543             if (HostCaps.SimpleBitmaps)
00544             {
00545                 // Check that the bitmap area is rectangular, and is perpendicular to
00546                 // the x and y axes.
00547                 if (pNodeBitmap->HasSimpleOrientation(this))
00548                 {
00549                     // Yes - simple scaling - the render region can do this.
00550                     CanDoBitmap = TRUE;
00551                 }
00552             }
00553         }
00554     }
00555 
00556     // Here we set up reasonable attributes - we want to fill the bitmap
00557     // path but not stroke it.  NB. This is very important - do not remove
00558     // otherwise the mask will be wrong!
00559     DocColour           colorBlack( COLOUR_BLACK ); 
00560     SetFillColour( colorBlack );
00561     DocColour           colorNone( COLOUR_NONE );
00562     SetLineColour( colorNone );
00563 
00564     if (CanDoBitmap)
00565     {
00566         SetNextShapeColour(White);
00567 
00568         // Draw the path (that represents the bitmap object)
00569         GRenderBitmap::DrawPathToOutputDevice(&pNodeBitmap->InkPath);
00570     }
00571     else
00572     {
00573         if (pNodeBitmap->NeedsTransparency())
00574         {
00575             // It's a masked bitmap, so we'll need to actually render the non-masked
00576             // pixels as black 
00577             BOOL OldVMState = RenderFlags.VeryMono;
00578             RenderFlags.VeryMono = TRUE;    // Forces non-masked pixels to be plotted black
00579 
00580             // Call base class to plot the bitmap
00581             RenderRegion::DrawTransformedBitmap(pNodeBitmap);
00582 
00583             RenderFlags.VeryMono = OldVMState;
00584         }
00585         else
00586         {
00587             SetNextShapeColour(Black);
00588 
00589             // Draw the path (that represents the bitmap object)
00590             GRenderBitmap::DrawPathToOutputDevice(&pNodeBitmap->InkPath);
00591         }
00592     }
00593 
00594     // restore the context
00595     RestoreContext();
00596 
00597     return TRUE;
00598 }
00599 
00600 /********************************************************************************************
00601 
00602 >   virtual void MaskedRenderRegion::DrawDragRect(DocRect *RectToRender)
00603 
00604     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00605     Created:    6/4/95
00606     Inputs:     RectToRender - The Rectangle
00607     Purpose:    None - Does nothing
00608 
00609 ********************************************************************************************/
00610 
00611 void MaskedRenderRegion::DrawDragRect(DocRect *RectToRender)
00612 {
00613 }
00614 
00615 
00616 /********************************************************************************************
00617 
00618 >   virtual void MaskedRenderRegion::DrawBlob(DocCoord p, BlobType type)
00619 
00620     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00621     Created:    6/4/95
00622     Inputs:     p - A coord
00623                 type - The type of blob
00624     Purpose:    None - Does nothing
00625 
00626 ********************************************************************************************/
00627 
00628 void MaskedRenderRegion::DrawBlob(DocCoord p, BlobType type)
00629 {
00630 }
00631 
00632 
00633 /********************************************************************************************
00634 
00635 >   virtual void MaskedRenderRegion::DrawCross(const DocCoord &Point, const UINT32 Size)
00636 
00637     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00638     Created:    6/4/95
00639     Inputs:     Point - a Coord
00640                 Size - the size of the cross
00641     Purpose:    None - Does nothing
00642 
00643 ********************************************************************************************/
00644 
00645 void MaskedRenderRegion::DrawCross(const DocCoord &Point, const UINT32 Size)
00646 {
00647 }
00648 
00649 
00650 /********************************************************************************************
00651 
00652 >   virtual void MaskedRenderRegion::DrawBitmapBlob(const DocCoord &Point,
00653                                                     KernelBitmap* BlobShape)
00654 
00655     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00656     Created:    6/4/95
00657     Inputs:     Point - A Coord
00658                 BlobShape - the bitmap to use
00659     Purpose:    None - Does nothing
00660 
00661 ********************************************************************************************/
00662 
00663 void MaskedRenderRegion::DrawBitmapBlob(const DocCoord &Point, KernelBitmap* BlobShape)
00664 {
00665 }
00666 
00667 
00668 /********************************************************************************************
00669 
00670 >   virtual void MaskedRenderRegion::DrawBitmapBlob(const DocCoord &Point, UINT32 BitmapID,
00671                                                         UINT32 ToolID)
00672 
00673     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00674     Created:    6/4/95
00675     Inputs:     Point - A coord
00676                 BitmapID - the ID of a bitmap
00677                 ToolID - the Id of the tool the bitmap resource is in
00678     Purpose:    None - Does nothing
00679 
00680 ********************************************************************************************/
00681 
00682 void MaskedRenderRegion::DrawBitmapBlob(const DocCoord &Point, ResourceID resID )
00683 {
00684 }
00685 
00686 
00687 
00688 
00689 
00690 /********************************************************************************************
00691 
00692 >   void MaskedRenderRegion::SetNextShapeColour(DocColour& RequiredCol)
00693 
00694     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00695     Created:    20/4/95
00696     Inputs:     RequiredCol - The colour to replace fill and stroke colours with
00697     Purpose:    Sets all the attributes up so that we can render into our mask. It will
00698                 boil everything down to a flat fill and stroke ready to be rendered into
00699                 the mask. The colour passed in will probably be Black or White, but I left
00700                 it open in case I thought of some other use for this.
00701 
00702 ********************************************************************************************/
00703 
00704 void MaskedRenderRegion::SetNextShapeColour(DocColour& RequiredCol)
00705 {
00706     // Find out about the fill attr
00707     ColourFillAttribute* pColFillAttr = (ColourFillAttribute*) CurrentAttrs[ATTR_FILLGEOMETRY].pAttr;
00708     if ((pColFillAttr!=NULL) && (pColFillAttr->IS_KIND_OF(GradFillAttribute)))
00709     {
00710         // This is a grad fill, so just set the colour as required
00711         SetFillColour(RequiredCol);
00712     }
00713     else
00714     {
00715         // Is there a fill colour of any kind
00716         DocColour MyFillColour = RR_FILLCOLOUR();
00717 
00718         // See if it is 'no colour'
00719         if (!MyFillColour.IsTransparent())
00720         {
00721             // Nope, its a real colour alright, so we had better set the fill colour
00722             SetFillColour(RequiredCol);
00723         }
00724     }
00725 
00726     // Find out about the line colour
00727     DocColour MyStrokeColour = RR_STROKECOLOUR();
00728 
00729     // See if it is 'no colour'
00730     if (!MyStrokeColour.IsTransparent())
00731     {
00732         // Nope, its a real colour alright, so we had better set the fill colour
00733         SetLineColour(RequiredCol);
00734     }
00735 
00736     // Set Fill transp to none
00737     if (pFillAttr!=NULL)
00738         RenderRegion::SetTranspFillGeometry(pFillAttr, FALSE);
00739 
00740     // Set the stroke transp to none
00741     if (pStrokeAttr!=NULL)
00742         RenderRegion::SetLineTransp(pStrokeAttr, FALSE);
00743 }
00744 
00745 
00746 
00747 
00748 /********************************************************************************************
00749 
00750 >   BOOL MaskedRenderRegion::SpreadMask()
00751 
00752     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00753     Created:    15/5/95
00754     Returns:    TRUE if the mask was spread, FALSE if there was no mask in the first place
00755     Purpose:    Spreads the mask out by a pixel. This allows us to make the area that is
00756                 blitted slightly bigger to cover up any differences between the device
00757                 resolution and the bitmap resolution. This function will grow the mask
00758                 above, below, to the left and right by a single pixel. If this is not
00759                 enough, call this function more than once.
00760 
00761 ********************************************************************************************/
00762 
00763 BOOL MaskedRenderRegion::SpreadMask()
00764 {
00765     // If there is a bitmap
00766     if (pBits!=NULL && pBitmapInfo!=NULL)
00767     {
00768         // Get the scan line size in bytes
00769         INT32 ScanLineByteSize = (pBitmapInfo->bmiHeader.biWidth+7)/8;
00770 
00771         // Round it up to the nearest word boundary. Note, this is still a count of bytes
00772         INT32 ScanLineWordSize = ((ScanLineByteSize+3)/4)*4;
00773         
00774         // Start looping through all the scan lines in the mask,
00775         // going from top to bottom, moving set pixels up
00776         LPBYTE CurrentByte = NULL;
00777         LPBYTE ByteAbove = NULL;
00778         INT32 i;
00779         for (i=1; i<pBitmapInfo->bmiHeader.biHeight; i++)
00780         {
00781             // point CurrentByte at the start of the next scan line
00782             CurrentByte = pBits + (i*ScanLineWordSize);
00783             ByteAbove = pBits + ((i-1)*ScanLineWordSize);
00784 
00785             // Go along the scan line
00786             BOOL SetHighBit = FALSE;
00787             for (INT32 j=0; j<ScanLineByteSize; j++)
00788             {
00789                 // Try and set the leading pixel on the current byte
00790                 BYTE Mask = 0x01;
00791                 BYTE Current = BYTE(~(*CurrentByte));
00792 
00793                 // Loop though the mask
00794                 BOOL Found = FALSE;
00795                 while (Mask!=0)
00796                 {
00797                     // See if we have found the least sig. pixel yet
00798                     if ((Mask & Current) != 0)
00799                     {
00800                         Found = TRUE;
00801                         break;
00802                     }
00803 
00804                     // Move the mask along a bit
00805                     Mask = Mask << 1;
00806                 }
00807 
00808                 // Set the high bit if needed
00809                 if (SetHighBit)
00810                 {
00811                     Current = Current | 0x80;
00812                     SetHighBit = FALSE;
00813                 }
00814 
00815                 // If we found a bit in this byte, set the bit next to the least sig bit
00816                 if (Found)
00817                 {
00818                     if (Mask==0x01)
00819                         SetHighBit = TRUE;
00820                     else
00821                         Current = Current | (Mask>>1);
00822                 }
00823 
00824                 // Or this byte with the one in the scan line above
00825                 BYTE Result = BYTE(~(*ByteAbove)) | Current;
00826                 *ByteAbove = BYTE(~Result);
00827 
00828                 // Move to the next byte
00829                 CurrentByte++;
00830                 ByteAbove++;
00831             }
00832         }
00833 
00834         // Start looping through all the scan lines in the mask,
00835         // going from bottom to top, moving set pixels down
00836         CurrentByte = NULL;
00837         LPBYTE ByteBelow = NULL;
00838         for (i=pBitmapInfo->bmiHeader.biHeight-2; i>=0; i--)
00839         {
00840             // point CurrentByte at the start of the next scan line
00841             CurrentByte = pBits + (i*ScanLineWordSize) + ScanLineByteSize;
00842             ByteBelow = pBits + ((i+1)*ScanLineWordSize) + ScanLineByteSize;
00843 
00844             // Go along the scan line
00845             BOOL SetLowBit = FALSE;
00846             for (INT32 j=ScanLineByteSize-1; j>=0; j--)
00847             {
00848                 // Try and set the leading pixel on the current byte
00849                 BYTE Mask = 0x80;
00850                 BYTE Current = BYTE(~(*CurrentByte));
00851 
00852                 // loop though the mask
00853                 BOOL Found = FALSE;
00854                 while (Mask!=0)
00855                 {
00856                     // See if we have found the least sig. pixel yet
00857                     if ((Mask & Current) != 0)
00858                     {
00859                         Found = TRUE;
00860                         break;
00861                     }
00862 
00863                     // Move the mask along a bit
00864                     Mask = Mask >> 1;
00865                 }
00866 
00867                 // Set the low bit if needed
00868                 if (SetLowBit)
00869                 {
00870                     Current = Current | 0x01;
00871                     SetLowBit = FALSE;
00872                 }
00873 
00874                 // If we found a bit in this byte, set the bit next to the most sig bit
00875                 if (Found)
00876                 {
00877                     if (Mask==0x80)
00878                         SetLowBit = TRUE;
00879                     else
00880                         Current = Current | (Mask<<1);
00881                 }
00882 
00883                 // Or this byte with the one in the scan line below
00884                 BYTE Result = BYTE(~(*ByteBelow)) | Current;
00885                 *ByteBelow = BYTE(~Result);
00886 
00887                 // Move to the next byte
00888                 CurrentByte--;
00889                 ByteBelow--;
00890             }
00891         }
00892     }
00893     
00894     return TRUE;
00895 }
00896 
00897 
00898 /********************************************************************************************
00899 
00900 >   INT32 MaskedRenderRegion::FindCoverage(BOOL AnyCoverageReturns100 = FALSE)
00901 
00902     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00903     Created:    21/4/95
00904 
00905     Inputs:     AnyConverageReturns100 - In most (if not all) calls to this function,
00906                 the caller is only interested in whether coverage is equal to zero
00907                 or not (i.e. "Do I have to bother rendering anything?"). If you set
00908                 this flag to TRUE, this function will return 100% immediately if it
00909                 finds a single pixel set in the mask, or 0% only if there are no pixels
00910                 set in the mask. This is thus a much faster test of "do we need to render"
00911                 because it usually doesn't have to scan far before it finds a pixel to plot.
00912                 (Added by Jason, 1/7/96)
00913 
00914     Returns:    0 - 100. This represents the percentage of the masked bitmap that has pixels
00915                 set in it. A value of 0 means that there are no pixels set in the mask. You
00916                 can take this value to mean 'do not bother trying to display the bitmap cos
00917                 none of it is visible'. A value of 100 means that every pixel in the mask is set
00918                 so no clever masked plotting of the bitmap is required.
00919                 (or, if the AnyConverageReturns100 flag was set, a value of 100 just means
00920                 that there was at least one pixel requiring plotting)
00921 
00922     Purpose:    Finds out how much of the mask has been set.
00923 
00924 ********************************************************************************************/
00925 
00926 INT32 MaskedRenderRegion::FindCoverage(BOOL AnyCoverageReturns100)
00927 {
00928     INT32 TotalPixels = 0;
00929     INT32 TotalClearPixels = 0;
00930 
00931     if (pBits!=NULL && pBitmapInfo!=NULL)
00932     {
00933         // Get the scan line size in bytes
00934         const INT32 ScanLineByteSize = (pBitmapInfo->bmiHeader.biWidth+7)/8;
00935 
00936         // Round it up to the nearest word boundary. Note, this is still a count of bytes
00937         const INT32 ScanLineWordSize = ((ScanLineByteSize+3)/4)*4;
00938 
00939         // Work out how many padding pixels (bits) are on the end of the scanline
00940         const INT32 EndPixels = 8- ((ScanLineByteSize*8) - pBitmapInfo->bmiHeader.biWidth);
00941 
00942         // The last byte of each scanline may not use all its pixels, so we build a mask,
00943         // which is used to discount padding pixels from consideration
00944         BYTE Mask = 0x0;
00945         {
00946             BYTE Bit = 0x80;
00947             for (INT32 i=0; i<EndPixels; i++)
00948                 Mask |= Bit>>i;
00949         }
00950 
00951 
00952         // Start looping through all the scan lines in the mask
00953         LPBYTE CurrentByte = NULL;
00954         for (INT32 i=0; i<pBitmapInfo->bmiHeader.biHeight; i++)
00955         {
00956             // point CurrentByte at the start of the next scan line
00957             CurrentByte = pBits + (i*ScanLineWordSize);
00958 
00959             // Count this scan line of pixels
00960             TotalPixels += pBitmapInfo->bmiHeader.biWidth;
00961 
00962             // Go along the scan line, counting pixels
00963             for (INT32 j=0; j<ScanLineByteSize-1; j++)
00964             {
00965                 // look up the current byte
00966                 TotalClearPixels += BitCountTable[*CurrentByte];
00967 
00968                 // Move to the next byte
00969                 CurrentByte ++;
00970             }
00971 
00972             BYTE EndByte = *CurrentByte & Mask;
00973             TotalClearPixels += BitCountTable[EndByte];
00974 
00975             // If we just want to know if the entire mask is clear, then check if we found
00976             // any non-masked pixels at all in this scanline - if so, return immediately.
00977             if (AnyCoverageReturns100 && TotalClearPixels != TotalPixels)
00978                 return(100);
00979         }
00980     }
00981 
00982     // The mask was empty or missing
00983     if ((TotalClearPixels==TotalPixels) || (TotalPixels==0))
00984     {
00985         TRACEUSER( "Rik", _T("Coverage = 0\n"));
00986         return 0;
00987     }
00988 
00989     // Every pixel was set
00990     if (TotalClearPixels==0)
00991     {
00992         TRACEUSER( "Rik", _T("Coverage = 100\n"));
00993         return 100;
00994     }
00995 
00996     // Work out the result
00997     INT32 Result = 100 - ((TotalClearPixels*100) / TotalPixels);
00998     
00999     // Rounding errors could give this misleading result
01000     if (Result<=0)
01001         Result = 1;
01002 
01003     // and this one, so change them
01004     if (Result>=100)
01005         Result = 99;
01006 
01007     // Tell them what percentage of pixels were set
01008     TRACEUSER( "Rik", _T("Coverage = %ld\n"), Result);
01009     return Result;
01010 }
01011 
01012 
01013 
01014 /********************************************************************************************
01015 
01016 >   INT32 MaskedRenderRegion::FindMaskDpi()
01017 
01018     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
01019     Created:    30/4/95
01020     Returns:    The Dpi of the mask in this region
01021     Purpose:    This function is used to find out the DPI that the region was created at.
01022                 This is important as the device it is displaying to may have a different
01023                 dpi and the difference has to be compensated for.
01024                 Returns a INT32 form of the dpi
01025                 As most printing and masking related items only require non-fractional dpis
01026                 then this should not be a problem. So return a rounded up form of the stored
01027                 double form. 
01028 
01029 ********************************************************************************************/
01030 
01031 INT32 MaskedRenderRegion::FindMaskDpi()
01032 {
01033     // tell them about the dpi
01034     // Need to return a rounded form of the stored double dpi
01035     return (INT32)(PixelsPerInch + 0.5);
01036 }
01037 
01038 /********************************************************************************************
01039 
01040 >   double MaskedRenderRegion::FindMaskDpi()
01041 
01042     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01043     Created:    12/12/95
01044     Returns:    The Dpi of the mask in this region
01045     Purpose:    This function is used to find out the DPI that the region was created at.
01046                 This is important as the device it is displaying to may have a different
01047                 dpi and the difference has to be compensated for.
01048                 Returns the new double form of the dpi
01049 
01050 ********************************************************************************************/
01051 
01052 //double MaskedRenderRegion::FindMaskDpi()
01053 //{
01054     // tell them about the dpi
01055 //  return PixelsPerInch;
01056 //}
01057 
01058 
01059 /********************************************************************************************
01060 
01061 >   void MaskedRenderRegion::GetFirstMaskRegion(MaskRegion* pMaskInfo)
01062 
01063     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
01064     Created:    21/4/95
01065     Outputs:    pMaskInfo - holds info about the first region as output
01066     Purpose:    This function finds the first scan line section in the mask that indicates
01067                 pixels need to be set. When it finds the next section it fills in the info
01068                 about it in pMaskInfo and returns.
01069                 If there are no regions to be found in the mask then the Length member
01070                 of pMaskInfo will be set to zero. This is your clue that there are no
01071                 scan line sections to process.
01072     SeeAlso:    MaskedRenderRegion::GetNextMaskRegion; struct MaskRegion
01073 
01074 ********************************************************************************************/
01075 
01076 void MaskedRenderRegion::GetFirstMaskRegion(MaskRegion* pMaskInfo)
01077 {
01078     // Set up the starting conditions
01079     pMaskInfo->x = 0;
01080     pMaskInfo->y = 0;
01081     pMaskInfo->Length = 0;
01082 
01083     // start looking for a bit we have to blit
01084     ScanMaskFrom(pMaskInfo);
01085 }
01086 
01087 
01088 
01089 
01090 /********************************************************************************************
01091 
01092 >   void MaskedRenderRegion::GetNextMaskRegion(MaskRegion* pMaskInfo)
01093 
01094     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
01095     Created:    21/4/95
01096     Inputs:     pMaskInfo - Holds info about the last region that was found
01097     Outputs:    pMaskInfo - but holds info about the next region as output
01098     Purpose:    This function finds the next scan line section in the mask that indicates
01099                 pixels need to be set. It uses the info in the pMaskInfo param to work out
01100                 where to start looking from. When it finds the next section, which could
01101                 be on the same scan line as the present one, it fills in the info about it
01102                 in pMaskInfo and returns.
01103                 If there are no more regions to be found in the mask then the Length member
01104                 of pMaskInfo will be set to zero. This is your clue that there are no more
01105                 scan line sections to process.
01106     SeeAlso:    MaskedRenderRegion::GetFirstMaskRegion; struct MaskRegion
01107 
01108 ********************************************************************************************/
01109 
01110 void MaskedRenderRegion::GetNextMaskRegion(MaskRegion* pMaskInfo)
01111 {
01112     // Find the end of the last scan section    
01113     // Move to the end of the last region
01114     pMaskInfo->x += pMaskInfo->Length;
01115 
01116     // are we at the end of the scan line
01117     if (pMaskInfo->x >= pBitmapInfo->bmiHeader.biWidth)
01118     {
01119         pMaskInfo->x = 0;
01120         pMaskInfo->y++;
01121     }
01122 
01123     // Reset the length to zero
01124     pMaskInfo->Length = 0;
01125 
01126     // start looking for a bit we have to blit
01127     ScanMaskFrom(pMaskInfo);
01128 }
01129 
01130 
01131 
01132 /********************************************************************************************
01133 
01134 >   void MaskedRenderRegion::ScanMaskFrom(MaskRegion* pMaskInfo)
01135 
01136     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
01137     Created:    23/4/95
01138     Inputs:     pMaskInfo - Holds the position to start looking from
01139     Outputs:    pMaskInfo - Hold info about the next scan section to look at
01140     Purpose:    Searchs the mask for a section that means we will have to blit something.
01141                 The starting position of the section and the length of the section are put
01142                 into pMaskInfo and returned. pMaskInfo->Length will be set to zero if there
01143                 are no more sections in the mask.
01144 
01145 ********************************************************************************************/
01146 
01147 void MaskedRenderRegion::ScanMaskFrom(MaskRegion* pMaskInfo)
01148 {
01149     // Assume we will find no more scan sections
01150     pMaskInfo->Length = 0;
01151 
01152     // get a mask to look along the bits in the mask
01153     INT32 Mask = 0x80;
01154     INT32 XStartPos = pMaskInfo->x;
01155     INT32 YStartPos = pMaskInfo->y;
01156 
01157     // Set the mask up correctly, as the X starting pos may not be at the start of a byte
01158     if (XStartPos!=0)
01159     {
01160         // Go through the byte, setting the bits back to 1 as needed
01161         INT32 PixelNum = (XStartPos/8) * 8;
01162         while (PixelNum < XStartPos)
01163         {
01164             // Shift the bit along
01165             Mask = Mask>>1;
01166 
01167             // Count the pixel
01168             PixelNum++;
01169         }
01170     }
01171 
01172     // Find out how many bytes in a scan line
01173     INT32 ScanLineSize = (pBitmapInfo->bmiHeader.biWidth+7)/8;
01174     ScanLineSize = (ScanLineSize+3)&~3;
01175 
01176     // We start out looking for the start of a region
01177     BOOL LookingForStart = TRUE;
01178 
01179     // a pointer to the byte we are dealing with
01180     LPBYTE pByte = NULL;
01181 
01182     // try and find the start of the first region
01183     for (INT32 j=YStartPos; j<pBitmapInfo->bmiHeader.biHeight; j++)
01184     {
01185         // Get the byte we are interested in
01186         pByte = pBits + (j*ScanLineSize) + (XStartPos/8);
01187 
01188         // start going accross the scan line
01189         for (INT32 i=XStartPos; i<pBitmapInfo->bmiHeader.biWidth; i++)
01190         {
01191             // Find out what this bit is (1 or 0)
01192             INT32 ThisBit = (*pByte) & Mask;
01193 
01194             // what are we looking for - the start or the end of a region.
01195             if (LookingForStart)
01196             {
01197                 if (ThisBit == 0)
01198                 {
01199                     // Set the start position in the mask region
01200                     pMaskInfo->x = i;
01201                     pMaskInfo->y = j;
01202                     
01203                     // This bit could be all there is of a 1 pixel wide region
01204                     pMaskInfo->Length = 1;
01205 
01206                     // we are no longer looking for the start of the region
01207                     LookingForStart = FALSE;
01208                 }
01209             }
01210             else
01211             {
01212                 // We are looking for the end of the region
01213                 if (ThisBit!=0)
01214                 {
01215                     // we have reached the end of the region
01216                     return;
01217                 }
01218                 else
01219                 {
01220                     // we are still in the region, so count the pixel
01221                     pMaskInfo->Length++;
01222                 }
01223             }
01224 
01225             // Move the mask bit along to the next pixel
01226             Mask = Mask>>1;
01227             
01228             // if we have exhasuted this byte, go on to the next one and reset the mask
01229             if (Mask==0)
01230             {
01231                 Mask = 0x80;
01232                 pByte++;
01233             }
01234         }
01235         
01236         // if we have found part of a region at the end of the scan line, return it
01237         if (pMaskInfo->Length>0)
01238             return;
01239 
01240         // Start the next scan line from the beginning
01241         XStartPos = 0;
01242         Mask = 0x80;
01243     }
01244 }
01245 
01246 

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