Main Page   Class Hierarchy   Compound List   File List   Compound Members  

libemf.h

00001 /* -*- c++ -*-
00002  * EMF: A library for generating ECMA-234 Enhanced Metafiles
00003  * Copyright (C) 2002 lignum Computing, Inc. <libemf@lignumcomputing.com>
00004  * $Id: libemf_8h-source.html,v 1.5 2003/01/14 03:57:22 allen Exp $
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 #ifndef _LIBEMF_H
00022 #define _LIBEMF_H 1
00023 
00024 #include <cmath>
00025 #include <vector>
00026 #include <map>
00027 #include <functional>
00028 #include <algorithm>
00029 
00030 #include <config.h>
00031 #include <libEMF/emf.h>
00032 
00033 #include <libEMF/wine/w16.h>
00034 
00035 namespace EMF {
00040 #if 1
00041   const int XMAX_PIXELS = 1024; /*(INT_MAX)*/
00042 #else
00043   const int XMAX_PIXELS = 1280; /*(INT_MAX)*/
00044 #endif
00045 
00049 #if 1
00050   const int YMAX_PIXELS = 768; /*(INT_MAX)*/
00051 #else
00052   const int YMAX_PIXELS = 1024; /*(INT_MAX)*/
00053 #endif
00054 
00059   const int XMAX_MM = 320;
00065   const int YMAX_MM = 240;
00069   const int RESOLUTION = 96;
00073   static inline int ROUND_TO_LONG ( int n ) { return ((n+3)/4)*4; }
00074 
00076 
00081   struct WCHARSTR {
00082     WCHAR *const string_;       
00083     const int length_;          
00084 
00089     WCHARSTR ( WCHAR *const string, const int length )
00090       : string_( string ), length_( length ) {}
00091   };
00092 
00094 
00099   struct CHARSTR {
00100     CHAR *const string_;        
00101     const int length_;          
00102 
00107     CHARSTR ( CHAR *const string, const int length )
00108       : string_( string ), length_( length ) {}
00109   };
00110 
00112 
00116   struct BYTEARRAY {
00117     BYTE *const array_;         
00118     const int n_;               
00119 
00124     BYTEARRAY ( BYTE *const array, const int n )
00125       : array_( array ), n_( n ) {}
00126   };
00127 
00129 
00132   struct POINTLARRAY {
00133     POINTL *const points_;      
00134     const DWORD n_;             
00135 
00140     POINTLARRAY ( POINTL *const points, const DWORD n )
00141       : points_( points ), n_( n ) {}
00142   };
00143 
00145 
00148   struct POINT16ARRAY {
00149     POINT16 *const points_;     
00150     const DWORD n_;             
00151 
00156     POINT16ARRAY ( POINT16 *const points, const DWORD n )
00157       : points_( points ), n_( n ) {}
00158   };
00159 
00161 
00164   struct INTARRAY {
00165     INT *const ints_;           
00166     const DWORD n_;             
00167 
00172     INTARRAY ( INT *const ints, const DWORD n )
00173       : ints_( ints ), n_( n ) {}
00174   };
00175 
00177 
00180   struct DWORDARRAY {
00181     DWORD *const dwords_;       
00182     const DWORD n_;             
00183 
00188     DWORDARRAY ( DWORD *const dwords, const DWORD n )
00189       : dwords_( dwords ), n_( n ) {}
00190   };
00191 
00193 
00196   struct PADDING {
00197     static const char padding_[4]; 
00198     const int size_;            
00199 
00203     PADDING ( const int size ) : size_( size ) {}
00204   };
00205   
00207 
00214   class DATASTREAM {
00215     bool swap_;
00216     ::FILE* fp_;
00217 
00218     static bool bigEndian ( void );
00219   public:
00225     DATASTREAM ( ::FILE* fp = 0 ) : swap_( bigEndian() ), fp_( fp ) {}
00230     void setStream ( ::FILE* fp ) { fp_ = fp; }
00235     DATASTREAM& operator<< ( const BYTE& byte )
00236     {
00237       fwrite( &byte, sizeof(BYTE), 1, fp_ );
00238       return *this;
00239     }
00244     DATASTREAM& operator>> ( BYTE& byte )
00245     {
00246       fread( &byte, sizeof(BYTE), 1, fp_ );
00247       return *this;
00248     }
00253     DATASTREAM& operator<< ( const WORD& word )
00254     {
00255       if ( swap_ ) {
00256         unsigned char const * p = (unsigned char const*)&word;
00257         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00258         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00259       }
00260       else
00261         fwrite( &word, sizeof(WORD), 1, fp_ );
00262       return *this;
00263     }
00268     DATASTREAM& operator>> ( WORD& word )
00269     {
00270       if ( swap_ ) {
00271         unsigned char* p = (unsigned char*)&word;
00272         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00273         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00274       }
00275       else
00276         fread( &word, sizeof(WORD), 1, fp_ );
00277       return *this;
00278     }
00283     DATASTREAM& operator<< ( const INT16& word )
00284     {
00285       if ( swap_ ) {
00286         unsigned char const * p = (unsigned char const*)&word;
00287         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00288         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00289       }
00290       else
00291         fwrite( &word, sizeof(INT16), 1, fp_ );
00292       return *this;
00293     }
00298     DATASTREAM& operator>> ( INT16& word )
00299     {
00300       if ( swap_ ) {
00301         unsigned char* p = (unsigned char*)&word;
00302         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00303         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00304       }
00305       else
00306         fread( &word, sizeof(INT16), 1, fp_ );
00307       return *this;
00308     }
00313     DATASTREAM& operator<< ( const DWORD& dword )
00314     {
00315       if ( swap_ ) {
00316         unsigned char const* p = (unsigned char const*)&dword;
00317         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00318         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00319         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00320         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00321       }
00322       else
00323         fwrite( &dword, sizeof(DWORD), 1, fp_ );
00324       return *this;
00325     }
00330     DATASTREAM& operator>> ( DWORD& dword )
00331     {
00332       if ( swap_ ) {
00333         unsigned char* p = (unsigned char*)&dword;
00334         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00335         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00336         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00337         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00338       }
00339       else
00340         fread( &dword, sizeof(DWORD), 1, fp_ );
00341       return *this;
00342     }
00347     DATASTREAM& operator<< ( const LONG& long_ )
00348     {
00349       if ( swap_ ) {
00350         unsigned char const* p = (unsigned char const*)&long_;
00351         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00352         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00353         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00354         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00355       }
00356       else
00357         fwrite( &long_, sizeof(LONG), 1, fp_ );
00358       return *this;
00359     }
00364     DATASTREAM& operator>> ( LONG& long_ )
00365     {
00366       if ( swap_ ) {
00367         unsigned char* p = (unsigned char*)&long_;
00368         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00369         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00370         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00371         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00372       }
00373       else
00374         fread( &long_, sizeof(LONG), 1, fp_ );
00375       return *this;
00376     }
00381     DATASTREAM& operator<< ( const INT& int_ )
00382     {
00383       if ( swap_ ) {
00384         unsigned char const* p = (unsigned char const*)&int_;
00385         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00386         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00387         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00388         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00389       }
00390       else
00391         fwrite( &int_, sizeof(INT), 1, fp_ );
00392       return *this;
00393     }
00398     DATASTREAM& operator>> ( INT& int_ )
00399     {
00400       if ( swap_ ) {
00401         unsigned char* p = (unsigned char*)&int_;
00402         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00403         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00404         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00405         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00406       }
00407       else
00408         fread( &int_, sizeof(INT), 1, fp_ );
00409       return *this;
00410     }
00415     DATASTREAM& operator<< ( const UINT& uint )
00416     {
00417       if ( swap_ ) {
00418         unsigned char const* p = (unsigned char const*)&uint;
00419         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00420         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00421         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00422         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00423       }
00424       else
00425         fwrite( &uint, sizeof(UINT), 1, fp_ );
00426       return *this;
00427     }
00432     DATASTREAM& operator>> ( UINT& uint )
00433     {
00434       if ( swap_ ) {
00435         unsigned char* p = (unsigned char*)&uint;
00436         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00437         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00438         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00439         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00440       }
00441       else
00442         fread( &uint, sizeof(UINT), 1, fp_ );
00443       return *this;
00444     }
00449     DATASTREAM& operator<< ( const FLOAT& float_ )
00450     {
00451       if ( swap_ ) {
00452         unsigned char const* p = (unsigned char const*)&float_;
00453         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00454         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00455         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00456         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00457       }
00458       else
00459         fwrite( &float_, sizeof(FLOAT), 1, fp_ );
00460       return *this;
00461     }
00466     DATASTREAM& operator>> ( FLOAT& float_ )
00467     {
00468       if ( swap_ ) {
00469         unsigned char* p = (unsigned char*)&float_;
00470         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00471         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00472         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00473         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00474       }
00475       else
00476         fread( &float_, sizeof(FLOAT), 1, fp_ );
00477       return *this;
00478     }
00483     DATASTREAM& operator<< ( const PADDING& padding )
00484     {
00485       if ( padding.size_ != 0 )
00486         fwrite( &padding.padding_, sizeof(CHAR), padding.size_, fp_ );
00487       return *this;
00488     }
00493     DATASTREAM& operator<< ( const RECTL& rectl )
00494     {
00495       *this << rectl.left << rectl.top << rectl.right << rectl.bottom;
00496       return *this;
00497     }
00502     DATASTREAM& operator>> ( RECTL& rectl )
00503     {
00504       *this >> rectl.left >> rectl.top >> rectl.right >> rectl.bottom;
00505       return *this;
00506     }
00511     DATASTREAM& operator<< ( const SIZEL& sizel )
00512     {
00513       *this << sizel.cx << sizel.cy;
00514       return *this;
00515     }
00520     DATASTREAM& operator>> ( SIZEL& sizel )
00521     {
00522       *this >> sizel.cx >> sizel.cy;
00523       return *this;
00524     }
00529     DATASTREAM& operator<< ( const WCHARSTR& wcharstr )
00530     {
00531       for ( int i = 0; i < wcharstr.length_; i++ )
00532         *this << wcharstr.string_[i];
00533       return *this;
00534     }
00539     DATASTREAM& operator>> ( WCHARSTR& wcharstr )
00540     {
00541       for ( int i = 0; i < wcharstr.length_; i++ )
00542         *this >> wcharstr.string_[i];
00543       return *this;
00544     }
00549     DATASTREAM& operator<< ( const CHARSTR& charstr )
00550     {
00551       fwrite( charstr.string_, sizeof(CHAR), charstr.length_, fp_ );
00552       return *this;
00553     }
00558     DATASTREAM& operator>> ( CHARSTR& charstr )
00559     {
00560       fread( charstr.string_, sizeof(CHAR), charstr.length_, fp_ );
00561       return *this;
00562     }
00567     DATASTREAM& operator<< ( const ::EMR& emr )
00568     {
00569       *this << emr.iType << emr.nSize;
00570       return *this;
00571     }
00576     DATASTREAM& operator>> ( ::EMR& emr )
00577     {
00578       *this >> emr.iType >> emr.nSize;
00579       return *this;
00580     }
00585     DATASTREAM& operator<< ( const POINT& point )
00586     {
00587       *this << point.x << point.y;
00588       return *this;
00589     }
00594     DATASTREAM& operator>> ( POINT& point )
00595     {
00596       *this >> point.x >> point.y;
00597       return *this;
00598     }
00603     DATASTREAM& operator<< ( const POINTL& pointl )
00604     {
00605       *this << pointl.x << pointl.y;
00606       return *this;
00607     }
00612     DATASTREAM& operator>> ( POINTL& pointl )
00613     {
00614       *this >> pointl.x >> pointl.y;
00615       return *this;
00616     }
00621     DATASTREAM& operator<< ( const POINT16& point )
00622     {
00623       *this << point.x << point.y;
00624       return *this;
00625     }
00630     DATASTREAM& operator>> ( POINT16& point )
00631     {
00632       *this >> point.x >> point.y;
00633       return *this;
00634     }
00639     DATASTREAM& operator<< ( const XFORM& xform )
00640     {
00641       *this << xform.eM11 << xform.eM12 << xform.eM21 << xform.eM22
00642             << xform.eDx << xform.eDy;
00643       return *this;
00644     }
00649     DATASTREAM& operator>> ( XFORM& xform )
00650     {
00651       *this >> xform.eM11 >> xform.eM12 >> xform.eM21 >> xform.eM22
00652             >> xform.eDx >> xform.eDy;
00653       return *this;
00654     }
00659     DATASTREAM& operator<< ( const BYTEARRAY& array )
00660     {
00661       fwrite( array.array_, sizeof(BYTE), array.n_, fp_ );
00662       return *this;
00663     }
00668     DATASTREAM& operator>> ( BYTEARRAY& array )
00669     {
00670       fread( array.array_, sizeof(BYTE), array.n_, fp_ );
00671       return *this;
00672     }
00677     DATASTREAM& operator<< ( const POINTLARRAY& array )
00678     {
00679       for ( unsigned int i = 0; i < array.n_; i++ )
00680         *this << array.points_[i];
00681       return *this;
00682     }
00687     DATASTREAM& operator>> ( POINTLARRAY& array )
00688     {
00689       for ( unsigned int i = 0; i < array.n_; i++ )
00690         *this >> array.points_[i];
00691       return *this;
00692     }
00697     DATASTREAM& operator<< ( const POINT16ARRAY& array )
00698     {
00699       for ( unsigned int i = 0; i < array.n_; i++ )
00700         *this << array.points_[i];
00701       return *this;
00702     }
00707     DATASTREAM& operator>> ( POINT16ARRAY& array )
00708     {
00709       for ( unsigned int i = 0; i < array.n_; i++ )
00710         *this >> array.points_[i];
00711       return *this;
00712     }
00717     DATASTREAM& operator<< ( const INTARRAY& array )
00718     {
00719       for ( unsigned int i = 0; i < array.n_; i++ )
00720         *this << array.ints_[i];
00721       return *this;
00722     }
00727     DATASTREAM& operator>> ( INTARRAY& array )
00728     {
00729       for ( unsigned int i = 0; i < array.n_; i++ )
00730         *this >> array.ints_[i];
00731       return *this;
00732     }
00737     DATASTREAM& operator<< ( const DWORDARRAY& array )
00738     {
00739       for ( unsigned int i = 0; i < array.n_; i++ )
00740         *this << array.dwords_[i];
00741       return *this;
00742     }
00747     DATASTREAM& operator>> ( DWORDARRAY& array )
00748     {
00749       for ( unsigned int i = 0; i < array.n_; i++ )
00750         *this >> array.dwords_[i];
00751       return *this;
00752     }
00757     DATASTREAM& operator<< ( const ::EMRTEXT& text )
00758     {
00759       *this << text.ptlReference << text.nChars << text.offString << text.fOptions
00760          << text.rcl << text.offDx;
00761       return *this;
00762     }
00767     DATASTREAM& operator>> ( ::EMRTEXT& text )
00768     {
00769       *this >> text.ptlReference >> text.nChars >> text.offString >> text.fOptions
00770             >> text.rcl >> text.offDx;
00771       return *this;
00772     }
00777     DATASTREAM& operator<< ( const LOGPEN& pen )
00778     {
00779       *this << pen.lopnStyle << pen.lopnWidth << pen.lopnColor;
00780       return *this;
00781     }
00786     DATASTREAM& operator>> ( LOGPEN& pen )
00787     {
00788       *this >> pen.lopnStyle >> pen.lopnWidth >> pen.lopnColor;
00789       return *this;
00790     }
00795     DATASTREAM& operator<< ( const EXTLOGPEN& pen )
00796     {
00797       // *** How big is this structure if there are no style entries? ***
00798       *this << pen.elpPenStyle << pen.elpWidth << pen.elpBrushStyle << pen.elpColor
00799             << pen.elpHatch << pen.elpNumEntries;
00800       return *this;
00801     }
00806     DATASTREAM& operator>> ( EXTLOGPEN& pen )
00807     {
00808       // *** How big is this structure if there are no style entries? ***
00809       *this >> pen.elpPenStyle >> pen.elpWidth >> pen.elpBrushStyle >> pen.elpColor
00810             >> pen.elpHatch >> pen.elpNumEntries;
00811       return *this;
00812     }
00817     DATASTREAM& operator<< ( const LOGBRUSH& brush )
00818     {
00819       *this << brush.lbStyle << brush.lbColor << brush.lbHatch;
00820       return *this;
00821     }
00826     DATASTREAM& operator>> ( LOGBRUSH& brush )
00827     {
00828       *this >> brush.lbStyle >> brush.lbColor >> brush.lbHatch;
00829       return *this;
00830     }
00835     DATASTREAM& operator<< ( const LOGFONTW& font )
00836     {
00837       *this << font.lfHeight << font.lfWidth << font.lfEscapement
00838             << font.lfOrientation << font.lfWeight << font.lfItalic
00839             << font.lfUnderline << font.lfStrikeOut << font.lfCharSet
00840             << font.lfOutPrecision << font.lfClipPrecision << font.lfQuality
00841             << font.lfPitchAndFamily
00842             << WCHARSTR( const_cast<WCHAR*const>(font.lfFaceName), LF_FACESIZE );
00843       return *this;
00844     }
00849     DATASTREAM& operator>> ( LOGFONTW& font )
00850     {
00851       WCHARSTR wFaceName( font.lfFaceName, LF_FACESIZE );
00852 
00853       *this >> font.lfHeight >> font.lfWidth >> font.lfEscapement
00854             >> font.lfOrientation >> font.lfWeight >> font.lfItalic
00855             >> font.lfUnderline >> font.lfStrikeOut >> font.lfCharSet
00856             >> font.lfOutPrecision >> font.lfClipPrecision >> font.lfQuality
00857             >> font.lfPitchAndFamily
00858             >> wFaceName;
00859       return *this;
00860     }
00865     DATASTREAM& operator<< ( const PANOSE& panose )
00866     {
00867       fwrite( &panose, sizeof(PANOSE), 1, fp_ );
00868       return *this;
00869     }
00874     DATASTREAM& operator>> ( PANOSE& panose )
00875     {
00876       fread( &panose, sizeof(PANOSE), 1, fp_ );
00877       return *this;
00878     }
00883     DATASTREAM& operator<< ( const EXTLOGFONTW& font )
00884     {
00885       *this << font.elfLogFont
00886             << WCHARSTR( const_cast<WCHAR*const>(font.elfFullName),
00887                          LF_FULLFACESIZE )
00888             << WCHARSTR( const_cast<WCHAR*const>(font.elfStyle), LF_FACESIZE )
00889             << font.elfVersion << font.elfStyleSize << font.elfMatch
00890             << font.elfReserved
00891             << BYTEARRAY( const_cast<BYTE*const>(font.elfVendorId),
00892                           ELF_VENDOR_SIZE )
00893             << font.elfCulture << font.elfPanose;
00894       return *this;
00895     }
00900     DATASTREAM& operator>> ( EXTLOGFONTW& font )
00901     {
00902       WCHARSTR wFullName( font.elfFullName, LF_FULLFACESIZE );
00903       WCHARSTR wStyle( font.elfStyle, LF_FACESIZE );
00904       BYTEARRAY bVendorId( font.elfVendorId, ELF_VENDOR_SIZE );
00905       *this >> font.elfLogFont
00906             >> wFullName >> wStyle
00907             >> font.elfVersion >> font.elfStyleSize >> font.elfMatch
00908             >> font.elfReserved >> bVendorId
00909             >> font.elfCulture >> font.elfPanose;
00910       return *this;
00911     }
00916     DATASTREAM& operator<< ( const LOGPALETTE& palette )
00917     {
00918       // *** How big is this structure if the palette is empty? ***
00919       *this << palette.palVersion << palette.palNumEntries;
00920       return *this;
00921     }
00926     DATASTREAM& operator>> ( LOGPALETTE& palette )
00927     {
00928       // *** How big is this structure if the palette is empty? ***
00929       *this >> palette.palVersion >> palette.palNumEntries;
00930       return *this;
00931     }
00932   };
00933 
00934   class METAFILEDEVICECONTEXT;
00935 
00937 
00943   class METARECORD {
00944   public:
00951     virtual void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const = 0;
00958     virtual bool serialize ( DATASTREAM ds ) = 0;
00964     virtual int size ( void ) const = 0;
00970     virtual ~METARECORD( ) { }
00971 #ifdef ENABLE_EDITING
00972 
00976     virtual void edit ( void ) const {}
00977 #endif
00978   };
00979 
00980 #ifdef ENABLE_EDITING
00981   /* Miscellaneous editing routines */
00982   inline void edit_rectl ( const char* tag, const RECTL& rectl )
00983   {
00984     printf( "\t%s\t: (%ld, %ld) - (%ld, %ld)\n", tag, rectl.left, rectl.top,
00985             rectl.right, rectl.bottom );
00986   }
00987 
00988   inline void edit_xform ( const char* tag, const XFORM& xform )
00989   {
00990     printf( "\t%s.eM11\t: %f\n", tag, xform.eM11 );
00991     printf( "\t%s.eM12\t: %f\n", tag, xform.eM12 );
00992     printf( "\t%s.eM21\t: %f\n", tag, xform.eM21 );
00993     printf( "\t%s.eM22\t: %f\n", tag, xform.eM22 );
00994     printf( "\t%s.eDx\t: %f\n", tag, xform.eDx );
00995     printf( "\t%s.eDy\t: %f\n", tag, xform.eDy );
00996   }
00997 
00998   inline void edit_color ( const char* tag, const COLORREF& color )
00999   {
01000     printf( "\t%s\t: R(0x%02lx) G(0x%02lx) B(0x%02lx)\n", tag,
01001             GetRValue( color ), GetGValue( color ), GetBValue( color ) );
01002   }
01003 
01004   inline void edit_sizel ( const char* tag, const SIZEL& size )
01005   {
01006     printf( "\t%s\t: (%ld, %ld)\n", tag, size.cx, size.cy );
01007   }
01008 
01009   inline void edit_pointl ( const char* tag, const POINTL& point )
01010   {
01011     printf( "\t%s\t: (%ld, %ld)\n", tag, point.x, point.y );
01012   }
01013 
01014   inline void edit_pointlarray ( const char* tag, const DWORD cptl,
01015                                   const POINTL* points )
01016   {
01017     printf( "\tcptl%s\t: %ld\n", tag, cptl );
01018     printf( "\taptl%s\t: ", tag );
01019     if ( cptl > 0 )
01020       printf( "%ld, %ld\n", points[0].x, points[0].y );
01021     else
01022       puts( "" );
01023     for ( DWORD i = 1; i < cptl; i++ )
01024       printf( "\t\t%s  %ld, %ld\n", tag, points[i].x, points[i].y );
01025   }
01026 
01027   inline void edit_point16array ( const char* tag, const unsigned int cpts,
01028                                   const POINT16* points )
01029   {
01030     printf( "\tcpts%s\t: %d\n", tag, cpts );
01031     printf( "\tapts%s\t: ", tag );
01032     if ( cpts > 0 )
01033       printf( "%d, %d\n", points[0].x, points[0].y );
01034     else
01035       puts( "" );
01036     for ( unsigned int i = 1; i < cpts; i++ )
01037       printf( "\t\t%s  %d, %d\n", tag, points[i].x, points[i].y );
01038   }
01039 
01040   inline void edit_pen_style ( const char* tag, DWORD style )
01041   {
01042     printf( "\t%s\t: ", tag );
01043     switch ( style & PS_STYLE_MASK ) {
01044     case PS_SOLID: printf( "PS_SOLID" ); break;
01045     case PS_DASH: printf( "PS_DASH" ); break;
01046     case PS_DOT: printf( "PS_DOT" ); break;
01047     case PS_DASHDOT: printf( "PS_DASHDOT" ); break;
01048     case PS_DASHDOTDOT: printf( "PS_DASHDOTDOT" ); break;
01049     case PS_NULL: printf( "PS_NULL" ); break;
01050     case PS_INSIDEFRAME: printf( "PS_INSIDEFRAME" ); break;
01051     case PS_USERSTYLE: printf( "PS_USERSTYLE" ); break;
01052     case PS_ALTERNATE: printf( "PS_ALTERNATE" ); break;
01053     }
01054     switch ( style & PS_ENDCAP_MASK ) {
01055     case PS_ENDCAP_ROUND: printf( " | PS_ENDCAP_ROUND" ); break;
01056     case PS_ENDCAP_SQUARE: printf( " | PS_ENDCAP_SQUARE" ); break;
01057     case PS_ENDCAP_FLAT: printf( " | PS_ENDCAP_FLAT" ); break;
01058     }
01059     switch ( style & PS_JOIN_MASK ) {
01060     case PS_JOIN_ROUND: printf( " | PS_JOIN_ROUND" ); break;
01061     case PS_JOIN_BEVEL: printf( " | PS_JOIN_BEVEL" ); break;
01062     case PS_JOIN_MITER: printf( " | PS_JOIN_MITER" ); break;
01063     }
01064     switch ( style & PS_TYPE_MASK ) {
01065     case PS_COSMETIC: printf( " | PS_COSMETIC" ); break;
01066     case PS_GEOMETRIC: printf( " | PS_GEOMETRIC" ); break;
01067     }
01068     printf( "\n" );
01069   }
01070 
01071   inline void edit_brush_style ( const char* tag, DWORD style )
01072   {
01073     printf( "\t%s\t: ", tag );
01074     switch ( style ) {
01075     case BS_SOLID: printf( "BS_SOLID" ); break;
01076     case BS_NULL: printf( "BS_NULL" ); break;
01077     case BS_HATCHED: printf( "BS_HATCHED" ); break;
01078     case BS_PATTERN: printf( "BS_PATTERN" ); break;
01079     case BS_INDEXED: printf( "BS_INDEXED" ); break;
01080     case BS_DIBPATTERN: printf( "BS_DIBPATTERN" ); break;
01081     case BS_DIBPATTERNPT: printf( "BS_DIBPATTERNPT" ); break;
01082     case BS_PATTERN8X8: printf( "BS_PATTERN8X8" ); break;
01083     case BS_DIBPATTERN8X8: printf( "BS_DIBPATTERN8X8" ); break;
01084     case BS_MONOPATTERN: printf( "BS_DIBPATTERN8X8" ); break;
01085     default: printf( "unknown(%ld)", style );
01086     }
01087     printf( "\n" );
01088   }
01089 
01090   inline void edit_brush_hatch ( const char* tag, DWORD hatch )
01091   {
01092     printf( "\t%s\t: ", tag );
01093     switch ( hatch ) {
01094     case HS_HORIZONTAL: printf( "HS_HORIZONTAL" ); break;
01095     case HS_VERTICAL: printf( "HS_VERTICAL" ); break;
01096     case HS_FDIAGONAL: printf( "HS_FDIAGONAL" ); break;
01097     case HS_BDIAGONAL: printf( "HS_BDIAGONAL" ); break;
01098     case HS_CROSS: printf( "HS_CROSS" ); break;
01099     case HS_DIAGCROSS: printf( "HS_DIAGCROSS" ); break;
01100     default: printf( "unknown(%ld)", hatch );
01101     }
01102     printf( "\n" );
01103   }
01104 #endif
01105 
01112   enum OBJECTTYPE { O_METAFILEDEVICECONTEXT     = OBJ_METADC,
01113                     O_FONT                      = OBJ_FONT,
01114                     O_PEN                       = OBJ_PEN,
01115                     O_EXTPEN                    = OBJ_EXTPEN,
01116                     O_BRUSH                     = OBJ_BRUSH,
01117                     O_PALETTE                   = OBJ_PAL };
01118 #if 0
01119 
01122   static char* typStr ( OBJECTTYPE type )
01123   {
01124     switch (type) {
01125     case O_METAFILEDEVICECONTEXT:
01126       return "metafile device context";
01127     case O_FONT:
01128       return "font";
01129     case O_PEN:
01130       return "pen";
01131     case O_EXTPEN:
01132       return "extended pen";
01133     case O_BRUSH:
01134       return "brush";
01135     case O_PALETTE:
01136       return "palette";
01137     }
01138     return "unknown object";
01139   }
01140 #endif
01141 
01142 
01147   class OBJECT {
01148   public:
01149     HGDIOBJ handle;             
01150 
01151     virtual ~OBJECT () {}
01156     OBJECT ( void ) : handle( 0 ) {}
01160     virtual OBJECTTYPE getType ( void ) const = 0;
01161   };
01162 
01164 
01169   class GRAPHICSOBJECT : public OBJECT {
01170   public:
01172     virtual ~GRAPHICSOBJECT () {}
01177     std::map< HDC, HGDIOBJ > contexts;
01183     virtual METARECORD* newEMR ( HDC dc, HGDIOBJ handle ) = 0;
01184   };
01185 
01186   typedef METARECORD*(*METARECORDCTOR)(DATASTREAM&);
01187 
01188   class GLOBALOBJECTS {
01192     std::vector<OBJECT*> objects;
01193 
01200     std::map< DWORD, METARECORDCTOR > new_records;
01201 
01202   public:
01203     GLOBALOBJECTS ( void );
01204     ~GLOBALOBJECTS ( void );
01205     HGDIOBJ add ( OBJECT* object );
01206     OBJECT* find ( const HGDIOBJ handle );
01207     void remove ( const OBJECT* object );
01208 
01209     std::vector<EMF::OBJECT*>::const_iterator begin ( void ) const
01210     { return objects.begin(); }
01211     std::vector<EMF::OBJECT*>::const_iterator end ( void ) const
01212     { return objects.end(); }
01213 
01214     METARECORDCTOR newRecord ( DWORD iType ) const;
01215 
01216     static EMF::METARECORD* new_eof ( DATASTREAM& ds );
01217     static EMF::METARECORD* new_setviewportorgex ( DATASTREAM& ds );
01218     static EMF::METARECORD* new_setwindoworgex ( DATASTREAM& ds );
01219     static EMF::METARECORD* new_setviewportextex ( DATASTREAM& ds );
01220     static EMF::METARECORD* new_setwindowextex ( DATASTREAM& ds );
01221     static EMF::METARECORD* new_scaleviewportextex ( DATASTREAM& ds );
01222     static EMF::METARECORD* new_scalewindowextex ( DATASTREAM& ds );
01223     static EMF::METARECORD* new_modifyworldtransform ( DATASTREAM& ds );
01224     static EMF::METARECORD* new_setworldtransform ( DATASTREAM& ds );
01225     static EMF::METARECORD* new_settextalign ( DATASTREAM& ds );
01226     static EMF::METARECORD* new_settextcolor ( DATASTREAM& ds );
01227     static EMF::METARECORD* new_setbkcolor ( DATASTREAM& ds );
01228     static EMF::METARECORD* new_setbkmode ( DATASTREAM& ds );
01229     static EMF::METARECORD* new_setpolyfillmode ( DATASTREAM& ds );
01230     static EMF::METARECORD* new_setmapmode ( DATASTREAM& ds );
01231     static EMF::METARECORD* new_selectobject ( DATASTREAM& ds );
01232     static EMF::METARECORD* new_deleteobject ( DATASTREAM& ds );
01233     static EMF::METARECORD* new_movetoex ( DATASTREAM& ds );
01234     static EMF::METARECORD* new_lineto ( DATASTREAM& ds );
01235     static EMF::METARECORD* new_arc ( DATASTREAM& ds );
01236     static EMF::METARECORD* new_arcto ( DATASTREAM& ds );
01237     static EMF::METARECORD* new_rectangle ( DATASTREAM& ds );
01238     static EMF::METARECORD* new_ellipse ( DATASTREAM& ds );
01239     static EMF::METARECORD* new_polyline ( DATASTREAM& ds );
01240     static EMF::METARECORD* new_polyline16 ( DATASTREAM& ds );
01241     static EMF::METARECORD* new_polygon ( DATASTREAM& ds );
01242     static EMF::METARECORD* new_polygon16 ( DATASTREAM& ds );
01243     static EMF::METARECORD* new_polypolygon ( DATASTREAM& ds );
01244     static EMF::METARECORD* new_polypolygon16 ( DATASTREAM& ds );
01245     static EMF::METARECORD* new_polybezier ( DATASTREAM& ds );
01246     static EMF::METARECORD* new_polybezier16 ( DATASTREAM& ds );
01247     static EMF::METARECORD* new_polybezierto ( DATASTREAM& ds );
01248     static EMF::METARECORD* new_polybezierto16 ( DATASTREAM& ds );
01249     static EMF::METARECORD* new_polylineto ( DATASTREAM& ds );
01250     static EMF::METARECORD* new_polylineto16 ( DATASTREAM& ds );
01251     static EMF::METARECORD* new_exttextouta ( DATASTREAM& ds );
01252     static EMF::METARECORD* new_setpixelv ( DATASTREAM& ds );
01253     static EMF::METARECORD* new_createpen ( DATASTREAM& ds );
01254     static EMF::METARECORD* new_extcreatepen ( DATASTREAM& ds );
01255     static EMF::METARECORD* new_createbrushindirect ( DATASTREAM& ds );
01256     static EMF::METARECORD* new_extcreatefontindirectw ( DATASTREAM& ds );
01257     static EMF::METARECORD* new_fillpath ( DATASTREAM& ds );
01258     static EMF::METARECORD* new_strokepath ( DATASTREAM& ds );
01259     static EMF::METARECORD* new_strokeandfillpath ( DATASTREAM& ds );
01260     static EMF::METARECORD* new_beginpath ( DATASTREAM& ds );
01261     static EMF::METARECORD* new_endpath ( DATASTREAM& ds );
01262     static EMF::METARECORD* new_closefigure ( DATASTREAM& ds );
01263     static EMF::METARECORD* new_savedc ( DATASTREAM& ds );
01264     static EMF::METARECORD* new_restoredc ( DATASTREAM& ds );
01265     static EMF::METARECORD* new_setmetargn ( DATASTREAM& ds );
01266   };
01267 
01268   extern GLOBALOBJECTS globalObjects;
01269 
01271 
01277   class ENHMETAHEADER : public METARECORD, public ::ENHMETAHEADER {
01278 
01279     LPWSTR description_w;
01280     int description_size;
01281 
01282   public:
01289     ENHMETAHEADER ( LPCWSTR description = 0 )
01290       : description_w( 0 ), description_size( 0 )
01291     {
01292       iType = EMR_HEADER;
01293       nSize = sizeof( ::ENHMETAHEADER );
01294 
01295       // Compute the bounds
01296       RECTL default_bounds = { 0, 0, 0, 0 };
01297       rclBounds = default_bounds;
01298       RECTL default_frame = { 0, 0, 0, 0 };
01299       rclFrame = default_frame;
01300       dSignature = ENHMETA_SIGNATURE;
01301       nVersion = 0x10000;
01302       nBytes = nSize;
01303       nRecords = 1;
01304       nHandles = 0;
01305       sReserved = 0;
01306       nDescription = 0;
01307       offDescription = 0;
01308       nPalEntries = 0;
01309       szlDevice.cx = XMAX_PIXELS;
01310       szlDevice.cy = YMAX_PIXELS;
01311       szlMillimeters.cx = XMAX_MM;
01312       szlMillimeters.cy = YMAX_MM;
01313       //
01314       cbPixelFormat = 0;
01315       offPixelFormat = 0;
01316       bOpenGL = FALSE;
01317       //
01318 #if 1
01319       szlMicrometers.cx = 1000 * szlMillimeters.cx;
01320       szlMicrometers.cy = 1000 * szlMillimeters.cy;
01321 #endif
01322       if ( description ) {
01323         // Count the number of characters in the description
01324         int description_count = 0, nulls = 0;
01325         LPCWSTR description_p = description;
01326         while ( nulls < 3 ) {
01327           description_count++;
01328           if ( (*description_p++) == 0 ) nulls++;
01329         }
01330 
01331         // Make sure that the TOTAL record length will be a multiple of 4
01332 
01333         int record_size = ROUND_TO_LONG( sizeof( ::ENHMETAHEADER ) +
01334                                          sizeof( WCHAR ) * description_count );
01335         description_size =
01336           (record_size - sizeof( ::ENHMETAHEADER )) / sizeof( WCHAR );
01337 
01338         description_w = new WCHAR[ description_size ];
01339 
01340         memset( description_w, 0, sizeof(WCHAR) * description_size );
01341 
01342         for ( int i=0; i<description_count; i++ )
01343           description_w[i] = *description++;
01344 
01345         nSize = nBytes = record_size;
01346         nDescription = description_count;
01347         offDescription = sizeof( ::ENHMETAHEADER );
01348       }
01349     }
01350     
01354     ~ENHMETAHEADER ( )
01355     {
01356       if ( description_w ) delete[] description_w;
01357     }
01362     bool serialize ( DATASTREAM ds )
01363     {
01364       ds << iType << nSize
01365          << rclBounds << rclFrame
01366          << dSignature << nVersion << nBytes << nRecords << nHandles << sReserved
01367          << nDescription << offDescription << nPalEntries
01368          << szlDevice << szlMillimeters
01369          << cbPixelFormat << offPixelFormat << bOpenGL
01370 #if 1
01371          << szlMicrometers
01372 #endif
01373          << WCHARSTR( description_w, description_size );
01374       return true;
01375     }
01379     bool unserialize ( DATASTREAM ds )
01380     {
01381       ds >> iType >> nSize
01382          >> rclBounds >> rclFrame
01383          >> dSignature >> nVersion >> nBytes >> nRecords >> nHandles >> sReserved
01384          >> nDescription >> offDescription >> nPalEntries
01385          >> szlDevice >> szlMillimeters;
01386 
01387       // Some elements of the metafile header were added at later dates
01388 
01389 #define OffsetOf( a, b ) ((unsigned int)(((char*)&(((::ENHMETAHEADER*)a)->b)) - \
01390 (char*)((::ENHMETAHEADER*)a)))
01391 #if 1
01392       if ( OffsetOf( this, szlMicrometers ) <= offDescription )
01393         ds >> cbPixelFormat >> offPixelFormat >> bOpenGL;
01394 #else
01395       if ( sizeof(::ENHMETAHEADER) <= offDescription )
01396         ds >> cbPixelFormat >> offPixelFormat >> bOpenGL;
01397 #endif
01398 #undef OffsetOf
01399 #if 1
01400       if ( sizeof(::ENHMETAHEADER) <= offDescription )
01401         ds >> szlMicrometers;
01402 #endif
01403       // Should now probably check that the offset is correct...
01404 
01405       description_size = ( nSize - offDescription ) / sizeof(WCHAR);
01406       description_w = new WCHAR[ description_size ];
01407 
01408       WCHARSTR description( description_w, description_size );
01409 
01410       ds >> description;
01411 
01412       return true;
01413     }
01417     int size ( void ) const { return nSize; }
01423     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC /*dc*/ ) const
01424     {
01425       // Actually handled by the destination device context.
01426     }
01427 #ifdef ENABLE_EDITING
01428 
01431     void edit ( void ) const
01432     {
01433       printf( "*HEADER*\n" );
01434       printf( "\tiType\t\t\t: %ld\n", iType );
01435       printf( "\tnSize\t\t\t: %ld\n", nSize );
01436       edit_rectl( "rclBounds\t", rclBounds );
01437       edit_rectl( "rclFrame\t", rclFrame );
01438       printf( "\tdSignature\t\t: %.4s\n", (const char*)&dSignature );
01439       printf( "\tnVersion\t\t: 0x%x\n", (unsigned int)nVersion );
01440       printf( "\tnBytes\t\t\t: %ld\n", nBytes );
01441       printf( "\tnRecords\t\t: %ld\n", nRecords );
01442       printf( "\tnHandles\t\t: %d\n", nHandles );
01443       printf( "\tnDescription\t\t: %ld\n", nDescription );
01444       printf( "\toffDescription\t\t: %ld\n", offDescription );
01445       printf( "\tnPalEntries\t\t: %ld\n", nPalEntries );
01446       edit_sizel( "szlDevice\t", szlDevice );
01447       edit_sizel( "szlMillimeters\t", szlMillimeters );
01448 
01449       /* Make a crude guess as to the age of this file */
01450 #define OffsetOf( a, b ) ((unsigned int)(((const char*)&(((const ::ENHMETAHEADER*)a)->b)) - \
01451 (const char*)((const ::ENHMETAHEADER*)a)))
01452 
01453       if ( OffsetOf( this, cbPixelFormat ) <= offDescription ) {
01454         printf( "\tcbPixelFormat\t\t: %ld\n", cbPixelFormat );
01455         printf( "\toffPixelFormat\t\t: %ld\n", offPixelFormat );
01456         printf( "\tbOpenGL\t\t\t: %ld\n", bOpenGL );
01457 #if 1
01458         if ( sizeof(::ENHMETAHEADER) <= offDescription ) {
01459           edit_sizel( "szlMicrometers\t", szlMicrometers );
01460         }
01461 #endif
01462       }
01463 
01464 #undef OffsetOf
01465 
01466       if ( nDescription != 0 ) {
01467 
01468         wchar_t last_w = 0;
01469         WCHAR* description = description_w;
01470 
01471         printf( "\tDescription:" );
01472 
01473         for ( DWORD i = 0; i < nDescription; i++ ) {
01474 
01475           wchar_t w = *description++; /* This is not true, really. UNICODE is not
01476                                        * glibc's wide character representation */
01477 
01478           if ( w != 0 ) {
01479             if ( last_w == 0 ) printf( "\n\t\t" );
01480             putchar( w );
01481           }
01482           
01483           last_w = w;
01484         }
01485         printf( "\n" );
01486       }
01487     }
01488 #endif /* ENABLE_EDITING */
01489   };
01490 
01492 
01497   class EMREOF : public METARECORD, ::EMREOF {
01498   public:
01502     EMREOF ( void )
01503     {
01504       emr.iType = EMR_EOF;
01505       emr.nSize = sizeof( ::EMREOF );
01506       nPalEntries = 0;
01507       offPalEntries = 0;
01508       nSizeLast = 0;
01509     }
01510 
01515     EMREOF ( DATASTREAM& ds )
01516     {
01517       ds >> emr >> nPalEntries >> offPalEntries >> nSizeLast;
01518     }
01519 
01523     bool serialize ( DATASTREAM ds )
01524     {
01525       ds << emr << nPalEntries << offPalEntries << nSizeLast;
01526       return true;
01527     }
01531     int size ( void ) const { return emr.nSize; }
01537     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC /*dc*/ ) const
01538     {
01539       // Actually handled by the destination device context.
01540     }
01541 #ifdef ENABLE_EDITING
01542 
01545     void edit ( void ) const
01546     {
01547       printf( "*EOF*\n" );
01548     }
01549 #endif /* ENABLE_EDITING */
01550   };
01551 
01553 
01558   class EMRSETVIEWPORTORGEX : public METARECORD, ::EMRSETVIEWPORTORGEX {
01559   public:
01564     EMRSETVIEWPORTORGEX ( INT x, INT y )
01565     {
01566       emr.iType = EMR_SETVIEWPORTORGEX;
01567       emr.nSize = sizeof( ::EMRSETVIEWPORTORGEX );
01568       ptlOrigin.x = x;
01569       ptlOrigin.y = y;
01570     }
01575     EMRSETVIEWPORTORGEX ( DATASTREAM& ds )
01576     {
01577       ds >> emr >> ptlOrigin;
01578     }
01582     bool serialize ( DATASTREAM ds )
01583     {
01584       ds << emr << ptlOrigin;
01585       return true;
01586     }
01590     int size ( void ) const { return emr.nSize; }
01596     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01597     {
01598       SetViewportOrgEx( dc, ptlOrigin.x, ptlOrigin.y, 0 );
01599     }
01600 #ifdef ENABLE_EDITING
01601 
01604     void edit ( void ) const
01605     {
01606       printf( "*SETVIEWPORTORGEX*\n" );
01607       edit_pointl( "ptlOrigin", ptlOrigin );
01608     }
01609 #endif /* ENABLE_EDITING */
01610   };
01611 
01613 
01620   class EMRSETWINDOWORGEX : public METARECORD, ::EMRSETWINDOWORGEX {
01621   public:
01626     EMRSETWINDOWORGEX ( INT x, INT y )
01627     {
01628       emr.iType = EMR_SETWINDOWORGEX;
01629       emr.nSize = sizeof( ::EMRSETWINDOWORGEX );
01630       ptlOrigin.x = x;
01631       ptlOrigin.y = y;
01632     }
01637     EMRSETWINDOWORGEX ( DATASTREAM& ds )
01638     {
01639       ds >> emr >> ptlOrigin;
01640     }
01644     bool serialize ( DATASTREAM ds )
01645     {
01646       ds << emr << ptlOrigin;
01647       return true;
01648     }
01652     int size ( void ) const { return emr.nSize; }
01658     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01659     {
01660       SetWindowOrgEx( dc, ptlOrigin.x, ptlOrigin.y, 0 );
01661     }
01662 #ifdef ENABLE_EDITING
01663 
01666     void edit ( void ) const
01667     {
01668       printf( "*SETWINDOWORGEX*\n" );
01669       edit_pointl( "ptlOrigin", ptlOrigin );
01670     }
01671 #endif /* ENABLE_EDITING */
01672   };
01673 
01675 
01680   class EMRSETVIEWPORTEXTEX : public METARECORD, ::EMRSETVIEWPORTEXTEX {
01681   public:
01686     EMRSETVIEWPORTEXTEX ( INT cx, INT cy )
01687     {
01688       emr.iType = EMR_SETVIEWPORTEXTEX;
01689       emr.nSize = sizeof( ::EMRSETVIEWPORTEXTEX );
01690       szlExtent.cx = cx;
01691       szlExtent.cy = cy;
01692     }
01697     EMRSETVIEWPORTEXTEX ( DATASTREAM& ds )
01698     {
01699       ds >> emr >> szlExtent;
01700     }
01704     bool serialize ( DATASTREAM ds )
01705     {
01706       ds << emr << szlExtent;
01707       return true;
01708     }
01712     int size ( void ) const { return emr.nSize; }
01718     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01719     {
01720       SetViewportExtEx( dc, szlExtent.cx, szlExtent.cy, 0 );
01721     }
01722 #ifdef ENABLE_EDITING
01723 
01726     void edit ( void ) const
01727     {
01728       printf( "*SETVIEWPORTEXTEX*\n" );
01729       edit_sizel( "szlExtent", szlExtent );
01730     }
01731 #endif /* ENABLE_EDITING */
01732   };
01733 
01735 
01740   class EMRSCALEVIEWPORTEXTEX : public METARECORD, ::EMRSCALEVIEWPORTEXTEX {
01741   public:
01748     EMRSCALEVIEWPORTEXTEX ( LONG x_num, LONG x_den, LONG y_num, LONG y_den )
01749     {
01750       emr.iType = EMR_SCALEVIEWPORTEXTEX;
01751       emr.nSize = sizeof( ::EMRSCALEVIEWPORTEXTEX );
01752       xNum = x_num;
01753       xDenom = x_den;
01754       yNum = y_num;
01755       yDenom = y_den;
01756     }
01761     EMRSCALEVIEWPORTEXTEX ( DATASTREAM& ds )
01762     {
01763       ds >> emr >> xNum >> xDenom >> yNum >> yDenom;
01764     }
01768     bool serialize ( DATASTREAM ds )
01769     {
01770       ds << emr << xNum << xDenom << yNum << yDenom;
01771       return true;
01772     }
01776     int size ( void ) const { return emr.nSize; }
01782     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01783     {
01784       ScaleViewportExtEx( dc, xNum, xDenom, yNum, yDenom, 0 );
01785     }
01786 #ifdef ENABLE_EDITING
01787 
01790     void edit ( void ) const
01791     {
01792       printf( "*SCALEVIEWPORTEXTEX*\n" );
01793       printf( "\txNum\t: %ld\n", xNum );
01794       printf( "\txDenom\t: %ld\n", xDenom );
01795       printf( "\tyNum\t: %ld\n", yNum );
01796       printf( "\tyDenom\t: %ld\n", yDenom );
01797     }
01798 #endif /* ENABLE_EDITING */
01799   };
01800 
01802 
01807   class EMRSETWINDOWEXTEX : public METARECORD, ::EMRSETWINDOWEXTEX {
01808   public:
01813     EMRSETWINDOWEXTEX ( INT cx, INT cy )
01814     {
01815       emr.iType = EMR_SETWINDOWEXTEX;
01816       emr.nSize = sizeof( ::EMRSETWINDOWEXTEX );
01817       szlExtent.cx = cx;
01818       szlExtent.cy = cy;
01819     }
01824     EMRSETWINDOWEXTEX ( DATASTREAM& ds )
01825     {
01826       ds >> emr >> szlExtent;
01827     }
01831     bool serialize ( DATASTREAM ds )
01832     {
01833       ds << emr << szlExtent;
01834       return true;
01835     }
01839     int size ( void ) const { return emr.nSize; }
01845     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01846     {
01847       SetWindowExtEx( dc, szlExtent.cx, szlExtent.cy, 0 );
01848     }
01849 #ifdef ENABLE_EDITING
01850 
01853     void edit ( void ) const
01854     {
01855       printf( "*SETWINDOWEXTEX*\n" );
01856       edit_sizel( "szlExtent", szlExtent );
01857     }
01858 #endif /* ENABLE_EDITING */
01859   };
01860 
01862 
01867   class EMRSCALEWINDOWEXTEX : public METARECORD, ::EMRSCALEWINDOWEXTEX {
01868   public:
01875     EMRSCALEWINDOWEXTEX ( LONG x_num, LONG x_den, LONG y_num, LONG y_den )
01876     {
01877       emr.iType = EMR_SCALEWINDOWEXTEX;
01878       emr.nSize = sizeof( ::EMRSCALEWINDOWEXTEX );
01879       xNum = x_num;
01880       xDenom = x_den;
01881       yNum = y_num;
01882       yDenom = y_den;
01883     }
01888     EMRSCALEWINDOWEXTEX ( DATASTREAM& ds )
01889     {
01890       ds >> emr >> xNum >> xDenom >> yNum >> yDenom;
01891     }
01895     bool serialize ( DATASTREAM ds )
01896     {
01897       ds << emr << xNum << xDenom << yNum << yDenom;
01898       return true;
01899     }
01903     int size ( void ) const { return emr.nSize; }
01909     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01910     {
01911       ScaleWindowExtEx( dc, xNum, xDenom, yNum, yDenom, 0 );
01912     }
01913 #ifdef ENABLE_EDITING
01914 
01917     void edit ( void ) const
01918     {
01919       printf( "*SCALEWINDOWEXTEX*\n" );
01920       printf( "\txNum\t: %ld\n", xNum );
01921       printf( "\txDenom\t: %ld\n", xDenom );
01922       printf( "\tyNum\t: %ld\n", yNum );
01923       printf( "\tyDenom\t: %ld\n", yDenom );
01924     }
01925 #endif /* ENABLE_EDITING */
01926   };
01927 
01929 
01935   class EMRMODIFYWORLDTRANSFORM : public METARECORD, ::EMRMODIFYWORLDTRANSFORM {
01936   public:
01942     EMRMODIFYWORLDTRANSFORM ( const XFORM* transform, DWORD mode )
01943     {
01944       emr.iType = EMR_MODIFYWORLDTRANSFORM;
01945       emr.nSize = sizeof( ::EMRMODIFYWORLDTRANSFORM );
01946       xform = *transform;
01947       iMode = mode;
01948     }
01953     EMRMODIFYWORLDTRANSFORM ( DATASTREAM& ds )
01954     {
01955       ds >> emr >> xform >> iMode;
01956     }
01960     bool serialize ( DATASTREAM ds )
01961     {
01962       ds << emr << xform << iMode;
01963       return true;
01964     }
01968     int size ( void ) const { return emr.nSize; }
01974     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01975     {
01976       ModifyWorldTransform( dc, &xform, iMode );
01977     }
01978 #ifdef ENABLE_EDITING
01979 
01982     void edit ( void ) const
01983     {
01984       printf( "*MODIFYWORLDTRANSFORM*\n" );
01985       edit_xform( "xform", xform );
01986       printf( "\tiMode\t\t: " );
01987       switch ( iMode ) {
01988       case MWT_IDENTITY: printf( "MWT_IDENTITY\n" ); break;
01989       case MWT_LEFTMULTIPLY: printf( "MWT_LEFTMULTIPLY\n" ); break;
01990       case MWT_RIGHTMULTIPLY: printf( "MWT_RIGHTMULTIPLY\n" ); break;
01991       default: printf( "unknown(%ld)\n", iMode );
01992       }
01993     }
01994 #endif /* ENABLE_EDITING */
01995   };
01996 
01998 
02004   class EMRSETWORLDTRANSFORM : public METARECORD, ::EMRSETWORLDTRANSFORM {
02005   public:
02009     EMRSETWORLDTRANSFORM ( const XFORM* transform )
02010     {
02011       emr.iType = EMR_SETWORLDTRANSFORM;
02012       emr.nSize = sizeof( ::EMRSETWORLDTRANSFORM );
02013       xform = *transform;
02014     }
02019     EMRSETWORLDTRANSFORM ( DATASTREAM& ds )
02020     {
02021       ds >> emr >> xform;
02022     }
02026     bool serialize ( DATASTREAM ds )
02027     {
02028       ds << emr << xform;
02029       return true;
02030     }
02034     int size ( void ) const { return emr.nSize; }
02040     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02041     {
02042       SetWorldTransform( dc, &xform );
02043     }
02044 #ifdef ENABLE_EDITING
02045 
02048     void edit ( void ) const
02049     {
02050       printf( "*SETWORLDTRANSFORM*\n" );
02051       edit_xform( "xform", xform );
02052     }
02053 #endif /* ENABLE_EDITING */
02054   };
02055 
02057 
02060   class EMRSETTEXTALIGN : public METARECORD, ::EMRSETTEXTALIGN {
02061   public:
02065     EMRSETTEXTALIGN ( UINT mode )
02066     {
02067       emr.iType = EMR_SETTEXTALIGN;
02068       emr.nSize = sizeof( ::EMRSETTEXTALIGN );
02069       iMode = mode;
02070     }
02075     EMRSETTEXTALIGN ( DATASTREAM& ds )
02076     {
02077       ds >> emr >> iMode;
02078     }
02082     bool serialize ( DATASTREAM ds )
02083     {
02084       ds << emr << iMode;
02085       return true;
02086     }
02090     int size ( void ) const { return emr.nSize; }
02096     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02097     {
02098       SetTextAlign( dc, iMode );
02099     }
02100 #ifdef ENABLE_EDITING
02101 
02104     void edit ( void ) const
02105     {
02106       unsigned int known_bits = TA_BASELINE+TA_CENTER+TA_UPDATECP+TA_RTLREADING;
02107       unsigned int unknown_bits = ~known_bits;
02108 
02109       printf( "*SETTEXTALIGN*\n" );
02110       printf( "\tiMode\t: " );
02111       if ( iMode & TA_UPDATECP )
02112         printf( "TA_UPDATECP" );
02113       else
02114         printf( "TA_NOUPDATECP" );
02115       if ( iMode & TA_CENTER )
02116         printf( " | TA_CENTER" );
02117       else if ( iMode & TA_RIGHT )
02118         printf( " | TA_RIGHT" );
02119       else
02120         printf( " | TA_LEFT" );
02121       if ( iMode & TA_BASELINE )
02122         printf( " | TA_BASELINE" );
02123       else if ( iMode & TA_BOTTOM )
02124         printf( " | TA_BOTTOM" );
02125       else
02126         printf( " | TA_TOP" );
02127       if ( iMode & TA_RTLREADING )
02128         printf( " | TA_RTLREADING" );
02129       if ( iMode & unknown_bits )
02130         printf( " | unknown bits(0x%lx)", iMode & unknown_bits );
02131       printf( "\n" );
02132     }
02133 #endif /* ENABLE_EDITING */
02134   };
02135 
02137 
02140   class EMRSETTEXTCOLOR : public METARECORD, ::EMRSETTEXTCOLOR {
02141   public:
02145     EMRSETTEXTCOLOR ( COLORREF color )
02146     {
02147       emr.iType = EMR_SETTEXTCOLOR;
02148       emr.nSize = sizeof( ::EMRSETTEXTCOLOR );
02149       crColor = color;
02150     }
02155     EMRSETTEXTCOLOR ( DATASTREAM& ds )
02156     {
02157       ds >> emr >> crColor;
02158     }
02162     bool serialize ( DATASTREAM ds )
02163     {
02164       ds << emr << crColor;
02165       return true;
02166     }
02170     int size ( void ) const { return emr.nSize; }
02176     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02177     {
02178       SetTextColor( dc, crColor );
02179     }
02180 #ifdef ENABLE_EDITING
02181 
02184     void edit ( void ) const
02185     {
02186       printf( "*SETTEXTCOLOR*\n" );
02187       edit_color( "crColor", crColor );
02188     }
02189 #endif /* ENABLE_EDITING */
02190   };
02191 
02193 
02196   class EMRSETBKCOLOR : public METARECORD, ::EMRSETBKCOLOR {
02197   public:
02201     EMRSETBKCOLOR ( COLORREF color )
02202     {
02203       emr.iType = EMR_SETBKCOLOR;
02204       emr.nSize = sizeof( ::EMRSETBKCOLOR );
02205       crColor = color;
02206     }
02211     EMRSETBKCOLOR ( DATASTREAM& ds )
02212     {
02213       ds >> emr >> crColor;
02214     }
02218     bool serialize ( DATASTREAM ds )
02219     {
02220       ds << emr << crColor;
02221       return true;
02222     }
02226     int size ( void ) const { return emr.nSize; }
02232     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02233     {
02234       SetBkColor( dc, crColor );
02235     }
02236 #ifdef ENABLE_EDITING
02237 
02240     void edit ( void ) const
02241     {
02242       printf( "*SETBKCOLOR*\n" );
02243       edit_color( "crColor", crColor );
02244     }
02245 #endif /* ENABLE_EDITING */
02246   };
02247 
02249 
02253   class EMRSETBKMODE : public METARECORD, ::EMRSETBKMODE {
02254   public:
02258     EMRSETBKMODE ( DWORD mode )
02259     {
02260       emr.iType = EMR_SETBKMODE;
02261       emr.nSize = sizeof( ::EMRSETBKMODE );
02262       iMode = mode;
02263     }
02268     EMRSETBKMODE ( DATASTREAM& ds )
02269     {
02270       ds >> emr >> iMode;
02271     }
02275     bool serialize ( DATASTREAM ds )
02276     {
02277       ds << emr << iMode;
02278       return true;
02279     }
02283     int size ( void ) const { return emr.nSize; }
02289     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02290     {
02291       SetBkMode( dc, iMode );
02292     }
02293 #ifdef ENABLE_EDITING
02294 
02297     void edit ( void ) const
02298     {
02299       printf( "*SETBKMODE*\n" );
02300       printf( "\tiMode\t: " );
02301       switch ( iMode ) {
02302       case TRANSPARENT: printf( "TRANSPARENT\n" ); break;
02303       case OPAQUE: printf( "OPAQUE\n" ); break;
02304       default: printf( "unknown(%ld)\n", iMode );
02305       }
02306     }
02307 #endif /* ENABLE_EDITING */
02308   };
02309 
02311 
02314   class EMRSETPOLYFILLMODE : public METARECORD, ::EMRSETPOLYFILLMODE {
02315   public:
02319     EMRSETPOLYFILLMODE ( DWORD mode )
02320     {
02321       emr.iType = EMR_SETPOLYFILLMODE;
02322       emr.nSize = sizeof( ::EMRSETPOLYFILLMODE );
02323       iMode = mode;
02324     }
02329     EMRSETPOLYFILLMODE ( DATASTREAM& ds )
02330     {
02331       ds >> emr >> iMode;
02332     }
02336     bool serialize ( DATASTREAM ds )
02337     {
02338       ds << emr << iMode;
02339       return true;
02340     }
02344     int size ( void ) const { return emr.nSize; }
02350     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02351     {
02352       SetPolyFillMode( dc, iMode );
02353     }
02354 #ifdef ENABLE_EDITING
02355 
02358     void edit ( void ) const
02359     {
02360       printf( "*SETPOLYFILLMODE*\n" );
02361       printf( "\tiMode: " );
02362       switch ( iMode ) {
02363       case ALTERNATE: printf( "ALTERNATE\n" ); break;
02364       case WINDING: printf( "WINDING\n" ); break;
02365       default: printf( "unknown(%ld)\n", iMode );
02366       }
02367     }
02368 #endif /* ENABLE_EDITING */
02369   };
02370 
02372 
02376   class EMRSETMAPMODE : public METARECORD, ::EMRSETMAPMODE {
02377   public:
02381     EMRSETMAPMODE ( DWORD mode )
02382     {
02383       emr.iType = EMR_SETMAPMODE;
02384       emr.nSize = sizeof( ::EMRSETMAPMODE );
02385       iMode = mode;
02386     }
02391     EMRSETMAPMODE ( DATASTREAM& ds )
02392     {
02393       ds >> emr >> iMode;
02394     }
02398     bool serialize ( DATASTREAM ds )
02399     {
02400       ds << emr << iMode;
02401       return true;
02402     }
02406     int size ( void ) const { return emr.nSize; }
02412     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02413     {
02414       SetMapMode( dc, iMode );
02415     }
02416 #ifdef ENABLE_EDITING
02417 
02420     void edit ( void ) const
02421     {
02422       printf( "*SETMAPMODE*\n" );
02423       printf( "\tiMode\t: " );
02424       switch ( iMode ) {
02425       case MM_TEXT: printf( "MM_TEXT\n" ); break;
02426       case MM_LOMETRIC: printf( "MM_LOMETRIC\n" ); break;
02427       case MM_HIMETRIC: printf( "MM_HIMETRIC\n" ); break;
02428       case MM_LOENGLISH: printf( "MM_LOENGLISH\n" ); break;
02429       case MM_HIENGLISH: printf( "MM_HIENGLISH\n" ); break;
02430       case MM_TWIPS: printf( "MM_TWIPS\n" ); break;
02431       case MM_ISOTROPIC: printf( "MM_ISOTROPIC\n" ); break;
02432       case MM_ANISOTROPIC: printf( "MM_ANISOTROPIC\n" ); break;
02433       default: printf( "unknown(%ld)\n", iMode );
02434       }
02435     }
02436 #endif /* ENABLE_EDITING */
02437   };
02438 
02440 
02443   class EMRSELECTOBJECT : public METARECORD, ::EMRSELECTOBJECT {
02444   public:
02448     EMRSELECTOBJECT ( HGDIOBJ object )
02449     {
02450       emr.iType = EMR_SELECTOBJECT;
02451       emr.nSize = sizeof( ::EMRSELECTOBJECT );
02452       ihObject = object;
02453     }
02458     EMRSELECTOBJECT ( DATASTREAM& ds )
02459     {
02460       ds >> emr >> ihObject;
02461     }
02465     bool serialize ( DATASTREAM ds )
02466     {
02467       ds << emr << ihObject;
02468       return true;
02469     }
02473     int size ( void ) const { return emr.nSize; }
02479     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
02480 #ifdef ENABLE_EDITING
02481 
02484     void edit ( void ) const
02485     {
02486       printf( "*SELECTOBJECT*\n" );
02487       printf( "\tihObject\t: 0x%lx\n", ihObject );
02488     }
02489 #endif /* ENABLE_EDITING */
02490   };
02491 
02493 
02496   class EMRDELETEOBJECT : public METARECORD, ::EMRDELETEOBJECT {
02497   public:
02501     EMRDELETEOBJECT ( HGDIOBJ object )
02502     {
02503       emr.iType = EMR_DELETEOBJECT;
02504       emr.nSize = sizeof( ::EMRDELETEOBJECT );
02505       ihObject = object;
02506     }
02511     EMRDELETEOBJECT ( DATASTREAM& ds )
02512     {
02513       ds >> emr >> ihObject;
02514     }
02518     bool serialize ( DATASTREAM ds )
02519     {
02520       ds << emr << ihObject;
02521       return true;
02522     }
02526     int size ( void ) const { return emr.nSize; }
02532     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
02533 #ifdef ENABLE_EDITING
02534 
02537     void edit ( void ) const
02538     {
02539       printf( "*DELETEOBJECT*\n" );
02540       printf( "\tihObject\t: 0x%lx\n", ihObject );
02541     }
02542 #endif /* ENABLE_EDITING */
02543   };
02544 
02546 
02549   class EMRMOVETOEX : public METARECORD, ::EMRMOVETOEX {
02550   public:
02555     EMRMOVETOEX ( INT x, INT y )
02556     {
02557       emr.iType = EMR_MOVETOEX;
02558       emr.nSize = sizeof( ::EMRMOVETOEX );
02559       ptl.x = x;
02560       ptl.y = y;
02561     }
02566     EMRMOVETOEX ( DATASTREAM& ds )
02567     {
02568       ds >> emr >> ptl;
02569     }
02573     bool serialize ( DATASTREAM ds )
02574     {
02575       ds << emr << ptl;
02576       return true;
02577     }
02581     int size ( void ) const { return emr.nSize; }
02587     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02588     {
02589       MoveToEx( dc,  ptl.x, ptl.y, 0 );
02590     }
02591 #ifdef ENABLE_EDITING
02592 
02595     void edit ( void ) const
02596     {
02597       printf( "*MOVETOEX*\n" );
02598       edit_pointl( "ptl", ptl );
02599     }
02600 #endif /* ENABLE_EDITING */
02601   };
02602 
02604 
02607   class EMRLINETO : public METARECORD, ::EMRLINETO {
02608   public:
02613     EMRLINETO ( INT x, INT y )
02614     {
02615       emr.iType = EMR_LINETO;
02616       emr.nSize = sizeof( ::EMRLINETO );
02617       ptl.x = x;
02618       ptl.y = y;
02619     }
02624     EMRLINETO ( DATASTREAM& ds )
02625     {
02626       ds >> emr >> ptl;
02627     }
02631     bool serialize ( DATASTREAM ds )
02632     {
02633       ds << emr << ptl;
02634       return true;
02635     }
02639     int size ( void ) const { return emr.nSize; }
02645     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02646     {
02647       LineTo( dc,  ptl.x, ptl.y );
02648     }
02649 #ifdef ENABLE_EDITING
02650 
02653     void edit ( void ) const
02654     {
02655       printf( "*LINETO*\n" );
02656       edit_pointl( "ptl", ptl );
02657     }
02658 #endif /* ENABLE_EDITING */
02659   };
02660 
02662 
02665   class EMRARC : public METARECORD, ::EMRARC {
02666   public:
02678     EMRARC ( INT left, INT top, INT right, INT bottom, INT xstart,
02679              INT ystart, INT xend, INT yend )
02680     {
02681       emr.iType = EMR_ARC;
02682       emr.nSize = sizeof( ::EMRARC );
02683       rclBox.left = left;
02684       rclBox.right = right;
02685       rclBox.bottom = bottom;
02686       rclBox.top = top;
02687       ptlStart.x = xstart;
02688       ptlStart.y = ystart;
02689       ptlEnd.x = xend;
02690       ptlEnd.y = yend;
02691     }
02696     EMRARC ( DATASTREAM& ds )
02697     {
02698       ds >> emr >> rclBox >> ptlStart >> ptlEnd;
02699     }
02703     bool serialize ( DATASTREAM ds )
02704     {
02705       ds << emr << rclBox << ptlStart << ptlEnd;
02706       return true;
02707     }
02711     int size ( void ) const { return emr.nSize; }
02717     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02718     {
02719       Arc( dc, rclBox.left, rclBox.top, rclBox.right, rclBox.bottom,
02720            ptlStart.x, ptlStart.y, ptlEnd.x, ptlEnd.y );
02721     }
02722 #ifdef ENABLE_EDITING
02723 
02726     void edit ( void ) const
02727     {
02728       printf( "*ARC*\n" );
02729       edit_rectl( "rclBox\t", rclBox );
02730       edit_pointl( "ptlStart", ptlStart );
02731       edit_pointl( "ptlEnd\t", ptlEnd );
02732     }
02733 #endif /* ENABLE_EDITING */
02734   };
02735 
02737 
02740   class EMRARCTO : public METARECORD, ::EMRARCTO {
02741   public:
02753     EMRARCTO ( INT left, INT top, INT right, INT bottom, INT xstart,
02754              INT ystart, INT xend, INT yend )
02755     {
02756       emr.iType = EMR_ARCTO;
02757       emr.nSize = sizeof( ::EMRARCTO );
02758       rclBox.left = left;
02759       rclBox.right = right;
02760       rclBox.bottom = bottom;
02761       rclBox.top = top;
02762       ptlStart.x = xstart;
02763       ptlStart.y = ystart;
02764       ptlEnd.x = xend;
02765       ptlEnd.y = yend;
02766     }
02771     EMRARCTO ( DATASTREAM& ds )
02772     {
02773       ds >> emr >> rclBox >> ptlStart >> ptlEnd;
02774     }
02778     bool serialize ( DATASTREAM ds )
02779     {
02780       ds << emr << rclBox << ptlStart << ptlEnd;
02781       return true;
02782     }
02786     int size ( void ) const { return emr.nSize; }
02792     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02793     {
02794       ArcTo( dc, rclBox.left, rclBox.top, rclBox.right, rclBox.bottom,
02795              ptlStart.x, ptlStart.y, ptlEnd.x, ptlEnd.y );
02796     }
02797 #ifdef ENABLE_EDITING
02798 
02801     void edit ( void ) const
02802     {
02803       printf( "*ARCTO*\n" );
02804       edit_rectl( "rclBox\t", rclBox );
02805       edit_pointl( "ptlStart", ptlStart );
02806       edit_pointl( "ptlEnd\t", ptlEnd );
02807     }
02808 #endif /* ENABLE_EDITING */
02809   };
02810 
02812 
02815   class EMRRECTANGLE : public METARECORD, ::EMRRECTANGLE {
02816   public:
02823     EMRRECTANGLE ( INT left, INT top, INT right, INT bottom )
02824     {
02825       emr.iType = EMR_RECTANGLE;
02826       emr.nSize = sizeof( ::EMRRECTANGLE );
02827       rclBox.left = left;
02828       rclBox.right = right;
02829       rclBox.bottom = bottom;
02830       rclBox.top = top;
02831     }
02836     EMRRECTANGLE ( DATASTREAM& ds )
02837     {
02838       ds >> emr >> rclBox;
02839     }
02843     bool serialize ( DATASTREAM ds )
02844     {
02845       ds << emr << rclBox;
02846       return true;
02847     }
02851     int size ( void ) const { return emr.nSize; }
02857     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02858     {
02859       Rectangle( dc, rclBox.left, rclBox.top, rclBox.right, rclBox.bottom );
02860     }
02861 #ifdef ENABLE_EDITING
02862 
02865     void edit ( void ) const
02866     {
02867       printf( "*RECTANGLE*\n" );
02868       edit_rectl( "rclBox", rclBox );
02869     }
02870 #endif /* ENABLE_EDITING */
02871   };
02872 
02874 
02877   class EMRELLIPSE : public METARECORD, ::EMRELLIPSE {
02878   public:
02886     EMRELLIPSE ( INT left, INT top, INT right, INT bottom )
02887     {
02888       emr.iType = EMR_ELLIPSE;
02889       emr.nSize = sizeof( ::EMRELLIPSE );
02890       rclBox.left = left;
02891       rclBox.right = right;
02892       rclBox.bottom = bottom;
02893       rclBox.top = top;
02894     }
02899     EMRELLIPSE ( DATASTREAM& ds )
02900     {
02901       ds >> emr >> rclBox;
02902     }
02906     bool serialize ( DATASTREAM ds )
02907     {
02908       ds << emr << rclBox;
02909       return true;
02910     }
02914     int size ( void ) const { return emr.nSize; }
02920     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02921     {
02922       Ellipse( dc, rclBox.left, rclBox.top, rclBox.right, rclBox.bottom );
02923     }
02924 #ifdef ENABLE_EDITING
02925 
02928     void edit ( void ) const
02929     {
02930       printf( "*ELLIPSE*\n" );
02931       edit_rectl( "rclBox", rclBox );
02932     }
02933 #endif /* ENABLE_EDITING */
02934   };
02935 
02937 
02940   class EMRPOLYLINE : public METARECORD, ::EMRPOLYLINE {
02941     POINTL* lpoints;
02942   public:
02948     EMRPOLYLINE ( const RECTL* bounds, const POINT* points, INT n )
02949     {
02950       cptl = n;
02951       aptl[0].x = 0;            // Really unused
02952       aptl[0].y = 0;
02953 
02954       emr.iType = EMR_POLYLINE;
02955       // The (cptl - 1) below is to account for aptl, which isn't written out
02956       emr.nSize = sizeof( ::EMRPOLYLINE ) + sizeof( POINTL ) * ( cptl - 1);
02957 
02958       lpoints = new POINTL[cptl];
02959 
02960       for (int i=0; i<n; i++) {
02961         lpoints[i].x = points[i].x;
02962         lpoints[i].y = points[i].y;
02963       }
02964 
02965       rclBounds = *bounds;
02966     }
02970     ~EMRPOLYLINE ( )
02971     {
02972       if ( lpoints ) delete[] lpoints;
02973     }
02978     EMRPOLYLINE ( DATASTREAM& ds )
02979     {
02980       ds >> emr >> rclBounds >> cptl;
02981 
02982       lpoints = new POINTL[cptl];
02983 
02984       POINTLARRAY points( lpoints, cptl );
02985 
02986       ds >> points;
02987     }
02991     bool serialize ( DATASTREAM ds )
02992     {
02993       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
02994       return true;
02995     }
02999     int size ( void ) const { return emr.nSize; }
03005     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03006     {
03007       // According to the wine windef.h header, POINT and POINTL are equivalent
03008       Polyline( dc, (POINT*)lpoints, cptl );
03009     }
03010 #ifdef ENABLE_EDITING
03011 
03014     void edit ( void ) const
03015     {
03016       printf( "*POLYLINE*\n" );
03017       edit_rectl( "rclBounds", rclBounds );
03018 #if 0
03019       printf( "\tcptl              : %ld\n", cptl );
03020       printf( "\taptl->\n" );
03021       for ( unsigned int i = 0; i < cptl; i++ )
03022         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
03023 #else
03024       edit_pointlarray( "\t", cptl, lpoints );
03025 #endif
03026     }
03027 #endif /* ENABLE_EDITING */
03028   };
03029 
03031 
03034   class EMRPOLYLINE16 : public METARECORD, ::EMRPOLYLINE16 {
03035     POINT16* lpoints;
03036   public:
03042     EMRPOLYLINE16 ( const RECTL* bounds, const POINT16* points, INT n )
03043     {
03044       cpts = n;
03045       apts[0].x = 0;            // Really unused
03046       apts[0].y = 0;
03047 
03048       emr.iType = EMR_POLYLINE16;
03049       // The (cptl - 1) below is to account for aptl, which isn't written out
03050       emr.nSize = sizeof( ::EMRPOLYLINE16 ) + sizeof( POINT16 ) * ( cpts - 1);
03051 
03052       lpoints = new POINT16[cpts];
03053 
03054       for (int i=0; i<n; i++) {
03055         lpoints[i].x = points[i].x;
03056         lpoints[i].y = points[i].y;
03057       }
03058 
03059       rclBounds = *bounds;
03060     }
03067     EMRPOLYLINE16 ( const RECTL* bounds, const POINT* points, INT n )
03068     {
03069       cpts = n;
03070       apts[0].x = 0;            // Really unused
03071       apts[0].y = 0;
03072 
03073       emr.iType = EMR_POLYLINE16;
03074       // The (cptl - 1) below is to account for aptl, which isn't written out
03075       emr.nSize = sizeof( ::EMRPOLYLINE16 ) + sizeof( POINT16 ) * ( cpts - 1);
03076 
03077       lpoints = new POINT16[cpts];
03078 
03079       for (int i=0; i<n; i++) {
03080         lpoints[i].x = points[i].x;
03081         lpoints[i].y = points[i].y;
03082       }
03083 
03084       rclBounds = *bounds;
03085     }
03089     ~EMRPOLYLINE16 ( )
03090     {
03091       if ( lpoints ) delete[] lpoints;
03092     }
03097     EMRPOLYLINE16 ( DATASTREAM& ds )
03098     {
03099       ds >> emr >> rclBounds >> cpts;
03100 
03101       lpoints = new POINT16[cpts];
03102 
03103       POINT16ARRAY points( lpoints, cpts );
03104 
03105       ds >> points;
03106     }
03110     bool serialize ( DATASTREAM ds )
03111     {
03112       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
03113       return true;
03114     }
03118     int size ( void ) const { return emr.nSize; }
03124     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03125     {
03126       // According to the wine windef.h header, POINT and POINTL are equivalent
03127       Polyline16( dc, lpoints, cpts );
03128     }
03129 #ifdef ENABLE_EDITING
03130 
03133     void edit ( void ) const
03134     {
03135       printf( "*POLYLINE16*\n" );
03136       edit_rectl( "rclBounds", rclBounds );
03137       edit_point16array( "\t", cpts, lpoints );
03138     }
03139 #endif /* ENABLE_EDITING */
03140   };
03141 
03143 
03146   class EMRPOLYGON : public METARECORD, ::EMRPOLYGON {
03147     POINTL* lpoints;
03148   public:
03154     EMRPOLYGON ( const RECTL* bounds, const POINT* points, INT n )
03155     {
03156       cptl = n;
03157       aptl[0].x = 0;            // Really unused
03158       aptl[0].y = 0;
03159 
03160       emr.iType = EMR_POLYGON;
03161       // The (cptl-1) below is to account for aptl, which isn't written out
03162       emr.nSize = sizeof( ::EMRPOLYGON ) + sizeof( POINTL ) * (cptl-1);
03163 
03164       lpoints = new POINTL[cptl];
03165 
03166       for (int i=0; i<n; i++) {
03167         lpoints[i].x = points[i].x;
03168         lpoints[i].y = points[i].y;
03169       }
03170 
03171       rclBounds = *bounds;
03172     }
03177     EMRPOLYGON ( DATASTREAM& ds )
03178     {
03179       ds >> emr >> rclBounds >> cptl;
03180 
03181       lpoints = new POINTL[cptl];
03182 
03183       POINTLARRAY points( lpoints, cptl );
03184 
03185       ds >> points;
03186     }
03190     ~EMRPOLYGON ( )
03191     {
03192       if ( lpoints ) delete[] lpoints;
03193     }
03197     bool serialize ( DATASTREAM ds )
03198     {
03199       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
03200       return true;
03201     }
03205     int size ( void ) const { return emr.nSize; }
03211     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03212     {
03213       // According to the wine windef.h header, POINT and POINTL are equivalent
03214       Polygon( dc, (POINT*)lpoints, cptl );
03215     }
03216 #ifdef ENABLE_EDITING
03217 
03220     void edit ( void ) const
03221     {
03222       printf( "*POLYGON*\n" );
03223       edit_rectl( "rclBounds", rclBounds );
03224 #if 0
03225       printf( "\tcptl              : %ld\n", cptl );
03226       printf( "\taptl->\n" );
03227       for ( unsigned int i = 0; i < cptl; i++ )
03228         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
03229 #else
03230       edit_pointlarray( "\t", cptl, lpoints );
03231 #endif
03232     }
03233 #endif /* ENABLE_EDITING */
03234   };
03235 
03237 
03240   class EMRPOLYGON16 : public METARECORD, ::EMRPOLYGON16 {
03241     POINT16* lpoints;
03242   public:
03248     EMRPOLYGON16 ( const RECTL* bounds, const POINT* points, INT16 n )
03249     {
03250       cpts = n;
03251       apts[0].x = 0;            // Really unused
03252       apts[0].y = 0;
03253 
03254       emr.iType = EMR_POLYGON16;
03255       // The (cptl-1) below is to account for aptl, which isn't written out
03256       emr.nSize = sizeof( ::EMRPOLYGON16 ) + sizeof( POINT16 ) * (cpts-1);
03257 
03258       lpoints = new POINT16[cpts];
03259 
03260       for (int i=0; i<n; i++) {
03261         lpoints[i].x = points[i].x;
03262         lpoints[i].y = points[i].y;
03263       }
03264 
03265       rclBounds = *bounds;
03266     }
03273     EMRPOLYGON16 ( const RECTL* bounds, const POINT16* points, INT16 n )
03274     {
03275       cpts = n;
03276       apts[0].x = 0;            // Really unused
03277       apts[0].y = 0;
03278 
03279       emr.iType = EMR_POLYGON16;
03280       // The (cptl-1) below is to account for aptl, which isn't written out
03281       emr.nSize = sizeof( ::EMRPOLYGON16 ) + sizeof( POINT16 ) * (cpts-1);
03282 
03283       lpoints = new POINT16[cpts];
03284 
03285       for (int i=0; i<n; i++) {
03286         lpoints[i].x = points[i].x;
03287         lpoints[i].y = points[i].y;
03288       }
03289 
03290       rclBounds = *bounds;
03291     }
03296     EMRPOLYGON16 ( DATASTREAM& ds )
03297     {
03298       ds >> emr >> rclBounds >> cpts;
03299 
03300       lpoints = new POINT16[cpts];
03301 
03302       POINT16ARRAY points( lpoints, cpts );
03303 
03304       ds >> points;
03305     }
03309     ~EMRPOLYGON16 ( )
03310     {
03311       if ( lpoints ) delete[] lpoints;
03312     }
03316     bool serialize ( DATASTREAM ds )
03317     {
03318       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
03319       return true;
03320     }
03324     int size ( void ) const { return emr.nSize; }
03330     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03331     {
03332       // According to the wine windef.h header, POINT and POINTL are equivalent
03333       Polygon16( dc, lpoints, cpts );
03334     }
03335 #ifdef ENABLE_EDITING
03336 
03339     void edit ( void ) const
03340     {
03341       printf( "*POLYGON16*\n" );
03342       edit_rectl( "rclBounds", rclBounds );
03343       edit_point16array( "\t", cpts, lpoints );
03344     }
03345 #endif /* ENABLE_EDITING */
03346   };
03347 
03349 
03352   class EMRPOLYPOLYGON : public METARECORD, ::EMRPOLYPOLYGON {
03353     DWORD* lcounts;
03354     POINTL* lpoints;
03355   public:
03362     EMRPOLYPOLYGON ( const RECTL* bounds, const POINT* points, const INT* counts,
03363                      UINT polygons )
03364     {
03365       nPolys = polygons;
03366       // Count the number of points in points
03367       int n = 0;
03368       for ( unsigned int i = 0; i < nPolys; i++ )
03369         n += counts[i];
03370 
03371       cptl = n;
03372       aPolyCounts[0] = 0;       // Really unused
03373       aptl[0].x = 0;
03374       aptl[0].y = 0;
03375 
03376       emr.iType = EMR_POLYPOLYGON;
03377       // The (#-1)'s below are to account for aPolyCounts[0] and aptl[0], which
03378       // aren't directly written out
03379       emr.nSize = sizeof( ::EMRPOLYPOLYGON ) + sizeof( POINTL ) * (cptl-1)
03380         + sizeof( DWORD ) * (nPolys-1);
03381 
03382       lcounts = new DWORD[nPolys];
03383 
03384       for ( unsigned int i = 0; i < nPolys; i++ )
03385         lcounts[i] = counts[i];
03386 
03387       lpoints = new POINTL[cptl];
03388 
03389       for (int i=0; i<n; i++) {
03390         lpoints[i].x = points[i].x;
03391         lpoints[i].y = points[i].y;
03392       }
03393 
03394       rclBounds = *bounds;
03395     }
03399     ~EMRPOLYPOLYGON ( )
03400     {
03401       if ( lcounts ) delete[] lcounts;
03402       if ( lpoints ) delete[] lpoints;
03403     }
03408     EMRPOLYPOLYGON ( DATASTREAM& ds )
03409     {
03410       ds >> emr >> rclBounds >> nPolys >> cptl;
03411 
03412       lcounts = new DWORD[nPolys];
03413 
03414       DWORDARRAY counts( lcounts, nPolys );
03415 
03416       ds >> counts;
03417 
03418       lpoints = new POINTL[cptl];
03419 
03420       POINTLARRAY points( lpoints, cptl );
03421 
03422       ds >> points;
03423     }
03427     bool serialize ( DATASTREAM ds )
03428     {
03429       ds << emr << rclBounds << nPolys << cptl << DWORDARRAY( lcounts, nPolys )
03430          << POINTLARRAY( lpoints, cptl );
03431       return true;
03432     }
03436     int size ( void ) const { return emr.nSize; }
03442     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03443     {
03444       // According to the wine windef.h header, POINT and POINTL are equivalent
03445       // (but DWORD and INT are not)
03446       INT* counts = new INT[nPolys];
03447       for ( unsigned int i = 0; i < nPolys; i++ )
03448         counts[i] = lcounts[i];
03449 
03450       PolyPolygon( dc, (POINT*)lpoints, counts, nPolys );
03451 
03452       delete[] counts;
03453     }
03454 #ifdef ENABLE_EDITING
03455 
03458     void edit ( void ) const
03459     {
03460       printf( "*POLYPOLYGON*\n" );
03461       edit_rectl( "rclBounds", rclBounds );
03462       printf( "\tnPolys\t\t: %ld\n", nPolys );
03463       printf( "\tcptl\t\t: %ld\n", cptl );
03464       printf( "\taPolyCounts\t: " );
03465       if ( nPolys > 0 )
03466         printf( "%ld\n", lcounts[0] );
03467       else
03468         puts( "" );
03469       for ( unsigned int i = 1; i < nPolys; i++ )
03470         printf( "\t\t\t  %ld\n", lcounts[i] );
03471       printf( "\tapts\t\t: " );
03472       if ( cptl > 0 )
03473         printf( "%ld, %ld\n", lpoints[0].x, lpoints[0].y );
03474       else
03475         puts( "" );
03476       for ( unsigned int i = 1; i < cptl; i++ )
03477         printf( "\t\t\t  %ld, %ld\n", lpoints[i].x, lpoints[i].y );
03478     }
03479 #endif /* ENABLE_EDITING */
03480   };
03481 
03483 
03486   class EMRPOLYPOLYGON16 : public METARECORD, ::EMRPOLYPOLYGON16 {
03487     DWORD* lcounts;
03488     POINT16* lpoints;
03489   public:
03496     EMRPOLYPOLYGON16 ( const RECTL* bounds, const POINT* points,
03497                        const INT* counts, UINT polygons )
03498     {
03499       nPolys = polygons;
03500       // Count the number of points in points
03501       int n = 0;
03502       for ( unsigned int i = 0; i < nPolys; i++ )
03503         n += counts[i];
03504 
03505       cpts = n;
03506       aPolyCounts[0] = 0;       // Really unused
03507       apts[0].x = 0;
03508       apts[0].y = 0;
03509 
03510       emr.iType = EMR_POLYPOLYGON16;
03511       // The (#-1)'s below are to account for aPolyCounts[0] and aptl[0], which
03512       // aren't directly written out
03513       emr.nSize = sizeof( ::EMRPOLYPOLYGON16 ) + sizeof( POINT16 ) * (cpts-1)
03514         + sizeof( DWORD ) * (nPolys-1);
03515 
03516       lcounts = new DWORD[nPolys];
03517 
03518       for ( unsigned int i = 0; i < nPolys; i++ )
03519         lcounts[i] = counts[i];
03520 
03521       lpoints = new POINT16[cpts];
03522 
03523       for (int i=0; i<n; i++) {
03524         lpoints[i].x = points[i].x;
03525         lpoints[i].y = points[i].y;
03526       }
03527 
03528       rclBounds = *bounds;
03529     }
03537     EMRPOLYPOLYGON16 ( const RECTL* bounds, const POINT16* points,
03538                        const INT* counts, UINT16 polygons )
03539     {
03540       nPolys = polygons;
03541       // Count the number of points in points
03542       int n = 0;
03543       for ( unsigned int i = 0; i < nPolys; i++ )
03544         n += counts[i];
03545 
03546       cpts = n;
03547       aPolyCounts[0] = 0;       // Really unused
03548       apts[0].x = 0;
03549       apts[0].y = 0;
03550 
03551       emr.iType = EMR_POLYPOLYGON16;
03552       // The (#-1)'s below are to account for aPolyCounts[0] and aptl[0], which
03553       // aren't directly written out
03554       emr.nSize = sizeof( ::EMRPOLYPOLYGON16 ) + sizeof( POINT16 ) * (cpts-1)
03555         + sizeof( DWORD ) * (nPolys-1);
03556 
03557       lcounts = new DWORD[nPolys];
03558 
03559       for ( unsigned int i = 0; i < nPolys; i++ )
03560         lcounts[i] = counts[i];
03561 
03562       lpoints = new POINT16[cpts];
03563 
03564       for (int i=0; i<n; i++) {
03565         lpoints[i].x = points[i].x;
03566         lpoints[i].y = points[i].y;
03567       }
03568 
03569       rclBounds = *bounds;
03570     }
03574     ~EMRPOLYPOLYGON16 ( )
03575     {
03576       if ( lcounts ) delete[] lcounts;
03577       if ( lpoints ) delete[] lpoints;
03578     }
03583     EMRPOLYPOLYGON16 ( DATASTREAM& ds )
03584     {
03585       ds >> emr >> rclBounds >> nPolys >> cpts;
03586 
03587       lcounts = new DWORD[nPolys];
03588 
03589       DWORDARRAY counts( lcounts, nPolys );
03590 
03591       ds >> counts;
03592 
03593       lpoints = new POINT16[cpts];
03594 
03595       POINT16ARRAY points( lpoints, cpts );
03596 
03597       ds >> points;
03598     }
03602     bool serialize ( DATASTREAM ds )
03603     {
03604       ds << emr << rclBounds << nPolys << cpts << DWORDARRAY( lcounts, nPolys )
03605          << POINT16ARRAY( lpoints, cpts );
03606       return true;
03607     }
03611     int size ( void ) const { return emr.nSize; }
03617     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03618     {
03619       // According to the wine windef.h header, POINT and POINTL are equivalent
03620       // (but DWORD and INT are not)
03621       INT* counts = new INT[nPolys];
03622       for ( unsigned int i = 0; i < nPolys; i++ )
03623         counts[i] = lcounts[i];
03624 
03625       PolyPolygon16( dc, lpoints, counts, nPolys );
03626 
03627       delete[] counts;
03628     }
03629 #ifdef ENABLE_EDITING
03630 
03633     void edit ( void ) const
03634     {
03635       printf( "*POLYPOLYGON16*\n" );
03636       edit_rectl( "rclBounds", rclBounds );
03637       printf( "\tnPolys\t\t: %ld\n", nPolys );
03638       printf( "\tcpts\t\t: %ld\n", cpts );
03639       printf( "\taPolyCounts\t: " );
03640       if ( nPolys > 0 )
03641         printf( "%ld\n", lcounts[0] );
03642       else
03643         puts( "" );
03644       for ( unsigned int i = 1; i < nPolys; i++ )
03645         printf( "\t\t\t  %ld\n", lcounts[i] );
03646       printf( "\tapts\t\t: " );
03647       if ( cpts > 0 )
03648         printf( "%d, %d\n", lpoints[0].x, lpoints[0].y );
03649       else
03650         puts( "" );
03651       for ( unsigned int i = 1; i < cpts; i++ )
03652         printf( "\t\t\t  %d, %d\n", lpoints[i].x, lpoints[i].y );
03653     }
03654 #endif /* ENABLE_EDITING */
03655   };
03656 
03658 
03661   class EMRPOLYBEZIER : public METARECORD, ::EMRPOLYBEZIER {
03662     POINTL* lpoints;
03663   public:
03669     EMRPOLYBEZIER ( const RECTL* bounds, const POINT* points, INT n )
03670     {
03671       cptl = n;
03672       aptl[0].x = 0;            // Really unused
03673       aptl[0].y = 0;
03674 
03675       emr.iType = EMR_POLYBEZIER;
03676       // The (cptl-1) below is to account for aptl, which isn't written out
03677       emr.nSize = sizeof( ::EMRPOLYBEZIER ) + sizeof( POINTL ) * (cptl-1);
03678 
03679       lpoints = new POINTL[cptl];
03680 
03681       for (int i=0; i<n; i++) {
03682         lpoints[i].x = points[i].x;
03683         lpoints[i].y = points[i].y;
03684       }
03685 
03686       rclBounds = *bounds;
03687     }
03692     EMRPOLYBEZIER ( DATASTREAM& ds )
03693     {
03694       ds >> emr >> rclBounds >> cptl;
03695 
03696       lpoints = new POINTL[cptl];
03697 
03698       POINTLARRAY points( lpoints, cptl );
03699 
03700       ds >> points;
03701     }
03705     ~EMRPOLYBEZIER ( )
03706     {
03707       if ( lpoints ) delete[] lpoints;
03708     }
03712     bool serialize ( DATASTREAM ds )
03713     {
03714       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
03715       return true;
03716     }
03720     int size ( void ) const { return emr.nSize; }
03726     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03727     {
03728       // According to the wine windef.h header, POINT and POINTL are equivalent
03729       PolyBezier( dc, (POINT*)lpoints, cptl );
03730     }
03731 #ifdef ENABLE_EDITING
03732 
03735     void edit ( void ) const
03736     {
03737       printf( "*POLYBEZIER*\n" );
03738       edit_rectl( "rclBounds", rclBounds );
03739 #if 0
03740       printf( "\tcptl              : %ld\n", cptl );
03741       printf( "\taptl->\n" );
03742       for ( unsigned int i = 0; i < cptl; i++ )
03743         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
03744 #else
03745       edit_pointlarray( "\t", cptl, lpoints );
03746 #endif
03747     }
03748 #endif /* ENABLE_EDITING */
03749   };
03750 
03752 
03755   class EMRPOLYBEZIER16 : public METARECORD, ::EMRPOLYBEZIER16 {
03756     POINT16* lpoints;
03757   public:
03763     EMRPOLYBEZIER16 ( const RECTL* bounds, const POINT16* points, INT n )
03764     {
03765       cpts = n;
03766       apts[0].x = 0;            // Really unused
03767       apts[0].y = 0;
03768 
03769       emr.iType = EMR_POLYBEZIER16;
03770       // The (cptl-1) below is to account for aptl, which isn't written out
03771       emr.nSize = sizeof( ::EMRPOLYBEZIER16 ) + sizeof( POINT16 ) * (cpts-1);
03772 
03773       lpoints = new POINT16[cpts];
03774 
03775       for (int i=0; i<n; i++) {
03776         lpoints[i].x = points[i].x;
03777         lpoints[i].y = points[i].y;
03778       }
03779 
03780       rclBounds = *bounds;
03781     }
03788     EMRPOLYBEZIER16 ( const RECTL* bounds, const POINT* points, INT n )
03789     {
03790       cpts = n;
03791       apts[0].x = 0;            // Really unused
03792       apts[0].y = 0;
03793 
03794       emr.iType = EMR_POLYBEZIER16;
03795       // The (cptl-1) below is to account for aptl, which isn't written out
03796       emr.nSize = sizeof( ::EMRPOLYBEZIER16 ) + sizeof( POINT16 ) * (cpts-1);
03797 
03798       lpoints = new POINT16[cpts];
03799 
03800       for (int i=0; i<n; i++) {
03801         lpoints[i].x = points[i].x;
03802         lpoints[i].y = points[i].y;
03803       }
03804 
03805       rclBounds = *bounds;
03806     }
03811     EMRPOLYBEZIER16 ( DATASTREAM& ds )
03812     {
03813       ds >> emr >> rclBounds >> cpts;
03814 
03815       lpoints = new POINT16[cpts];
03816 
03817       POINT16ARRAY points( lpoints, cpts );
03818 
03819       ds >> points;
03820     }
03824     ~EMRPOLYBEZIER16 ( )
03825     {
03826       if ( lpoints ) delete[] lpoints;
03827     }
03831     bool serialize ( DATASTREAM ds )
03832     {
03833       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
03834       return true;
03835     }
03839     int size ( void ) const { return emr.nSize; }
03845     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03846     {
03847       // According to the wine windef.h header, POINT and POINTL are equivalent
03848       PolyBezier16( dc, lpoints, cpts );
03849     }
03850 #ifdef ENABLE_EDITING
03851 
03854     void edit ( void ) const
03855     {
03856       printf( "*POLYBEZIER16*\n" );
03857       edit_rectl( "rclBounds", rclBounds );
03858       edit_point16array( "\t", cpts, lpoints );
03859     }
03860 #endif /* ENABLE_EDITING */
03861   };
03862 
03864 
03867   class EMRPOLYBEZIERTO : public METARECORD, ::EMRPOLYBEZIER {
03868     POINTL* lpoints;
03869   public:
03875     EMRPOLYBEZIERTO ( const RECTL* bounds, const POINT* points, INT n )
03876     {
03877       cptl = n;
03878       aptl[0].x = 0;            // Really unused
03879       aptl[0].y = 0;
03880 
03881       emr.iType = EMR_POLYBEZIERTO;
03882       // The (cptl-1) below is to account for aptl, which isn't written out
03883       emr.nSize = sizeof( ::EMRPOLYBEZIERTO ) + sizeof( POINTL ) * (cptl-1);
03884 
03885       lpoints = new POINTL[cptl];
03886 
03887       for (int i=0; i<n; i++) {
03888         lpoints[i].x = points[i].x;
03889         lpoints[i].y = points[i].y;
03890       }
03891 
03892       rclBounds = *bounds;
03893     }
03898     EMRPOLYBEZIERTO ( DATASTREAM& ds )
03899     {
03900       ds >> emr >> rclBounds >> cptl;
03901 
03902       lpoints = new POINTL[cptl];
03903 
03904       POINTLARRAY points( lpoints, cptl );
03905 
03906       ds >> points;
03907     }
03911     ~EMRPOLYBEZIERTO ( )
03912     {
03913       if ( lpoints ) delete[] lpoints;
03914     }
03918     bool serialize ( DATASTREAM ds )
03919     {
03920       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
03921       return true;
03922     }
03926     int size ( void ) const { return emr.nSize; }
03932     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03933     {
03934       // According to the wine windef.h header, POINT and POINTL are equivalent
03935       PolyBezierTo( dc, (POINT*)lpoints, cptl );
03936     }
03937 #ifdef ENABLE_EDITING
03938 
03941     void edit ( void ) const
03942     {
03943       printf( "*POLYBEZIERTO*\n" );
03944       edit_rectl( "rclBounds", rclBounds );
03945 #if 0
03946       printf( "\tcptl              : %ld\n", cptl );
03947       printf( "\taptl->\n" );
03948       for ( unsigned int i = 0; i < cptl; i++ )
03949         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
03950 #else
03951       edit_pointlarray( "\t", cptl, lpoints );
03952 #endif
03953     }
03954 #endif /* ENABLE_EDITING */
03955   };
03956 
03958 
03961   class EMRPOLYBEZIERTO16 : public METARECORD, ::EMRPOLYBEZIER16 {
03962     POINT16* lpoints;
03963   public:
03969     EMRPOLYBEZIERTO16 ( const RECTL* bounds, const POINT16* points, INT n )
03970     {
03971       cpts = n;
03972       apts[0].x = 0;            // Really unused
03973       apts[0].y = 0;
03974 
03975       emr.iType = EMR_POLYBEZIERTO16;
03976       // The (cptl-1) below is to account for aptl, which isn't written out
03977       emr.nSize = sizeof( ::EMRPOLYBEZIERTO16 ) + sizeof( POINT16 ) * (cpts-1);
03978 
03979       lpoints = new POINT16[cpts];
03980 
03981       for (int i=0; i<n; i++) {
03982         lpoints[i].x = points[i].x;
03983         lpoints[i].y = points[i].y;
03984       }
03985 
03986       rclBounds = *bounds;
03987     }
03994     EMRPOLYBEZIERTO16 ( const RECTL* bounds, const POINT* points, INT n )
03995     {
03996       cpts = n;
03997       apts[0].x = 0;            // Really unused
03998       apts[0].y = 0;
03999 
04000       emr.iType = EMR_POLYBEZIERTO16;
04001       // The (cptl-1) below is to account for aptl, which isn't written out
04002       emr.nSize = sizeof( ::EMRPOLYBEZIERTO16 ) + sizeof( POINT16 ) * (cpts-1);
04003 
04004       lpoints = new POINT16[cpts];
04005 
04006       for (int i=0; i<n; i++) {
04007         lpoints[i].x = points[i].x;
04008         lpoints[i].y = points[i].y;
04009       }
04010 
04011       rclBounds = *bounds;
04012     }
04017     EMRPOLYBEZIERTO16 ( DATASTREAM& ds )
04018     {
04019       ds >> emr >> rclBounds >> cpts;
04020 
04021       lpoints = new POINT16[cpts];
04022 
04023       POINT16ARRAY points( lpoints, cpts );
04024 
04025       ds >> points;
04026     }
04030     ~EMRPOLYBEZIERTO16 ( )
04031     {
04032       if ( lpoints ) delete[] lpoints;
04033     }
04037     bool serialize ( DATASTREAM ds )
04038     {
04039       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
04040       return true;
04041     }
04045     int size ( void ) const { return emr.nSize; }
04051     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04052     {
04053       // According to the wine windef.h header, POINT and POINTL are equivalent
04054       PolyBezierTo16( dc, lpoints, cpts );
04055     }
04056 #ifdef ENABLE_EDITING
04057 
04060     void edit ( void ) const
04061     {
04062       printf( "*POLYBEZIERTO16*\n" );
04063       edit_rectl( "rclBounds", rclBounds );
04064       edit_point16array( "\t", cpts, lpoints );
04065     }
04066 #endif /* ENABLE_EDITING */
04067   };
04068 
04070 
04073   class EMRPOLYLINETO : public METARECORD, ::EMRPOLYLINETO {
04074     POINTL* lpoints;
04075   public:
04081     EMRPOLYLINETO ( const RECTL* bounds, const POINT* points, INT n )
04082     {
04083       cptl = n;
04084       aptl[0].x = 0;
04085       aptl[0].y = 0;
04086 
04087       emr.iType = EMR_POLYLINETO;
04088       // The (cptl-1) below is to account for aptl, which isn't written out
04089       emr.nSize = sizeof( ::EMRPOLYLINETO ) + sizeof( POINTL ) * (cptl-1);
04090 
04091       lpoints = new POINTL[cptl];
04092 
04093       for (int i=0; i<n; i++) {
04094         lpoints[i].x = points[i].x;
04095         lpoints[i].y = points[i].y;
04096       }
04097 
04098       rclBounds = *bounds;
04099     }
04104     EMRPOLYLINETO ( DATASTREAM& ds )
04105     {
04106       ds >> emr >> rclBounds >> cptl;
04107 
04108       lpoints = new POINTL[cptl];
04109 
04110       POINTLARRAY points( lpoints, cptl );
04111 
04112       ds >> points;
04113     }
04117     ~EMRPOLYLINETO ( )
04118     {
04119       if ( lpoints ) delete[] lpoints;
04120     }
04124     bool serialize ( DATASTREAM ds )
04125     {
04126       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
04127       return true;
04128     }
04132     int size ( void ) const { return emr.nSize; }
04138     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04139     {
04140       // According to the wine windef.h header, POINT and POINTL are equivalent
04141       PolylineTo( dc, (POINT*)lpoints, cptl );
04142     }
04143 #ifdef ENABLE_EDITING
04144 
04147     void edit ( void ) const
04148     {
04149       printf( "*POLYLINETO*\n" );
04150       edit_rectl( "rclBounds", rclBounds );
04151 #if 0
04152       printf( "\tcptl              : %ld\n", cptl );
04153       printf( "\taptl->\n" );
04154       for ( unsigned int i = 0; i < cptl; i++ )
04155         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
04156 #else
04157       edit_pointlarray( "\t", cptl, lpoints );
04158 #endif
04159     }
04160 #endif /* ENABLE_EDITING */
04161   };
04162 
04164 
04167   class EMRPOLYLINETO16 : public METARECORD, ::EMRPOLYLINETO16 {
04168     POINT16* lpoints;
04169   public:
04175     EMRPOLYLINETO16 ( const RECTL* bounds, const POINT16* points, INT n )
04176     {
04177       cpts = n;
04178       apts[0].x = 0;
04179       apts[0].y = 0;
04180 
04181       emr.iType = EMR_POLYLINETO16;
04182       // The (cptl-1) below is to account for aptl, which isn't written out
04183       emr.nSize = sizeof( ::EMRPOLYLINETO16 ) + sizeof( POINT16 ) * (cpts-1);
04184 
04185       lpoints = new POINT16[cpts];
04186 
04187       for (int i=0; i<n; i++) {
04188         lpoints[i].x = points[i].x;
04189         lpoints[i].y = points[i].y;
04190       }
04191 
04192       rclBounds = *bounds;
04193     }
04200     EMRPOLYLINETO16 ( const RECTL* bounds, const POINT* points, INT n )
04201     {
04202       cpts = n;
04203       apts[0].x = 0;
04204       apts[0].y = 0;
04205 
04206       emr.iType = EMR_POLYLINETO16;
04207       // The (cptl-1) below is to account for aptl, which isn't written out
04208       emr.nSize = sizeof( ::EMRPOLYLINETO16 ) + sizeof( POINT16 ) * (cpts-1);
04209 
04210       lpoints = new POINT16[cpts];
04211 
04212       for (int i=0; i<n; i++) {
04213         lpoints[i].x = points[i].x;
04214         lpoints[i].y = points[i].y;
04215       }
04216 
04217       rclBounds = *bounds;
04218     }
04223     EMRPOLYLINETO16 ( DATASTREAM& ds )
04224     {
04225       ds >> emr >> rclBounds >> cpts;
04226 
04227       lpoints = new POINT16[cpts];
04228 
04229       POINT16ARRAY points( lpoints, cpts );
04230 
04231       ds >> points;
04232     }
04236     ~EMRPOLYLINETO16 ( )
04237     {
04238       if ( lpoints ) delete[] lpoints;
04239     }
04243     bool serialize ( DATASTREAM ds )
04244     {
04245       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
04246       return true;
04247     }
04251     int size ( void ) const { return emr.nSize; }
04257     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04258     {
04259       // According to the wine windef.h header, POINT and POINTL are equivalent
04260       PolylineTo16( dc, lpoints, cpts );
04261     }
04262 #ifdef ENABLE_EDITING
04263 
04266     void edit ( void ) const
04267     {
04268       printf( "*POLYLINETO16*\n" );
04269       edit_rectl( "rclBounds", rclBounds );
04270       edit_point16array( "\t", cpts, lpoints );
04271     }
04272 #endif /* ENABLE_EDITING */
04273   };
04274 
04276 
04281   class EMREXTTEXTOUTA : public METARECORD, ::EMREXTTEXTOUTA {
04282     PSTR string_a;
04283     int string_size;
04284 
04285     INT* dx_i;
04286   public:
04296     EMREXTTEXTOUTA ( const RECTL* bounds, DWORD graphicsMode, FLOAT xScale,
04297                      FLOAT yScale, const PEMRTEXT text, LPCSTR string,
04298                      const INT* dx )
04299     {
04300       emr.iType = EMR_EXTTEXTOUTA;
04301       emr.nSize = sizeof( ::EMREXTTEXTOUTA );
04302 
04303       rclBounds = *bounds;
04304 
04305       iGraphicsMode = graphicsMode;
04306       exScale = xScale;
04307       eyScale = yScale;
04308 
04309       emrtext = *text;
04310 
04311       string_size = ROUND_TO_LONG( emrtext.nChars );
04312 
04313       string_a = new CHAR[ string_size ];
04314 
04315       memset( string_a, 0, sizeof(CHAR) * string_size );
04316 
04317       for ( unsigned int i=0; i<emrtext.nChars; i++ )
04318         string_a[i] = *string++;
04319 
04320       emrtext.offString = emr.nSize;
04321       emr.nSize += string_size * sizeof(CHAR);
04322 
04323       if ( dx ) {
04324 
04325         dx_i = new INT[ emrtext.nChars ];
04326 
04327         for ( unsigned int i=0; i<emrtext.nChars; i++ )
04328           dx_i[i] = *dx++;
04329 
04330         emrtext.offDx = emr.nSize;
04331         emr.nSize += emrtext.nChars * sizeof(INT);
04332       }
04333       else {
04334         emrtext.offDx = 0;
04335         dx_i = 0;
04336       }
04337     }
04342     EMREXTTEXTOUTA ( DATASTREAM& ds )
04343     {
04344       ds >> emr >> rclBounds >> iGraphicsMode >> exScale >> eyScale >> emrtext;
04345 
04346       if ( emrtext.offString != 0 ) {
04347         string_size = ROUND_TO_LONG( emrtext.nChars );
04348 
04349         string_a = new CHAR[ string_size ];
04350 
04351         memset( string_a, 0, sizeof(CHAR) * string_size );
04352 
04353         CHARSTR string( string_a, string_size );
04354 
04355         ds >> string;
04356       }
04357       else
04358         string_a = 0;
04359 
04360       if ( emrtext.offDx ) {
04361         dx_i = new INT[ emrtext.nChars ];
04362 
04363         INTARRAY dx_is( dx_i, emrtext.nChars );
04364 
04365         ds >> dx_is;
04366       }
04367       else
04368         dx_i = 0;
04369     }
04374     ~EMREXTTEXTOUTA ( )
04375     {
04376       if ( string_a ) delete[] string_a;
04377       if ( dx_i ) delete[] dx_i;
04378     }
04382     bool serialize ( DATASTREAM ds )
04383     {
04384       ds << emr << rclBounds << iGraphicsMode << exScale << eyScale
04385          << emrtext << CHARSTR( string_a, string_size );
04386       if ( dx_i )
04387         ds << INTARRAY( dx_i, emrtext.nChars );
04388       return true;
04389     }
04393     int size ( void ) const { return emr.nSize; }
04399     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04400     {
04401       RECT rect;
04402       rect.left = emrtext.rcl.left;
04403       rect.top = emrtext.rcl.top;
04404       rect.right = emrtext.rcl.right;
04405       rect.bottom = emrtext.rcl.bottom;
04406 
04407       ExtTextOutA( dc, emrtext.ptlReference.x, emrtext.ptlReference.y,
04408                    emrtext.fOptions, &rect, string_a, emrtext.nChars,
04409                    dx_i );
04410     }
04411 #ifdef ENABLE_EDITING
04412 
04415     void edit ( void ) const
04416     {
04417       printf( "*EXTTEXTOUTA*\n" );
04418       edit_rectl( "rclBounds", rclBounds );
04419       printf( "\tiGraphicsMode\t: " );
04420       switch ( iGraphicsMode ) {
04421       case GM_COMPATIBLE: printf( "GM_COMPATIBLE\n" ); break;
04422       case GM_ADVANCED: printf( "GM_ADVANCED\n" ); break;
04423       default: printf( "unknown(%ld)\n", iGraphicsMode );
04424       }
04425       printf( "\texScale\t\t: %f\n", exScale );
04426       printf( "\teyScale\t\t: %f\n", eyScale );
04427       printf( "\tptlReference\t: (%ld,%ld)\n", emrtext.ptlReference.x,
04428               emrtext.ptlReference.y );
04429       printf( "\tnChars\t\t: %ld\n", emrtext.nChars );
04430       printf( "\toffString\t: %ld\n", emrtext.offString );
04431       printf( "\tfOptions\t: " );
04432       if ( emrtext.fOptions == 0 )
04433         printf( "None" );
04434       else {
04435         if ( emrtext.fOptions & ETO_GRAYED ) {
04436           printf( "ETO_GRAYED" );
04437           if ( emrtext.fOptions & ~ETO_GRAYED )
04438             printf( " | " );
04439         }
04440         if ( emrtext.fOptions & ETO_OPAQUE ) {
04441           printf( "ETO_OPAQUE" );
04442           if ( emrtext.fOptions & ~(ETO_GRAYED | ETO_OPAQUE) )
04443             printf( " | " );
04444         }
04445         if ( emrtext.fOptions & ETO_CLIPPED ) {
04446           printf( "ETO_CLIPPED" );
04447           if ( emrtext.fOptions & ~(ETO_GRAYED | ETO_OPAQUE | ETO_CLIPPED ) )
04448             printf( " | " );
04449         }
04450         if ( emrtext.fOptions & ETO_GLYPH_INDEX ) {
04451           printf( "ETO_GLYPH_INDEX" );
04452           if ( emrtext.fOptions &
04453                ~(ETO_GRAYED | ETO_OPAQUE | ETO_CLIPPED | ETO_GLYPH_INDEX) )
04454             printf( " | " );
04455         }
04456         if ( emrtext.fOptions & ETO_RTLREADING ) {
04457           printf( "ETO_RTLREADING" );
04458           if ( emrtext.fOptions &
04459                ~(ETO_GRAYED | ETO_OPAQUE | ETO_CLIPPED | ETO_GLYPH_INDEX |
04460                  ETO_RTLREADING) )
04461             printf( " | " );
04462         }
04463         if ( emrtext.fOptions & ETO_IGNORELANGUAGE )
04464           printf( "ETO_IGNORELANGUAGE" );
04465       }
04466       printf( "\n" );
04467       edit_rectl( "rcl\t", emrtext.rcl );
04468       printf( "\toffDx\t\t: %ld\n", emrtext.offDx );
04469       printf( "\tString:\n\t\t%s\n",  string_a );
04470 
04471       if ( emrtext.offDx != 0 ) {
04472         printf( "\tOffsets:\n\t\t" );
04473         for ( unsigned int i = 0; i < emrtext.nChars; i++ )
04474           printf( "%d ", dx_i[i] );
04475         printf( "\n" );
04476       }
04477     }
04478 #endif /* ENABLE_EDITING */
04479   };
04480 
04482 
04485   class EMRSETPIXELV : public METARECORD, ::EMRSETPIXELV {
04486   public:
04492     EMRSETPIXELV ( INT x, INT y, COLORREF color )
04493     {
04494       emr.iType = EMR_SETPIXELV;
04495       emr.nSize = sizeof( ::EMRSETPIXELV );
04496       ptlPixel.x = x;
04497       ptlPixel.y = y;
04498       crColor = color;
04499     }
04504     EMRSETPIXELV ( DATASTREAM& ds )
04505     {
04506       ds >> emr >> ptlPixel >> crColor;
04507     }
04511     bool serialize ( DATASTREAM ds )
04512     {
04513       ds << emr << ptlPixel << crColor;
04514       return true;
04515     }
04519     int size ( void ) const { return emr.nSize; }
04525     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04526     {
04527       SetPixel( dc, ptlPixel.x, ptlPixel.y, crColor );
04528     }
04529 #ifdef ENABLE_EDITING
04530 
04533     void edit ( void ) const
04534     {
04535       printf( "*SETPIXELV*\n" );
04536       edit_pointl( "ptlPixel", ptlPixel );
04537       edit_color( "crColor\t", crColor );
04538     }
04539 #endif /* ENABLE_EDITING */
04540   };
04541 
04542   class PEN;
04543   class EXTPEN;
04544   class BRUSH;
04545   class FONT;
04546   class PALETTE;
04547 
04549 
04552   class EMRCREATEPEN : public METARECORD, public ::EMRCREATEPEN
04553   {
04554   public:
04559     EMRCREATEPEN ( PEN* pen, HGDIOBJ handle );
04564     EMRCREATEPEN ( DATASTREAM& ds );
04568     bool serialize ( DATASTREAM ds )
04569     {
04570       ds << emr << ihPen << lopn;
04571       return true;
04572     }
04576     int size ( void ) const { return emr.nSize; }
04582     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
04583 #ifdef ENABLE_EDITING
04584 
04587     void edit ( void ) const
04588     {
04589       printf( "*CREATEPEN*\n" );
04590       printf( "\tihPen\t\t: 0x%lx\n", ihPen );
04591       edit_pen_style( "lopn.lopnStyle", lopn.lopnStyle );
04592       printf( "\tlopn.lopnWidth\t: %ld, %ld\n", lopn.lopnWidth.x, lopn.lopnWidth.y );
04593       edit_color( "lopn.lopnColor", lopn.lopnColor );
04594     }
04595 #endif /* ENABLE_EDITING */
04596   };
04597 
04599 
04603   class EMREXTCREATEPEN : public METARECORD, public ::EMREXTCREATEPEN
04604   {
04605   public:
04610     EMREXTCREATEPEN ( EXTPEN* pen, HGDIOBJ handle );
04615     EMREXTCREATEPEN ( DATASTREAM& ds );
04619     bool serialize ( DATASTREAM ds )
04620     {
04621       ds << emr << ihPen << offBmi << cbBmi << offBits << cbBits << elp;
04622       return true;
04623     }
04627     int size ( void ) const { return emr.nSize; }
04633     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
04634 #ifdef ENABLE_EDITING
04635 
04638     void edit ( void ) const
04639     {
04640       printf( "*EXTCREATEPEN*\n" );
04641       printf( "\tihPen\t\t\t: 0x%lx\n", ihPen );
04642       printf( "\toffBmi\t\t\t: %ld\n",  offBmi );
04643       printf( "\tcbBmi\t\t\t: %ld\n", cbBmi );
04644       printf( "\toffBits\t\t\t: %ld\n", offBits );
04645       printf( "\tcbBits\t\t\t: %ld\n", cbBits );
04646       edit_pen_style( "elp.elpPenStyle\t", elp.elpPenStyle );
04647       printf( "\telp.elpWidth\t\t: %ld\n", elp.elpWidth );
04648       edit_brush_style( "elp.elpBrushStyle", elp.elpBrushStyle );
04649       edit_color( "elp.elpColor\t", elp.elpColor );
04650       edit_brush_hatch( "elp.elpHatch\t", elp.elpHatch );
04651       printf( "\telp.elpNumEntries\t: %ld\n", elp.elpNumEntries );
04652     }
04653 #endif /* ENABLE_EDITING */
04654   };
04655 
04657 
04660   class EMRCREATEBRUSHINDIRECT : public METARECORD, public ::EMRCREATEBRUSHINDIRECT
04661   {
04662   public:
04667     EMRCREATEBRUSHINDIRECT ( BRUSH* brush, HGDIOBJ handle );
04672     EMRCREATEBRUSHINDIRECT ( DATASTREAM& ds );
04676     bool serialize ( DATASTREAM ds )
04677     {
04678       ds << emr << ihBrush << lb;
04679       return true;
04680     }
04684     int size ( void ) const { return emr.nSize; }
04690     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
04691 #ifdef ENABLE_EDITING
04692 
04695     void edit ( void ) const
04696     {
04697       printf( "*CREATEBRUSHINDIRECT*\n" );
04698       printf( "\tihBrush\t\t: 0x%lx\n", ihBrush );
04699       edit_brush_style( "lb.lbStyle", lb.lbStyle );
04700       edit_color( "lb.lbColor", lb.lbColor );
04701       edit_brush_hatch( "lb.lbHatch", lb.lbHatch );
04702     }
04703 #endif /* ENABLE_EDITING */
04704   };
04705 
04707 
04710   class EMREXTCREATEFONTINDIRECTW : public METARECORD, public ::EMREXTCREATEFONTINDIRECTW
04711   {
04712   public:
04717     EMREXTCREATEFONTINDIRECTW ( FONT* font, HGDIOBJ handle );
04722     EMREXTCREATEFONTINDIRECTW ( DATASTREAM& ds );
04726     bool serialize ( DATASTREAM ds )
04727     {
04728       // Since EMF records have to be multiples of 4 bytes, this
04729       // should perhaps be a general thing, but we know it's currently
04730       // only a problem for this structure.
04731 
04732       ds << emr << ihFont << elfw << PADDING( 2 );
04733 
04734       return true;
04735     }
04739     int size ( void ) const { return emr.nSize; }
04745     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
04746 #ifdef ENABLE_EDITING
04747 
04750     void edit ( void ) const
04751     {
04752       printf( "*EXTCREATEFONTINDIRECTW*\n" );
04753       printf( "\tihFont\t\t\t: %ld\n", ihFont );
04754       printf( "\tlfHeight\t\t: %ld\n", elfw.elfLogFont.lfHeight );
04755       printf( "\tlfWidth\t\t\t: %ld\n", elfw.elfLogFont.lfWidth );
04756       printf( "\tlfEscapement\t\t: %ld\n", elfw.elfLogFont.lfEscapement );
04757       printf( "\tlfOrientation\t\t: %ld\n", elfw.elfLogFont.lfOrientation );
04758       printf( "\tlfWeight\t\t: " );
04759       switch ( elfw.elfLogFont.lfWeight ) {
04760       case FW_DONTCARE: printf( "FW_DONTCARE\n" ); break;
04761       case FW_THIN: printf( "FW_THIN\n" ); break;
04762       case FW_EXTRALIGHT: printf( "FW_EXTRALIGHT\n" ); break;
04763       case FW_LIGHT: printf( "FW_LIGHT\n" ); break;
04764       case FW_NORMAL: printf( "FW_NORMAL\n" ); break;
04765       case FW_MEDIUM: printf( "FW_MEDIUM\n" ); break;
04766       case FW_SEMIBOLD: printf( "FW_SEMIBOLD\n" ); break;
04767       case FW_BOLD: printf( "FW_BOLD\n" ); break;
04768       case FW_EXTRABOLD: printf( "FW_EXTRABOLD\n" ); break;
04769       case FW_BLACK: printf( "FW_BLACK\n" ); break;
04770       }
04771       printf( "\tlfItalic\t\t: %d\n", elfw.elfLogFont.lfItalic );
04772       printf( "\tlfUnderline\t\t: %d\n", elfw.elfLogFont.lfUnderline );
04773       printf( "\tlfStrikeOut\t\t: %d\n", elfw.elfLogFont.lfStrikeOut );
04774       printf( "\tlfCharSet\t\t: %d\n", elfw.elfLogFont.lfCharSet );
04775       printf( "\tlfOutPrecision\t\t: %d\n", elfw.elfLogFont.lfOutPrecision );
04776       printf( "\tlfClipPrecision\t\t: %d\n", elfw.elfLogFont.lfClipPrecision );
04777       printf( "\tlfQuality\t\t: %d\n", elfw.elfLogFont.lfQuality );
04778       printf( "\tlfPitchAndFamily\t: %d\n", elfw.elfLogFont.lfPitchAndFamily );
04779       int i = 0;
04780       printf( "\tlfFaceName\t\t: '" );
04781       while ( elfw.elfLogFont.lfFaceName[i] != 0 && i < LF_FACESIZE ) {
04782         putchar( elfw.elfLogFont.lfFaceName[i] );
04783         i++;
04784       }
04785       puts( "'" );
04786 
04787       i = 0;
04788       printf( "\telfFullName\t\t: '" );
04789       while ( elfw.elfFullName[i] != 0 && i < LF_FULLFACESIZE ) {
04790         putchar( elfw.elfFullName[i] );
04791         i++;
04792       }
04793       puts( "'" );
04794 
04795       i = 0;
04796       printf( "\telfStyle\t\t: '" );
04797       while ( elfw.elfStyle[i] != 0 && i < LF_FACESIZE ) {
04798         putchar( elfw.elfStyle[i] );
04799         i++;
04800       }
04801       puts( "'" );
04802 
04803       printf( "\telfVersion\t\t: %ld\n", elfw.elfVersion );
04804       printf( "\telfStyleSize\t\t: %ld\n", elfw.elfStyleSize );
04805       printf( "\telfMatch\t\t: %ld\n", elfw.elfMatch );
04806       printf( "\telfVendorId\t\t: '%s'\n", elfw.elfVendorId );
04807       printf( "\telfCulture\t\t: %ld\n", elfw.elfCulture );
04808       printf( "\telfPanose\t\t:\n" );
04809       printf( "\t\tbFamilyType\t\t: %d\n", elfw.elfPanose.bFamilyType );
04810       printf( "\t\tbSerifStyle\t\t: %d\n", elfw.elfPanose.bSerifStyle );
04811       printf( "\t\tbWeight\t\t\t: %d\n", elfw.elfPanose.bWeight );
04812       printf( "\t\tbProportion\t\t: %d\n", elfw.elfPanose.bProportion );
04813       printf( "\t\tbContrast\t\t: %d\n", elfw.elfPanose.bContrast );
04814       printf( "\t\tbStrokeVariation\t: %d\n", elfw.elfPanose.bStrokeVariation );
04815       printf( "\t\tbArmStyle\t\t: %d\n", elfw.elfPanose.bArmStyle );
04816       printf( "\t\tbLetterform\t\t: %d\n", elfw.elfPanose.bLetterform );
04817       printf( "\t\tbMidline\t\t: %d\n", elfw.elfPanose.bMidline );
04818       printf( "\t\tbXHeight\t\t: %d\n", elfw.elfPanose.bXHeight );
04819     }
04820 #endif /* ENABLE_EDITING */
04821   };
04822 
04824 
04827   class EMRCREATEPALETTE : public METARECORD, public ::EMRCREATEPALETTE
04828   {
04829   public:
04834     EMRCREATEPALETTE ( PALETTE* palette, HGDIOBJ handle );
04839     EMRCREATEPALETTE ( DATASTREAM& ds );
04843     bool serialize ( DATASTREAM ds )
04844     {
04845       ds << emr << ihPal << lgpl;
04846       return true;
04847     }
04851     int size ( void ) const { return emr.nSize; }
04857     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
04858 #ifdef ENABLE_EDITING
04859 
04862     void edit ( void ) const
04863     {
04864       printf( "*CREATEPALETTE* (not really handled by libEMF)\n" );
04865     }
04866 #endif /* ENABLE_EDITING */
04867   };
04868 
04870 
04873   class EMRFILLPATH : public METARECORD, ::EMRFILLPATH {
04874   public:
04879     EMRFILLPATH ( const RECTL* bounds )
04880     {
04881       emr.iType = EMR_FILLPATH;
04882       emr.nSize = sizeof( ::EMRFILLPATH );
04883       rclBounds = *bounds;
04884     }
04889     EMRFILLPATH ( DATASTREAM& ds )
04890     {
04891       ds >> emr >> rclBounds;
04892     }
04896     bool serialize ( DATASTREAM ds )
04897     {
04898       ds << emr << rclBounds;
04899       return true;
04900     }
04904     int size ( void ) const { return emr.nSize; }
04910     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04911     {
04912       FillPath( dc );
04913     }
04914 #ifdef ENABLE_EDITING
04915 
04918     void edit ( void ) const
04919     {
04920       printf( "*FILLPATH*\n" );
04921       edit_rectl( "rclBounds", rclBounds );
04922     }
04923 #endif /* ENABLE_EDITING */
04924   };
04926 
04929   class EMRSTROKEPATH : public METARECORD, ::EMRSTROKEPATH {
04930   public:
04935     EMRSTROKEPATH ( const RECTL* bounds )
04936     {
04937       emr.iType = EMR_STROKEPATH;
04938       emr.nSize = sizeof( ::EMRSTROKEPATH );
04939       rclBounds = *bounds;
04940     }
04945     EMRSTROKEPATH ( DATASTREAM& ds )
04946     {
04947       ds >> emr >> rclBounds;
04948     }
04952     bool serialize ( DATASTREAM ds )
04953     {
04954       ds << emr << rclBounds;
04955       return true;
04956     }
04960     int size ( void ) const { return emr.nSize; }
04966     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04967     {
04968       StrokePath( dc );
04969     }
04970 #ifdef ENABLE_EDITING
04971 
04974     void edit ( void ) const
04975     {
04976       printf( "*STROKEPATH*\n" );
04977       edit_rectl( "rclBounds", rclBounds );
04978     }
04979 #endif /* ENABLE_EDITING */
04980   };
04982 
04985   class EMRSTROKEANDFILLPATH : public METARECORD, ::EMRSTROKEANDFILLPATH {
04986   public:
04991     EMRSTROKEANDFILLPATH ( const RECTL* bounds )
04992     {
04993       emr.iType = EMR_STROKEANDFILLPATH;
04994       emr.nSize = sizeof( ::EMRSTROKEANDFILLPATH );
04995       rclBounds = *bounds;
04996     }
05001     EMRSTROKEANDFILLPATH ( DATASTREAM& ds )
05002     {
05003       ds >> emr >> rclBounds;
05004     }
05008     bool serialize ( DATASTREAM ds )
05009     {
05010       ds << emr << rclBounds;
05011       return true;
05012     }
05016     int size ( void ) const { return emr.nSize; }
05022     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05023     {
05024       StrokeAndFillPath( dc );
05025     }
05026 #ifdef ENABLE_EDITING
05027 
05030     void edit ( void ) const
05031     {
05032       printf( "*STROKEANDFILLPATH*\n" );
05033       edit_rectl( "rclBounds", rclBounds );
05034     }
05035 #endif /* ENABLE_EDITING */
05036   };
05038 
05041   class EMRBEGINPATH : public METARECORD, ::EMRBEGINPATH {
05042   public:
05046     EMRBEGINPATH ( void )
05047     {
05048       emr.iType = EMR_BEGINPATH;
05049       emr.nSize = sizeof( ::EMRBEGINPATH );
05050     }
05055     EMRBEGINPATH ( DATASTREAM& ds )
05056     {
05057       ds >> emr;
05058     }
05062     bool serialize ( DATASTREAM ds )
05063     {
05064       ds << emr;
05065       return true;
05066     }
05070     int size ( void ) const { return emr.nSize; }
05076     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05077     {
05078       BeginPath( dc );
05079     }
05080 #ifdef ENABLE_EDITING
05081 
05084     void edit ( void ) const
05085     {
05086       printf( "*BEGINPATH*\n" );
05087     }
05088 #endif /* ENABLE_EDITING */
05089   };
05091 
05094   class EMRENDPATH : public METARECORD, ::EMRENDPATH {
05095   public:
05099     EMRENDPATH ( void )
05100     {
05101       emr.iType = EMR_ENDPATH;
05102       emr.nSize = sizeof( ::EMRENDPATH );
05103     }
05108     EMRENDPATH ( DATASTREAM& ds )
05109     {
05110       ds >> emr;
05111     }
05115     bool serialize ( DATASTREAM ds )
05116     {
05117       ds << emr;
05118       return true;
05119     }
05123     int size ( void ) const { return emr.nSize; }
05129     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05130     {
05131       EndPath( dc );
05132     }
05133 #ifdef ENABLE_EDITING
05134 
05137     void edit ( void ) const
05138     {
05139       printf( "*ENDPATH*\n" );
05140     }
05141 #endif /* ENABLE_EDITING */
05142   };
05144 
05147   class EMRCLOSEFIGURE : public METARECORD, ::EMRCLOSEFIGURE {
05148   public:
05152     EMRCLOSEFIGURE ( void )
05153     {
05154       emr.iType = EMR_CLOSEFIGURE;
05155       emr.nSize = sizeof( ::EMRCLOSEFIGURE );
05156     }
05161     EMRCLOSEFIGURE ( DATASTREAM& ds )
05162     {
05163       ds >> emr;
05164     }
05168     bool serialize ( DATASTREAM ds )
05169     {
05170       ds << emr;
05171       return true;
05172     }
05176     int size ( void ) const { return emr.nSize; }
05182     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05183     {
05184       CloseFigure( dc );
05185     }
05186 #ifdef ENABLE_EDITING
05187 
05190     void edit ( void ) const
05191     {
05192       printf( "*CLOSEFIGURE*\n" );
05193     }
05194 #endif /* ENABLE_EDITING */
05195   };
05197 
05201   class EMRSAVEDC : public METARECORD, ::EMRSAVEDC {
05202   public:
05206     EMRSAVEDC ( void )
05207     {
05208       emr.iType = EMR_SAVEDC;
05209       emr.nSize = sizeof( ::EMRSAVEDC );
05210     }
05215     EMRSAVEDC ( DATASTREAM& ds )
05216     {
05217       ds >> emr;
05218     }
05222     bool serialize ( DATASTREAM ds )
05223     {
05224       ds << emr;
05225       return true;
05226     }
05230     int size ( void ) const { return emr.nSize; }
05236     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05237     {
05238       SaveDC( dc );
05239     }
05240 #ifdef ENABLE_EDITING
05241 
05244     void edit ( void ) const
05245     {
05246       printf( "*SAVEDC*\n" );
05247     }
05248 #endif /* ENABLE_EDITING */
05249   };
05251 
05254   class EMRRESTOREDC : public METARECORD, ::EMRRESTOREDC {
05255   public:
05259     EMRRESTOREDC ( INT n )
05260     {
05261       emr.iType = EMR_RESTOREDC;
05262       emr.nSize = sizeof( ::EMRRESTOREDC );
05263       iRelative = n;
05264     }
05269     EMRRESTOREDC ( DATASTREAM& ds )
05270     {
05271       ds >> emr >> iRelative;
05272     }
05276     bool serialize ( DATASTREAM ds )
05277     {
05278       ds << emr << iRelative;
05279       return true;
05280     }
05284     int size ( void ) const { return emr.nSize; }
05290     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05291     {
05292       RestoreDC( dc, iRelative );
05293     }
05294 #ifdef ENABLE_EDITING
05295 
05298     void edit ( void ) const
05299     {
05300       printf( "*RESTOREDC*\n" );
05301       printf( "\tiRelative: %ld\n", iRelative );
05302     }
05303 #endif /* ENABLE_EDITING */
05304   };
05306 
05309   class EMRSETMETARGN : public METARECORD, ::EMRSETMETARGN {
05310   public:
05314     EMRSETMETARGN ( void )
05315     {
05316       emr.iType = EMR_SETMETARGN;
05317       emr.nSize = sizeof( ::EMRSETMETARGN );
05318     }
05323     EMRSETMETARGN ( DATASTREAM& ds )
05324     {
05325       ds >> emr;
05326     }
05330     bool serialize ( DATASTREAM ds )
05331     {
05332       ds << emr;
05333       return true;
05334     }
05338     int size ( void ) const { return emr.nSize; }
05344     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05345     {
05346       SetMetaRgn( dc );
05347     }
05348 #ifdef ENABLE_EDITING
05349 
05352     void edit ( void ) const
05353     {
05354       printf( "*SETMETARGN*\n" );
05355     }
05356 #endif /* ENABLE_EDITING */
05357   };
05358 
05360 
05363   class PEN : public GRAPHICSOBJECT, public LOGPEN {
05364   public:
05368     PEN ( const LOGPEN* lpen )
05369     {
05370       lopnStyle = lpen->lopnStyle;
05371       lopnWidth = lpen->lopnWidth;
05372       lopnColor = lpen->lopnColor;
05373     }
05377     OBJECTTYPE getType ( void ) const { return O_PEN; }
05384     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
05385     {
05386       contexts[dc] = emf_handle;
05387       return new EMRCREATEPEN( this, emf_handle );
05388     }
05389   };
05390 
05392 
05395   class EXTPEN : public GRAPHICSOBJECT, public EXTLOGPEN {
05396   public:
05400     EXTPEN ( const EXTLOGPEN* lpen )
05401     {
05402       elpPenStyle = lpen->elpPenStyle;
05403       elpWidth = lpen->elpWidth;
05404       elpBrushStyle = lpen->elpBrushStyle;
05405       elpColor = lpen->elpColor;
05406       elpHatch = lpen->elpHatch;
05407       elpNumEntries = 0;
05408       elpStyleEntry[0] = 0;
05409     }
05413     OBJECTTYPE getType ( void ) const { return O_EXTPEN; }
05420     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
05421     {
05422       contexts[dc] = emf_handle;
05423       return new EMREXTCREATEPEN( this, emf_handle );
05424     }
05425   };
05426 
05428 
05431   class BRUSH : public GRAPHICSOBJECT, public LOGBRUSH {
05432   public:
05436     BRUSH ( const LOGBRUSH* lbrush )
05437     {
05438       lbStyle = lbrush->lbStyle;
05439       lbColor = lbrush->lbColor;
05440       lbHatch = lbrush->lbHatch;
05441     }
05445     OBJECTTYPE getType ( void ) const { return O_BRUSH; }
05452     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
05453     {
05454       contexts[dc] = emf_handle;
05455       return new EMRCREATEBRUSHINDIRECT( this, emf_handle );
05456     }
05457   };
05458 
05460 
05463   class FONT : public GRAPHICSOBJECT, public EXTLOGFONTW {
05464   public:
05468     FONT ( const LOGFONTW* lfont )
05469     {
05470       this->elfLogFont = *lfont;
05471       // There are a lot more entries in the EXTLOGFONTW structure than
05472       // the API has values for, so we invent them here
05473       memset( &elfFullName, 0, sizeof elfFullName );
05474       memset( &elfStyle, 0, sizeof elfStyle );
05475       elfVersion = ELF_VERSION;
05476       elfStyleSize = 0;
05477       elfMatch = 0;
05478       elfReserved = 0;
05479       memset( &elfVendorId, 0, sizeof elfVendorId );
05480       elfCulture = ELF_CULTURE_LATIN;
05481       memset( &elfPanose, 1, sizeof(PANOSE) );
05482     }
05486     OBJECTTYPE getType ( void ) const { return O_FONT; }
05493     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
05494     {
05495       contexts[dc] = emf_handle;
05496       return new EMREXTCREATEFONTINDIRECTW( this, emf_handle );
05497     }
05498   };
05499 
05501 
05504   class PALETTE : public GRAPHICSOBJECT, public LOGPALETTE {
05505   public:
05509     PALETTE ( const LOGPALETTE* lpalette )
05510     {
05511       (void)lpalette;
05512       palVersion = 0;
05513       palNumEntries = 0;
05514       PALETTEENTRY zero_entry = { 0, 0, 0, 0 };
05515       palPalEntry[0] = zero_entry;
05516     }
05520     OBJECTTYPE getType ( void ) const { return O_PALETTE; }
05527     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
05528     {
05529       contexts[dc] = emf_handle;
05530       return new EMRCREATEPALETTE( this, emf_handle );
05531     }
05532   };
05533 
05535 
05541   class METAFILEDEVICECONTEXT : public OBJECT {
05549     void init ( const RECT* size, LPCWSTR description_w ) {
05550 
05551       // Evidently, metafile handles are numbered from 1, so don't
05552       // ever use 0.
05553 
05554       handles.push_back( true );
05555 
05556       // Keep some of our graphics state in a header record
05557 
05558       header = new ENHMETAHEADER ( description_w );
05559       records.push_back( header );
05560 
05561       // Compute the size and position of the metafile on the "page"
05562 
05563       if ( size ) {
05564         update_frame = false;
05565 
05566         header->rclFrame.left = size->left;
05567         header->rclFrame.top = size->top;
05568         header->rclFrame.right = size->right;
05569         header->rclFrame.bottom = size->bottom;
05570 
05571         header->rclBounds.left =
05572           size->left * header->szlDevice.cx / ( header->szlMillimeters.cx * 100 );
05573         header->rclBounds.top =
05574           size->top * header->szlDevice.cy / ( header->szlMillimeters.cy * 100 );
05575         header->rclBounds.right =
05576           size->right * header->szlDevice.cx / ( header->szlMillimeters.cx * 100 );
05577         header->rclBounds.bottom =
05578           size->bottom * header->szlDevice.cy / ( header->szlMillimeters.cy * 100 );
05579       }
05580       else {
05581         update_frame = true;
05582 
05583         header->rclBounds.left = -10;
05584         header->rclBounds.top = -10;
05585         header->rclBounds.right = 10;
05586         header->rclBounds.bottom = 10;
05587 
05588         header->rclFrame.left = (LONG)floor( (float)header->rclBounds.left *
05589           header->szlMillimeters.cx * 100 / header->szlDevice.cx );
05590         header->rclFrame.top = (LONG)floor( (float)header->rclBounds.top *
05591           header->szlMillimeters.cy * 100 / header->szlDevice.cy );
05592         header->rclFrame.right = (LONG)ceil( (float)header->rclBounds.right *
05593           header->szlMillimeters.cx * 100 / header->szlDevice.cx );
05594         header->rclFrame.bottom = (LONG)ceil( (float)header->rclBounds.bottom *
05595           header->szlMillimeters.cy * 100 / header->szlDevice.cy );
05596       }
05597 
05598       // Some default graphics state (are they really, though?)
05599 
05600       SIZEL default_resolution = { RESOLUTION, RESOLUTION };
05601       resolution = default_resolution;
05602       SIZEL default_viewport_ext = { 1, 1 };
05603       viewport_ext = default_viewport_ext;
05604       POINT default_viewport_org = { 0, 0 };
05605       viewport_org = default_viewport_org;
05606       SIZEL default_window_ext = { 1, 1 };
05607       window_ext = default_window_ext;
05608       POINT default_window_org = { 0, 0 };
05609       window_org = default_window_org;
05610 
05611       min_device_point = viewport_org;
05612       max_device_point = viewport_org;
05613 
05614       pen = (PEN*)globalObjects.find( BLACK_PEN | ENHMETA_STOCK_OBJECT );
05615       brush = (BRUSH*)globalObjects.find( BLACK_BRUSH | ENHMETA_STOCK_OBJECT );
05616       font = (FONT*)globalObjects.find( DEVICE_DEFAULT_FONT | ENHMETA_STOCK_OBJECT);
05617       palette = (PALETTE*)globalObjects.find( DEFAULT_PALETTE|ENHMETA_STOCK_OBJECT);
05618 
05619       text_alignment = TA_BASELINE;
05620       text_color = RGB(0,0,0);
05621       bk_color = RGB(0xff,0xff,0xff);
05622       bk_mode = OPAQUE;
05623       polyfill_mode = ALTERNATE;
05624       map_mode = MM_TEXT;
05625 
05626       handle = globalObjects.add( this );
05627     }
05628 
05629   public:
05633     ::FILE* fp;
05638     DATASTREAM ds;
05642     ENHMETAHEADER* header;
05646     std::vector< EMF::METARECORD* > records;
05647 
05648     // Keep a small set of graphics state information
05649     SIZEL resolution;           
05650     SIZEL viewport_ext;         
05651     POINT viewport_org;         
05652     SIZEL window_ext;           
05653     POINT window_org;           
05654     bool update_frame;          
05655     POINT min_device_point;     
05656     POINT max_device_point;     
05657     POINT point;                
05658     PEN* pen;                   
05659     BRUSH* brush;               
05660     FONT* font;                 
05661     PALETTE* palette;           
05662     UINT text_alignment;        
05663     COLORREF text_color;        
05664     COLORREF bk_color;          
05665     INT bk_mode;                
05666     INT polyfill_mode;          
05667     INT map_mode;               
05668 
05674     std::vector< bool > handles;
05675 
05681     std::map< HGDIOBJ, HGDIOBJ > emf_handles;
05682 
05693       METAFILEDEVICECONTEXT ( FILE* fp_, const RECT* size,
05694                               LPCWSTR description_w )
05695         : fp(fp_), ds( fp_ )
05696     {
05697           init( size, description_w );
05698     }
05703     virtual ~METAFILEDEVICECONTEXT ( )
05704     {
05705       // Purge all the metarecords (if there are any) {this include the
05706       // header record, too}
05707       if ( records.size() > 0 )
05708         deleteMetafile();
05709     }
05713     OBJECTTYPE getType ( void ) const { return O_METAFILEDEVICECONTEXT; }
05718     DWORD nextHandle ( void )
05719     {
05720       for ( unsigned int i = 1; i < handles.size(); i++ ) {
05721         if ( !handles[i] ) {
05722           handles[i] = true;
05723           return i;
05724         }
05725       }
05726       handles.push_back( true );
05727       // Well, it appears that even StockObject handles count for something.
05728       // Not sure what the right value here is, then.
05729       header->nHandles = handles.size();
05730       return handles.size()-1;
05731     }
05735     void clearHandle ( DWORD handle )
05736     {
05737       handles[handle] = false;
05738     }
05744     void appendRecord ( METARECORD* record )
05745     {
05746       records.push_back( record );
05747 
05748       header->nBytes += record->size();
05749       header->nRecords++;
05750     }
05756     void appendHandle ( METARECORD* record )
05757     {
05758       records.push_back( record );
05759 
05760       header->nBytes += record->size();
05761       header->nRecords++;
05762     }
05767     void deleteMetafile ( void )
05768     {
05769       for ( std::vector<METARECORD*>::const_iterator r = records.begin();
05770             r != records.end();
05771             r++ ) {
05772         delete *r;
05773       }
05774       records.clear();
05775     }
05780     void mergePoint ( const LONG& x, const LONG& y )
05781     {
05782       POINT p;
05783       p.x = x;
05784       p.y = y;
05785       mergePoint( p );
05786     }
05791     void mergePoint( const POINT& p )
05792     {
05793       POINT device_point;
05794 
05795       // *** Note, it's possible for the global transformation matrix to
05796       // affect this too. ***
05797 
05798       device_point.x = (LONG)( (float)( p.x - window_org.x ) / window_ext.cx *
05799         viewport_ext.cx + viewport_org.x );
05800 
05801       device_point.y = (LONG)( (float)( p.y - window_org.y ) / window_ext.cy *
05802         viewport_ext.cy + viewport_org.y );
05803 
05804       // If the user didn't specify a bounding rectangle in the constructor,
05805       // compute one from this data, too.
05806       if ( device_point.x < min_device_point.x ) {
05807         min_device_point.x = device_point.x;
05808         if ( update_frame ) {
05809           header->rclBounds.left = min_device_point.x - 10;
05810           header->rclFrame.left = (LONG)floor( (float)header->rclBounds.left *
05811             header->szlMillimeters.cx * 100 / header->szlDevice.cx );
05812         }
05813       }
05814       else if ( device_point.x > max_device_point.x ) {
05815         max_device_point.x = device_point.x;
05816         if ( update_frame ) {
05817           header->rclBounds.right = max_device_point.x + 10;
05818           header->rclFrame.right = (LONG)ceil( (float)header->rclBounds.right *
05819             header->szlMillimeters.cx * 100 / header->szlDevice.cx );
05820         }
05821       }
05822 
05823       if ( device_point.y < min_device_point.y ) {
05824         min_device_point.y = device_point.y;
05825         if ( update_frame ) {
05826           header->rclBounds.top = min_device_point.y - 10;
05827           header->rclFrame.top = (LONG)floor( (float)header->rclBounds.top *
05828             header->szlMillimeters.cy * 100 / header->szlDevice.cy );
05829         }
05830       }
05831       else if ( device_point.y > max_device_point.y ) {
05832         max_device_point.y = device_point.y;
05833         if ( update_frame ) {
05834           header->rclBounds.bottom = max_device_point.y + 10;
05835           header->rclFrame.bottom = (LONG)ceil( (float)header->rclBounds.bottom *
05836             header->szlMillimeters.cy * 100 / header->szlDevice.cy );
05837         }
05838       }
05839     }
05840   };
05841 
05842 } // close EMF namespace
05843 
05844 #endif /* _LIBEMF_H */

Generated at Mon Jan 13 21:34:19 2003 for EMF by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001