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 43 2002-02-04 20:57:04Z allen $
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 <emf.h>
00032 
00033 #include <wine/w16.h>
00034 
00035 namespace EMF {
00040   const int XMAX_PIXELS = 1024; /*(INT_MAX)*/
00045   const int YMAX_PIXELS = 768; /*(INT_MAX)*/
00051   const int XMAX_MM = 320;
00057   const int YMAX_MM = 240;
00061   const int RESOLUTION = 96;
00065   static inline int ROUND_TO_LONG ( int n ) { return ((n+3)/4)*4; }
00066 
00068 
00073   struct WCHARSTR {
00074     WCHAR *const string_;       
00075     const int length_;          
00076 
00081     WCHARSTR ( WCHAR *const string, const int length )
00082       : string_( string ), length_( length ) {}
00083   };
00084 
00086 
00091   struct CHARSTR {
00092     CHAR *const string_;        
00093     const int length_;          
00094 
00099     CHARSTR ( CHAR *const string, const int length )
00100       : string_( string ), length_( length ) {}
00101   };
00102 
00104 
00108   struct BYTEARRAY {
00109     BYTE *const array_;         
00110     const int n_;               
00111 
00116     BYTEARRAY ( BYTE *const array, const int n )
00117       : array_( array ), n_( n ) {}
00118   };
00119 
00121 
00124   struct POINTLARRAY {
00125     POINTL *const points_;      
00126     const DWORD n_;             
00127 
00132     POINTLARRAY ( POINTL *const points, const DWORD n )
00133       : points_( points ), n_( n ) {}
00134   };
00135 
00137 
00140   struct POINT16ARRAY {
00141     POINT16 *const points_;     
00142     const DWORD n_;             
00143 
00148     POINT16ARRAY ( POINT16 *const points, const DWORD n )
00149       : points_( points ), n_( n ) {}
00150   };
00151 
00153 
00156   struct INTARRAY {
00157     INT *const ints_;           
00158     const DWORD n_;             
00159 
00164     INTARRAY ( INT *const ints, const DWORD n )
00165       : ints_( ints ), n_( n ) {}
00166   };
00167 
00169 
00172   struct DWORDARRAY {
00173     DWORD *const dwords_;       
00174     const DWORD n_;             
00175 
00180     DWORDARRAY ( DWORD *const dwords, const DWORD n )
00181       : dwords_( dwords ), n_( n ) {}
00182   };
00183 
00185 
00188   struct PADDING {
00189     static const char padding_[4]; 
00190     const int size_;            
00191 
00195     PADDING ( const int size ) : size_( size ) {}
00196   };
00197   
00199 
00206   class DATASTREAM {
00207     bool swap_;
00208     ::FILE* fp_;
00209 
00210     static bool bigEndian ( void );
00211   public:
00217     DATASTREAM ( ::FILE* fp = 0 ) : swap_( bigEndian() ), fp_( fp ) {}
00222     void setStream ( ::FILE* fp ) { fp_ = fp; }
00227     DATASTREAM& operator<< ( const BYTE& byte )
00228     {
00229       fwrite( &byte, sizeof(BYTE), 1, fp_ );
00230       return *this;
00231     }
00236     DATASTREAM& operator>> ( BYTE& byte )
00237     {
00238       fread( &byte, sizeof(BYTE), 1, fp_ );
00239       return *this;
00240     }
00245     DATASTREAM& operator<< ( const WORD& word )
00246     {
00247       if ( swap_ ) {
00248         unsigned char const * p = (unsigned char const*)&word;
00249         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00250         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00251       }
00252       else
00253         fwrite( &word, sizeof(WORD), 1, fp_ );
00254       return *this;
00255     }
00260     DATASTREAM& operator>> ( WORD& word )
00261     {
00262       if ( swap_ ) {
00263         unsigned char* p = (unsigned char*)&word;
00264         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00265         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00266       }
00267       else
00268         fread( &word, sizeof(WORD), 1, fp_ );
00269       return *this;
00270     }
00275     DATASTREAM& operator<< ( const INT16& word )
00276     {
00277       if ( swap_ ) {
00278         unsigned char const * p = (unsigned char const*)&word;
00279         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00280         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00281       }
00282       else
00283         fwrite( &word, sizeof(INT16), 1, fp_ );
00284       return *this;
00285     }
00290     DATASTREAM& operator>> ( INT16& word )
00291     {
00292       if ( swap_ ) {
00293         unsigned char* p = (unsigned char*)&word;
00294         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00295         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00296       }
00297       else
00298         fread( &word, sizeof(INT16), 1, fp_ );
00299       return *this;
00300     }
00305     DATASTREAM& operator<< ( const DWORD& dword )
00306     {
00307       if ( swap_ ) {
00308         unsigned char const* p = (unsigned char const*)&dword;
00309         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00310         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00311         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00312         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00313       }
00314       else
00315         fwrite( &dword, sizeof(DWORD), 1, fp_ );
00316       return *this;
00317     }
00322     DATASTREAM& operator>> ( DWORD& dword )
00323     {
00324       if ( swap_ ) {
00325         unsigned char* p = (unsigned char*)&dword;
00326         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00327         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00328         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00329         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00330       }
00331       else
00332         fread( &dword, sizeof(DWORD), 1, fp_ );
00333       return *this;
00334     }
00339     DATASTREAM& operator<< ( const LONG& long_ )
00340     {
00341       if ( swap_ ) {
00342         unsigned char const* p = (unsigned char const*)&long_;
00343         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00344         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00345         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00346         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00347       }
00348       else
00349         fwrite( &long_, sizeof(LONG), 1, fp_ );
00350       return *this;
00351     }
00356     DATASTREAM& operator>> ( LONG& long_ )
00357     {
00358       if ( swap_ ) {
00359         unsigned char* p = (unsigned char*)&long_;
00360         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00361         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00362         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00363         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00364       }
00365       else
00366         fread( &long_, sizeof(LONG), 1, fp_ );
00367       return *this;
00368     }
00373     DATASTREAM& operator<< ( const INT& int_ )
00374     {
00375       if ( swap_ ) {
00376         unsigned char const* p = (unsigned char const*)&int_;
00377         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00378         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00379         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00380         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00381       }
00382       else
00383         fwrite( &int_, sizeof(INT), 1, fp_ );
00384       return *this;
00385     }
00390     DATASTREAM& operator>> ( INT& int_ )
00391     {
00392       if ( swap_ ) {
00393         unsigned char* p = (unsigned char*)&int_;
00394         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00395         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00396         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00397         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00398       }
00399       else
00400         fread( &int_, sizeof(INT), 1, fp_ );
00401       return *this;
00402     }
00407     DATASTREAM& operator<< ( const UINT& uint )
00408     {
00409       if ( swap_ ) {
00410         unsigned char const* p = (unsigned char const*)&uint;
00411         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00412         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00413         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00414         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00415       }
00416       else
00417         fwrite( &uint, sizeof(UINT), 1, fp_ );
00418       return *this;
00419     }
00424     DATASTREAM& operator>> ( UINT& uint )
00425     {
00426       if ( swap_ ) {
00427         unsigned char* p = (unsigned char*)&uint;
00428         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00429         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00430         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00431         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00432       }
00433       else
00434         fread( &uint, sizeof(UINT), 1, fp_ );
00435       return *this;
00436     }
00441     DATASTREAM& operator<< ( const FLOAT& float_ )
00442     {
00443       if ( swap_ ) {
00444         unsigned char const* p = (unsigned char const*)&float_;
00445         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00446         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00447         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00448         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00449       }
00450       else
00451         fwrite( &float_, sizeof(FLOAT), 1, fp_ );
00452       return *this;
00453     }
00458     DATASTREAM& operator>> ( FLOAT& float_ )
00459     {
00460       if ( swap_ ) {
00461         unsigned char* p = (unsigned char*)&float_;
00462         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00463         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00464         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00465         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00466       }
00467       else
00468         fread( &float_, sizeof(FLOAT), 1, fp_ );
00469       return *this;
00470     }
00475     DATASTREAM& operator<< ( const PADDING& padding )
00476     {
00477       if ( padding.size_ != 0 )
00478         fwrite( &padding.padding_, sizeof(CHAR), padding.size_, fp_ );
00479       return *this;
00480     }
00485     DATASTREAM& operator<< ( const RECTL& rectl )
00486     {
00487       *this << rectl.left << rectl.top << rectl.right << rectl.bottom;
00488       return *this;
00489     }
00494     DATASTREAM& operator>> ( RECTL& rectl )
00495     {
00496       *this >> rectl.left >> rectl.top >> rectl.right >> rectl.bottom;
00497       return *this;
00498     }
00503     DATASTREAM& operator<< ( const SIZEL& sizel )
00504     {
00505       *this << sizel.cx << sizel.cy;
00506       return *this;
00507     }
00512     DATASTREAM& operator>> ( SIZEL& sizel )
00513     {
00514       *this >> sizel.cx >> sizel.cy;
00515       return *this;
00516     }
00521     DATASTREAM& operator<< ( const WCHARSTR& wcharstr )
00522     {
00523       for ( int i = 0; i < wcharstr.length_; i++ )
00524         *this << wcharstr.string_[i];
00525       return *this;
00526     }
00531     DATASTREAM& operator>> ( WCHARSTR& wcharstr )
00532     {
00533       for ( int i = 0; i < wcharstr.length_; i++ )
00534         *this >> wcharstr.string_[i];
00535       return *this;
00536     }
00541     DATASTREAM& operator<< ( const CHARSTR& charstr )
00542     {
00543       fwrite( charstr.string_, sizeof(CHAR), charstr.length_, fp_ );
00544       return *this;
00545     }
00550     DATASTREAM& operator>> ( CHARSTR& charstr )
00551     {
00552       fread( charstr.string_, sizeof(CHAR), charstr.length_, fp_ );
00553       return *this;
00554     }
00559     DATASTREAM& operator<< ( const ::EMR& emr )
00560     {
00561       *this << emr.iType << emr.nSize;
00562       return *this;
00563     }
00568     DATASTREAM& operator>> ( ::EMR& emr )
00569     {
00570       *this >> emr.iType >> emr.nSize;
00571       return *this;
00572     }
00577     DATASTREAM& operator<< ( const POINT& point )
00578     {
00579       *this << point.x << point.y;
00580       return *this;
00581     }
00586     DATASTREAM& operator>> ( POINT& point )
00587     {
00588       *this >> point.x >> point.y;
00589       return *this;
00590     }
00595     DATASTREAM& operator<< ( const POINTL& pointl )
00596     {
00597       *this << pointl.x << pointl.y;
00598       return *this;
00599     }
00604     DATASTREAM& operator>> ( POINTL& pointl )
00605     {
00606       *this >> pointl.x >> pointl.y;
00607       return *this;
00608     }
00613     DATASTREAM& operator<< ( const POINT16& point )
00614     {
00615       *this << point.x << point.y;
00616       return *this;
00617     }
00622     DATASTREAM& operator>> ( POINT16& point )
00623     {
00624       *this >> point.x >> point.y;
00625       return *this;
00626     }
00631     DATASTREAM& operator<< ( const XFORM& xform )
00632     {
00633       *this << xform.eM11 << xform.eM12 << xform.eM21 << xform.eM22
00634             << xform.eDx << xform.eDy;
00635       return *this;
00636     }
00641     DATASTREAM& operator>> ( XFORM& xform )
00642     {
00643       *this >> xform.eM11 >> xform.eM12 >> xform.eM21 >> xform.eM22
00644             >> xform.eDx >> xform.eDy;
00645       return *this;
00646     }
00651     DATASTREAM& operator<< ( const BYTEARRAY& array )
00652     {
00653       fwrite( array.array_, sizeof(BYTE), array.n_, fp_ );
00654       return *this;
00655     }
00660     DATASTREAM& operator>> ( BYTEARRAY& array )
00661     {
00662       fread( array.array_, sizeof(BYTE), array.n_, fp_ );
00663       return *this;
00664     }
00669     DATASTREAM& operator<< ( const POINTLARRAY& array )
00670     {
00671       for ( unsigned int i = 0; i < array.n_; i++ )
00672         *this << array.points_[i];
00673       return *this;
00674     }
00679     DATASTREAM& operator>> ( POINTLARRAY& array )
00680     {
00681       for ( unsigned int i = 0; i < array.n_; i++ )
00682         *this >> array.points_[i];
00683       return *this;
00684     }
00689     DATASTREAM& operator<< ( const POINT16ARRAY& array )
00690     {
00691       for ( unsigned int i = 0; i < array.n_; i++ )
00692         *this << array.points_[i];
00693       return *this;
00694     }
00699     DATASTREAM& operator>> ( POINT16ARRAY& array )
00700     {
00701       for ( unsigned int i = 0; i < array.n_; i++ )
00702         *this >> array.points_[i];
00703       return *this;
00704     }
00709     DATASTREAM& operator<< ( const INTARRAY& array )
00710     {
00711       for ( unsigned int i = 0; i < array.n_; i++ )
00712         *this << array.ints_[i];
00713       return *this;
00714     }
00719     DATASTREAM& operator>> ( INTARRAY& array )
00720     {
00721       for ( unsigned int i = 0; i < array.n_; i++ )
00722         *this >> array.ints_[i];
00723       return *this;
00724     }
00729     DATASTREAM& operator<< ( const DWORDARRAY& array )
00730     {
00731       for ( unsigned int i = 0; i < array.n_; i++ )
00732         *this << array.dwords_[i];
00733       return *this;
00734     }
00739     DATASTREAM& operator>> ( DWORDARRAY& array )
00740     {
00741       for ( unsigned int i = 0; i < array.n_; i++ )
00742         *this >> array.dwords_[i];
00743       return *this;
00744     }
00749     DATASTREAM& operator<< ( const ::EMRTEXT& text )
00750     {
00751       *this << text.ptlReference << text.nChars << text.offString << text.fOptions
00752          << text.rcl << text.offDx;
00753       return *this;
00754     }
00759     DATASTREAM& operator>> ( ::EMRTEXT& text )
00760     {
00761       *this >> text.ptlReference >> text.nChars >> text.offString >> text.fOptions
00762             >> text.rcl >> text.offDx;
00763       return *this;
00764     }
00769     DATASTREAM& operator<< ( const LOGPEN& pen )
00770     {
00771       *this << pen.lopnStyle << pen.lopnWidth << pen.lopnColor;
00772       return *this;
00773     }
00778     DATASTREAM& operator>> ( LOGPEN& pen )
00779     {
00780       *this >> pen.lopnStyle >> pen.lopnWidth >> pen.lopnColor;
00781       return *this;
00782     }
00787     DATASTREAM& operator<< ( const EXTLOGPEN& pen )
00788     {
00789       // *** How big is this structure if there are no style entries? ***
00790       *this << pen.elpPenStyle << pen.elpWidth << pen.elpBrushStyle << pen.elpColor
00791             << pen.elpHatch << pen.elpNumEntries;
00792       return *this;
00793     }
00798     DATASTREAM& operator>> ( EXTLOGPEN& pen )
00799     {
00800       // *** How big is this structure if there are no style entries? ***
00801       *this >> pen.elpPenStyle >> pen.elpWidth >> pen.elpBrushStyle >> pen.elpColor
00802             >> pen.elpHatch >> pen.elpNumEntries;
00803       return *this;
00804     }
00809     DATASTREAM& operator<< ( const LOGBRUSH& brush )
00810     {
00811       *this << brush.lbStyle << brush.lbColor << brush.lbHatch;
00812       return *this;
00813     }
00818     DATASTREAM& operator>> ( LOGBRUSH& brush )
00819     {
00820       *this >> brush.lbStyle >> brush.lbColor >> brush.lbHatch;
00821       return *this;
00822     }
00827     DATASTREAM& operator<< ( const LOGFONTW& font )
00828     {
00829       *this << font.lfHeight << font.lfWidth << font.lfEscapement
00830             << font.lfOrientation << font.lfWeight << font.lfItalic
00831             << font.lfUnderline << font.lfStrikeOut << font.lfCharSet
00832             << font.lfOutPrecision << font.lfClipPrecision << font.lfQuality
00833             << font.lfPitchAndFamily
00834             << WCHARSTR( const_cast<WCHAR*const>(font.lfFaceName), LF_FACESIZE );
00835       return *this;
00836     }
00841     DATASTREAM& operator>> ( LOGFONTW& font )
00842     {
00843       WCHARSTR wFaceName( font.lfFaceName, LF_FACESIZE );
00844 
00845       *this >> font.lfHeight >> font.lfWidth >> font.lfEscapement
00846             >> font.lfOrientation >> font.lfWeight >> font.lfItalic
00847             >> font.lfUnderline >> font.lfStrikeOut >> font.lfCharSet
00848             >> font.lfOutPrecision >> font.lfClipPrecision >> font.lfQuality
00849             >> font.lfPitchAndFamily
00850             >> wFaceName;
00851       return *this;
00852     }
00857     DATASTREAM& operator<< ( const PANOSE& panose )
00858     {
00859       fwrite( &panose, sizeof(PANOSE), 1, fp_ );
00860       return *this;
00861     }
00866     DATASTREAM& operator>> ( PANOSE& panose )
00867     {
00868       fread( &panose, sizeof(PANOSE), 1, fp_ );
00869       return *this;
00870     }
00875     DATASTREAM& operator<< ( const EXTLOGFONTW& font )
00876     {
00877       *this << font.elfLogFont
00878             << WCHARSTR( const_cast<WCHAR*const>(font.elfFullName),
00879                          LF_FULLFACESIZE )
00880             << WCHARSTR( const_cast<WCHAR*const>(font.elfStyle), LF_FACESIZE )
00881             << font.elfVersion << font.elfStyleSize << font.elfMatch
00882             << font.elfReserved
00883             << BYTEARRAY( const_cast<BYTE*const>(font.elfVendorId),
00884                           ELF_VENDOR_SIZE )
00885             << font.elfCulture << font.elfPanose;
00886       return *this;
00887     }
00892     DATASTREAM& operator>> ( EXTLOGFONTW& font )
00893     {
00894       WCHARSTR wFullName( font.elfFullName, LF_FULLFACESIZE );
00895       WCHARSTR wStyle( font.elfStyle, LF_FACESIZE );
00896       BYTEARRAY bVendorId( font.elfVendorId, ELF_VENDOR_SIZE );
00897       *this >> font.elfLogFont
00898             >> wFullName >> wStyle
00899             >> font.elfVersion >> font.elfStyleSize >> font.elfMatch
00900             >> font.elfReserved >> bVendorId
00901             >> font.elfCulture >> font.elfPanose;
00902       return *this;
00903     }
00908     DATASTREAM& operator<< ( const LOGPALETTE& palette )
00909     {
00910       // *** How big is this structure if the palette is empty? ***
00911       *this << palette.palVersion << palette.palNumEntries;
00912       return *this;
00913     }
00918     DATASTREAM& operator>> ( LOGPALETTE& palette )
00919     {
00920       // *** How big is this structure if the palette is empty? ***
00921       *this >> palette.palVersion >> palette.palNumEntries;
00922       return *this;
00923     }
00924   };
00925 
00926   class METAFILEDEVICECONTEXT;
00927 
00929 
00935   class METARECORD {
00936   public:
00943     virtual void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const = 0;
00950     virtual bool serialize ( DATASTREAM ds ) = 0;
00956     virtual int size ( void ) const = 0;
00962     virtual ~METARECORD( ) { }
00963 #ifdef ENABLE_EDITING
00964 
00968     virtual void edit ( void ) const {}
00969 #endif
00970   };
00971 
00972 #ifdef ENABLE_EDITING
00973   /* Miscellaneous editing routines */
00974   inline void edit_rectl ( const char* tag, const RECTL& rectl )
00975   {
00976     printf( "\t%s\t: (%ld, %ld) - (%ld, %ld)\n", tag, rectl.left, rectl.top,
00977             rectl.right, rectl.bottom );
00978   }
00979 
00980   inline void edit_xform ( const char* tag, const XFORM& xform )
00981   {
00982     printf( "\t%s.eM11\t: %f\n", tag, xform.eM11 );
00983     printf( "\t%s.eM12\t: %f\n", tag, xform.eM12 );
00984     printf( "\t%s.eM21\t: %f\n", tag, xform.eM21 );
00985     printf( "\t%s.eM22\t: %f\n", tag, xform.eM22 );
00986     printf( "\t%s.eDx\t: %f\n", tag, xform.eDx );
00987     printf( "\t%s.eDy\t: %f\n", tag, xform.eDy );
00988   }
00989 
00990   inline void edit_color ( const char* tag, const COLORREF& color )
00991   {
00992     printf( "\t%s\t: R(0x%02lx) G(0x%02lx) B(0x%02lx)\n", tag,
00993             GetRValue( color ), GetGValue( color ), GetBValue( color ) );
00994   }
00995 
00996   inline void edit_sizel ( const char* tag, const SIZEL& size )
00997   {
00998     printf( "\t%s\t: (%ld, %ld)\n", tag, size.cx, size.cy );
00999   }
01000 
01001   inline void edit_pointl ( const char* tag, const POINTL& point )
01002   {
01003     printf( "\t%s\t: (%ld, %ld)\n", tag, point.x, point.y );
01004   }
01005 
01006   inline void edit_pointlarray ( const char* tag, const DWORD cptl,
01007                                   const POINTL* points )
01008   {
01009     printf( "\tcptl%s\t: %ld\n", tag, cptl );
01010     printf( "\taptl%s\t: ", tag );
01011     if ( cptl > 0 )
01012       printf( "%ld, %ld\n", points[0].x, points[0].y );
01013     else
01014       puts( "" );
01015     for ( DWORD i = 1; i < cptl; i++ )
01016       printf( "\t\t%s  %ld, %ld\n", tag, points[i].x, points[i].y );
01017   }
01018 
01019   inline void edit_point16array ( const char* tag, const unsigned int cpts,
01020                                   const POINT16* points )
01021   {
01022     printf( "\tcpts%s\t: %d\n", tag, cpts );
01023     printf( "\tapts%s\t: ", tag );
01024     if ( cpts > 0 )
01025       printf( "%d, %d\n", points[0].x, points[0].y );
01026     else
01027       puts( "" );
01028     for ( unsigned int i = 1; i < cpts; i++ )
01029       printf( "\t\t%s  %d, %d\n", tag, points[i].x, points[i].y );
01030   }
01031 
01032   inline void edit_pen_style ( const char* tag, DWORD style )
01033   {
01034     printf( "\t%s\t: ", tag );
01035     switch ( style & PS_STYLE_MASK ) {
01036     case PS_SOLID: printf( "PS_SOLID" ); break;
01037     case PS_DASH: printf( "PS_DASH" ); break;
01038     case PS_DOT: printf( "PS_DOT" ); break;
01039     case PS_DASHDOT: printf( "PS_DASHDOT" ); break;
01040     case PS_DASHDOTDOT: printf( "PS_DASHDOTDOT" ); break;
01041     case PS_NULL: printf( "PS_NULL" ); break;
01042     case PS_INSIDEFRAME: printf( "PS_INSIDEFRAME" ); break;
01043     case PS_USERSTYLE: printf( "PS_USERSTYLE" ); break;
01044     case PS_ALTERNATE: printf( "PS_ALTERNATE" ); break;
01045     }
01046     switch ( style & PS_ENDCAP_MASK ) {
01047     case PS_ENDCAP_ROUND: printf( " | PS_ENDCAP_ROUND" ); break;
01048     case PS_ENDCAP_SQUARE: printf( " | PS_ENDCAP_SQUARE" ); break;
01049     case PS_ENDCAP_FLAT: printf( " | PS_ENDCAP_FLAT" ); break;
01050     }
01051     switch ( style & PS_JOIN_MASK ) {
01052     case PS_JOIN_ROUND: printf( " | PS_JOIN_ROUND" ); break;
01053     case PS_JOIN_BEVEL: printf( " | PS_JOIN_BEVEL" ); break;
01054     case PS_JOIN_MITER: printf( " | PS_JOIN_MITER" ); break;
01055     }
01056     switch ( style & PS_TYPE_MASK ) {
01057     case PS_COSMETIC: printf( " | PS_COSMETIC" ); break;
01058     case PS_GEOMETRIC: printf( " | PS_GEOMETRIC" ); break;
01059     }
01060     printf( "\n" );
01061   }
01062 
01063   inline void edit_brush_style ( const char* tag, DWORD style )
01064   {
01065     printf( "\t%s\t: ", tag );
01066     switch ( style ) {
01067     case BS_SOLID: printf( "BS_SOLID" ); break;
01068     case BS_NULL: printf( "BS_NULL" ); break;
01069     case BS_HATCHED: printf( "BS_HATCHED" ); break;
01070     case BS_PATTERN: printf( "BS_PATTERN" ); break;
01071     case BS_INDEXED: printf( "BS_INDEXED" ); break;
01072     case BS_DIBPATTERN: printf( "BS_DIBPATTERN" ); break;
01073     case BS_DIBPATTERNPT: printf( "BS_DIBPATTERNPT" ); break;
01074     case BS_PATTERN8X8: printf( "BS_PATTERN8X8" ); break;
01075     case BS_DIBPATTERN8X8: printf( "BS_DIBPATTERN8X8" ); break;
01076     case BS_MONOPATTERN: printf( "BS_DIBPATTERN8X8" ); break;
01077     default: printf( "unknown(%ld)", style );
01078     }
01079     printf( "\n" );
01080   }
01081 
01082   inline void edit_brush_hatch ( const char* tag, DWORD hatch )
01083   {
01084     printf( "\t%s\t: ", tag );
01085     switch ( hatch ) {
01086     case HS_HORIZONTAL: printf( "HS_HORIZONTAL" ); break;
01087     case HS_VERTICAL: printf( "HS_VERTICAL" ); break;
01088     case HS_FDIAGONAL: printf( "HS_FDIAGONAL" ); break;
01089     case HS_BDIAGONAL: printf( "HS_BDIAGONAL" ); break;
01090     case HS_CROSS: printf( "HS_CROSS" ); break;
01091     case HS_DIAGCROSS: printf( "HS_DIAGCROSS" ); break;
01092     default: printf( "unknown(%ld)", hatch );
01093     }
01094     printf( "\n" );
01095   }
01096 #endif
01097 
01104   enum OBJECTTYPE { O_METAFILEDEVICECONTEXT     = OBJ_METADC,
01105                     O_FONT                      = OBJ_FONT,
01106                     O_PEN                       = OBJ_PEN,
01107                     O_EXTPEN                    = OBJ_EXTPEN,
01108                     O_BRUSH                     = OBJ_BRUSH,
01109                     O_PALETTE                   = OBJ_PAL };
01110 #if 0
01111 
01114   static char* typStr ( OBJECTTYPE type )
01115   {
01116     switch (type) {
01117     case O_METAFILEDEVICECONTEXT:
01118       return "metafile device context";
01119     case O_FONT:
01120       return "font";
01121     case O_PEN:
01122       return "pen";
01123     case O_EXTPEN:
01124       return "extended pen";
01125     case O_BRUSH:
01126       return "brush";
01127     case O_PALETTE:
01128       return "palette";
01129     }
01130     return "unknown object";
01131   }
01132 #endif
01133 
01134 
01139   class OBJECT {
01140   public:
01141     HGDIOBJ handle;             
01142 
01143     virtual ~OBJECT () {}
01148     OBJECT ( void ) : handle( 0 ) {}
01152     virtual OBJECTTYPE getType ( void ) const = 0;
01153   };
01154 
01156 
01161   class GRAPHICSOBJECT : public OBJECT {
01162   public:
01164     virtual ~GRAPHICSOBJECT () {}
01169     std::map< HDC, HGDIOBJ > contexts;
01175     virtual METARECORD* newEMR ( HDC dc, HGDIOBJ handle ) = 0;
01176   };
01177 
01178   typedef METARECORD*(*METARECORDCTOR)(DATASTREAM&);
01179 
01180   class GLOBALOBJECTS {
01184     std::vector<OBJECT*> objects;
01185 
01192     std::map< DWORD, METARECORDCTOR > new_records;
01193 
01194   public:
01195     GLOBALOBJECTS ( void );
01196     ~GLOBALOBJECTS ( void );
01197     HGDIOBJ add ( OBJECT* object );
01198     OBJECT* find ( const HGDIOBJ handle );
01199     void remove ( const OBJECT* object );
01200 
01201     std::vector<EMF::OBJECT*>::const_iterator begin ( void ) const
01202     { return objects.begin(); }
01203     std::vector<EMF::OBJECT*>::const_iterator end ( void ) const
01204     { return objects.end(); }
01205 
01206     METARECORDCTOR newRecord ( DWORD iType ) const;
01207 
01208     static EMF::METARECORD* new_eof ( DATASTREAM& ds );
01209     static EMF::METARECORD* new_setviewportorgex ( DATASTREAM& ds );
01210     static EMF::METARECORD* new_setwindoworgex ( DATASTREAM& ds );
01211     static EMF::METARECORD* new_setviewportextex ( DATASTREAM& ds );
01212     static EMF::METARECORD* new_setwindowextex ( DATASTREAM& ds );
01213     static EMF::METARECORD* new_scaleviewportextex ( DATASTREAM& ds );
01214     static EMF::METARECORD* new_scalewindowextex ( DATASTREAM& ds );
01215     static EMF::METARECORD* new_modifyworldtransform ( DATASTREAM& ds );
01216     static EMF::METARECORD* new_setworldtransform ( DATASTREAM& ds );
01217     static EMF::METARECORD* new_settextalign ( DATASTREAM& ds );
01218     static EMF::METARECORD* new_settextcolor ( DATASTREAM& ds );
01219     static EMF::METARECORD* new_setbkcolor ( DATASTREAM& ds );
01220     static EMF::METARECORD* new_setbkmode ( DATASTREAM& ds );
01221     static EMF::METARECORD* new_setpolyfillmode ( DATASTREAM& ds );
01222     static EMF::METARECORD* new_setmapmode ( DATASTREAM& ds );
01223     static EMF::METARECORD* new_selectobject ( DATASTREAM& ds );
01224     static EMF::METARECORD* new_deleteobject ( DATASTREAM& ds );
01225     static EMF::METARECORD* new_movetoex ( DATASTREAM& ds );
01226     static EMF::METARECORD* new_lineto ( DATASTREAM& ds );
01227     static EMF::METARECORD* new_arc ( DATASTREAM& ds );
01228     static EMF::METARECORD* new_arcto ( DATASTREAM& ds );
01229     static EMF::METARECORD* new_rectangle ( DATASTREAM& ds );
01230     static EMF::METARECORD* new_ellipse ( DATASTREAM& ds );
01231     static EMF::METARECORD* new_polyline ( DATASTREAM& ds );
01232     static EMF::METARECORD* new_polyline16 ( DATASTREAM& ds );
01233     static EMF::METARECORD* new_polygon ( DATASTREAM& ds );
01234     static EMF::METARECORD* new_polygon16 ( DATASTREAM& ds );
01235     static EMF::METARECORD* new_polypolygon ( DATASTREAM& ds );
01236     static EMF::METARECORD* new_polypolygon16 ( DATASTREAM& ds );
01237     static EMF::METARECORD* new_polybezier ( DATASTREAM& ds );
01238     static EMF::METARECORD* new_polybezier16 ( DATASTREAM& ds );
01239     static EMF::METARECORD* new_polybezierto ( DATASTREAM& ds );
01240     static EMF::METARECORD* new_polybezierto16 ( DATASTREAM& ds );
01241     static EMF::METARECORD* new_polylineto ( DATASTREAM& ds );
01242     static EMF::METARECORD* new_polylineto16 ( DATASTREAM& ds );
01243     static EMF::METARECORD* new_exttextouta ( DATASTREAM& ds );
01244     static EMF::METARECORD* new_setpixelv ( DATASTREAM& ds );
01245     static EMF::METARECORD* new_createpen ( DATASTREAM& ds );
01246     static EMF::METARECORD* new_extcreatepen ( DATASTREAM& ds );
01247     static EMF::METARECORD* new_createbrushindirect ( DATASTREAM& ds );
01248     static EMF::METARECORD* new_extcreatefontindirectw ( DATASTREAM& ds );
01249     static EMF::METARECORD* new_fillpath ( DATASTREAM& ds );
01250     static EMF::METARECORD* new_strokepath ( DATASTREAM& ds );
01251     static EMF::METARECORD* new_beginpath ( DATASTREAM& ds );
01252     static EMF::METARECORD* new_endpath ( DATASTREAM& ds );
01253     static EMF::METARECORD* new_closefigure ( DATASTREAM& ds );
01254     static EMF::METARECORD* new_savedc ( DATASTREAM& ds );
01255     static EMF::METARECORD* new_restoredc ( DATASTREAM& ds );
01256     static EMF::METARECORD* new_setmetargn ( DATASTREAM& ds );
01257   };
01258 
01259   extern GLOBALOBJECTS globalObjects;
01260 
01262 
01268   class ENHMETAHEADER : public METARECORD, public ::ENHMETAHEADER {
01269 
01270     LPWSTR description_w;
01271     int description_size;
01272 
01273   public:
01280     ENHMETAHEADER ( LPCWSTR description = 0 )
01281       : description_w( 0 ), description_size( 0 )
01282     {
01283       iType = EMR_HEADER;
01284       nSize = sizeof( ::ENHMETAHEADER );
01285 
01286       // Compute the bounds
01287       RECTL default_bounds = { 0, 0, 0, 0 };
01288       rclBounds = default_bounds;
01289       RECTL default_frame = { 0, 0, 0, 0 };
01290       rclFrame = default_frame;
01291       dSignature = ENHMETA_SIGNATURE;
01292       nVersion = 0x10000;
01293       nBytes = nSize;
01294       nRecords = 1;
01295       nHandles = 0;
01296       sReserved = 0;
01297       nDescription = 0;
01298       offDescription = 0;
01299       nPalEntries = 0;
01300       szlDevice.cx = XMAX_PIXELS;
01301       szlDevice.cy = YMAX_PIXELS;
01302       szlMillimeters.cx = XMAX_MM;
01303       szlMillimeters.cy = YMAX_MM;
01304       //
01305       cbPixelFormat = 0;
01306       offPixelFormat = 0;
01307       bOpenGL = FALSE;
01308       //
01309       szlMicrometers.cx = 1000 * szlMillimeters.cx;
01310       szlMicrometers.cy = 1000 * szlMillimeters.cy;
01311 
01312       if ( description ) {
01313         // Count the number of characters in the description
01314         int description_count = 0, nulls = 0;
01315         LPCWSTR description_p = description;
01316         while ( nulls < 3 ) {
01317           description_count++;
01318           if ( (*description_p++) == 0 ) nulls++;
01319         }
01320 
01321         // Make sure that the TOTAL record length will be a multiple of 4
01322 
01323         int record_size = ROUND_TO_LONG( sizeof( ::ENHMETAHEADER ) +
01324                                          sizeof( WCHAR ) * description_count );
01325         description_size =
01326           (record_size - sizeof( ::ENHMETAHEADER )) / sizeof( WCHAR );
01327 
01328         description_w = new WCHAR[ description_size ];
01329 
01330         memset( description_w, 0, sizeof(WCHAR) * description_size );
01331 
01332         for ( int i=0; i<description_count; i++ )
01333           description_w[i] = *description++;
01334 
01335         nSize = nBytes = record_size;
01336         nDescription = description_count;
01337         offDescription = sizeof( ::ENHMETAHEADER );
01338       }
01339     }
01340     
01344     ~ENHMETAHEADER ( )
01345     {
01346       if ( description_w ) delete[] description_w;
01347     }
01352     bool serialize ( DATASTREAM ds )
01353     {
01354       ds << iType << nSize
01355          << rclBounds << rclFrame
01356          << dSignature << nVersion << nBytes << nRecords << nHandles << sReserved
01357          << nDescription << offDescription << nPalEntries
01358          << szlDevice << szlMillimeters
01359          << cbPixelFormat << offPixelFormat << bOpenGL
01360          << szlMicrometers
01361          << WCHARSTR( description_w, description_size );
01362       return true;
01363     }
01367     bool unserialize ( DATASTREAM ds )
01368     {
01369       ds >> iType >> nSize
01370          >> rclBounds >> rclFrame
01371          >> dSignature >> nVersion >> nBytes >> nRecords >> nHandles >> sReserved
01372          >> nDescription >> offDescription >> nPalEntries
01373          >> szlDevice >> szlMillimeters;
01374 
01375       // Some elements of the metafile header were added at later dates
01376 
01377 #define OffsetOf( a, b ) ((unsigned int)(((char*)&(((::ENHMETAHEADER*)a)->b)) - \
01378 (char*)((::ENHMETAHEADER*)a)))
01379 
01380       if ( OffsetOf( this, szlMicrometers ) <= offDescription )
01381         ds >> cbPixelFormat >> offPixelFormat >> bOpenGL;
01382 
01383 #undef OffsetOf
01384 
01385       if ( sizeof(::ENHMETAHEADER) <= offDescription )
01386         ds >> szlMicrometers;
01387 
01388       // Should now probably check that the offset is correct...
01389 
01390       description_size = ( nSize - offDescription ) / sizeof(WCHAR);
01391       description_w = new WCHAR[ description_size ];
01392 
01393       WCHARSTR description( description_w, description_size );
01394 
01395       ds >> description;
01396 
01397       return true;
01398     }
01402     int size ( void ) const { return nSize; }
01408     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC /*dc*/ ) const
01409     {
01410       // Actually handled by the destination device context.
01411     }
01412 #ifdef ENABLE_EDITING
01413 
01416     void edit ( void ) const
01417     {
01418       printf( "*HEADER*\n" );
01419       printf( "\tiType\t\t\t: %ld\n", iType );
01420       printf( "\tnSize\t\t\t: %ld\n", nSize );
01421       edit_rectl( "rclBounds\t", rclBounds );
01422       edit_rectl( "rclFrame\t", rclFrame );
01423       printf( "\tdSignature\t\t: %.4s\n", (const char*)&dSignature );
01424       printf( "\tnVersion\t\t: 0x%x\n", (unsigned int)nVersion );
01425       printf( "\tnBytes\t\t\t: %ld\n", nBytes );
01426       printf( "\tnRecords\t\t: %ld\n", nRecords );
01427       printf( "\tnHandles\t\t: %d\n", nHandles );
01428       printf( "\tnDescription\t\t: %ld\n", nDescription );
01429       printf( "\toffDescription\t\t: %ld\n", offDescription );
01430       printf( "\tnPalEntries\t\t: %ld\n", nPalEntries );
01431       edit_sizel( "szlDevice\t", szlDevice );
01432       edit_sizel( "szlMillimeters\t", szlMillimeters );
01433 
01434       /* Make a crude guess as to the age of this file */
01435 #define OffsetOf( a, b ) ((unsigned int)(((const char*)&(((const ::ENHMETAHEADER*)a)->b)) - \
01436 (const char*)((const ::ENHMETAHEADER*)a)))
01437 
01438       if ( OffsetOf( this, cbPixelFormat ) <= offDescription ) {
01439         printf( "\tcbPixelFormat\t\t: %ld\n", cbPixelFormat );
01440         printf( "\toffPixelFormat\t\t: %ld\n", offPixelFormat );
01441         printf( "\tbOpenGL\t\t\t: %ld\n", bOpenGL );
01442 
01443         if ( sizeof(::ENHMETAHEADER) <= offDescription ) {
01444           edit_sizel( "szlMicrometers\t", szlMicrometers );
01445         }
01446       }
01447 
01448 #undef OffsetOf
01449 
01450       if ( nDescription != 0 ) {
01451 
01452         wchar_t last_w = 0;
01453         WCHAR* description = description_w;
01454 
01455         printf( "\tDescription:" );
01456 
01457         for ( DWORD i = 0; i < nDescription; i++ ) {
01458 
01459           wchar_t w = *description++; /* This is not true, really. UNICODE is not
01460                                        * glibc's wide character representation */
01461 
01462           if ( w != 0 ) {
01463             if ( last_w == 0 ) printf( "\n\t\t" );
01464             putchar( w );
01465           }
01466           
01467           last_w = w;
01468         }
01469         printf( "\n" );
01470       }
01471     }
01472 #endif /* ENABLE_EDITING */
01473   };
01474 
01476 
01481   class EMREOF : public METARECORD, ::EMREOF {
01482   public:
01486     EMREOF ( void )
01487     {
01488       emr.iType = EMR_EOF;
01489       emr.nSize = sizeof( ::EMREOF );
01490       nPalEntries = 0;
01491       offPalEntries = 0;
01492       nSizeLast = 0;
01493     }
01494 
01499     EMREOF ( DATASTREAM& ds )
01500     {
01501       ds >> emr >> nPalEntries >> offPalEntries >> nSizeLast;
01502     }
01503 
01507     bool serialize ( DATASTREAM ds )
01508     {
01509       ds << emr << nPalEntries << offPalEntries << nSizeLast;
01510       return true;
01511     }
01515     int size ( void ) const { return emr.nSize; }
01521     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC /*dc*/ ) const
01522     {
01523       // Actually handled by the destination device context.
01524     }
01525 #ifdef ENABLE_EDITING
01526 
01529     void edit ( void ) const
01530     {
01531       printf( "*EOF*\n" );
01532     }
01533 #endif /* ENABLE_EDITING */
01534   };
01535 
01537 
01542   class EMRSETVIEWPORTORGEX : public METARECORD, ::EMRSETVIEWPORTORGEX {
01543   public:
01548     EMRSETVIEWPORTORGEX ( INT x, INT y )
01549     {
01550       emr.iType = EMR_SETVIEWPORTORGEX;
01551       emr.nSize = sizeof( ::EMRSETVIEWPORTORGEX );
01552       ptlOrigin.x = x;
01553       ptlOrigin.y = y;
01554     }
01559     EMRSETVIEWPORTORGEX ( DATASTREAM& ds )
01560     {
01561       ds >> emr >> ptlOrigin;
01562     }
01566     bool serialize ( DATASTREAM ds )
01567     {
01568       ds << emr << ptlOrigin;
01569       return true;
01570     }
01574     int size ( void ) const { return emr.nSize; }
01580     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01581     {
01582       SetViewportOrgEx( dc, ptlOrigin.x, ptlOrigin.y, 0 );
01583     }
01584 #ifdef ENABLE_EDITING
01585 
01588     void edit ( void ) const
01589     {
01590       printf( "*SETVIEWPORTORGEX*\n" );
01591       edit_pointl( "ptlOrigin", ptlOrigin );
01592     }
01593 #endif /* ENABLE_EDITING */
01594   };
01595 
01597 
01604   class EMRSETWINDOWORGEX : public METARECORD, ::EMRSETWINDOWORGEX {
01605   public:
01610     EMRSETWINDOWORGEX ( INT x, INT y )
01611     {
01612       emr.iType = EMR_SETWINDOWORGEX;
01613       emr.nSize = sizeof( ::EMRSETWINDOWORGEX );
01614       ptlOrigin.x = x;
01615       ptlOrigin.y = y;
01616     }
01621     EMRSETWINDOWORGEX ( DATASTREAM& ds )
01622     {
01623       ds >> emr >> ptlOrigin;
01624     }
01628     bool serialize ( DATASTREAM ds )
01629     {
01630       ds << emr << ptlOrigin;
01631       return true;
01632     }
01636     int size ( void ) const { return emr.nSize; }
01642     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01643     {
01644       SetWindowOrgEx( dc, ptlOrigin.x, ptlOrigin.y, 0 );
01645     }
01646 #ifdef ENABLE_EDITING
01647 
01650     void edit ( void ) const
01651     {
01652       printf( "*SETWINDOWORGEX*\n" );
01653       edit_pointl( "ptlOrigin", ptlOrigin );
01654     }
01655 #endif /* ENABLE_EDITING */
01656   };
01657 
01659 
01664   class EMRSETVIEWPORTEXTEX : public METARECORD, ::EMRSETVIEWPORTEXTEX {
01665   public:
01670     EMRSETVIEWPORTEXTEX ( INT cx, INT cy )
01671     {
01672       emr.iType = EMR_SETVIEWPORTEXTEX;
01673       emr.nSize = sizeof( ::EMRSETVIEWPORTEXTEX );
01674       szlExtent.cx = cx;
01675       szlExtent.cy = cy;
01676     }
01681     EMRSETVIEWPORTEXTEX ( DATASTREAM& ds )
01682     {
01683       ds >> emr >> szlExtent;
01684     }
01688     bool serialize ( DATASTREAM ds )
01689     {
01690       ds << emr << szlExtent;
01691       return true;
01692     }
01696     int size ( void ) const { return emr.nSize; }
01702     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01703     {
01704       SetViewportExtEx( dc, szlExtent.cx, szlExtent.cy, 0 );
01705     }
01706 #ifdef ENABLE_EDITING
01707 
01710     void edit ( void ) const
01711     {
01712       printf( "*SETVIEWPORTEXTEX*\n" );
01713       edit_sizel( "szlExtent", szlExtent );
01714     }
01715 #endif /* ENABLE_EDITING */
01716   };
01717 
01719 
01724   class EMRSCALEVIEWPORTEXTEX : public METARECORD, ::EMRSCALEVIEWPORTEXTEX {
01725   public:
01732     EMRSCALEVIEWPORTEXTEX ( LONG x_num, LONG x_den, LONG y_num, LONG y_den )
01733     {
01734       emr.iType = EMR_SCALEVIEWPORTEXTEX;
01735       emr.nSize = sizeof( ::EMRSCALEVIEWPORTEXTEX );
01736       xNum = x_num;
01737       xDenom = x_den;
01738       yNum = y_num;
01739       yDenom = y_den;
01740     }
01745     EMRSCALEVIEWPORTEXTEX ( DATASTREAM& ds )
01746     {
01747       ds >> emr >> xNum >> xDenom >> yNum >> yDenom;
01748     }
01752     bool serialize ( DATASTREAM ds )
01753     {
01754       ds << emr << xNum << xDenom << yNum << yDenom;
01755       return true;
01756     }
01760     int size ( void ) const { return emr.nSize; }
01766     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01767     {
01768       ScaleViewportExtEx( dc, xNum, xDenom, yNum, yDenom, 0 );
01769     }
01770 #ifdef ENABLE_EDITING
01771 
01774     void edit ( void ) const
01775     {
01776       printf( "*SCALEVIEWPORTEXTEX*\n" );
01777       printf( "\txNum\t: %ld\n", xNum );
01778       printf( "\txDenom\t: %ld\n", xDenom );
01779       printf( "\tyNum\t: %ld\n", yNum );
01780       printf( "\tyDenom\t: %ld\n", yDenom );
01781     }
01782 #endif /* ENABLE_EDITING */
01783   };
01784 
01786 
01791   class EMRSETWINDOWEXTEX : public METARECORD, ::EMRSETWINDOWEXTEX {
01792   public:
01797     EMRSETWINDOWEXTEX ( INT cx, INT cy )
01798     {
01799       emr.iType = EMR_SETWINDOWEXTEX;
01800       emr.nSize = sizeof( ::EMRSETWINDOWEXTEX );
01801       szlExtent.cx = cx;
01802       szlExtent.cy = cy;
01803     }
01808     EMRSETWINDOWEXTEX ( DATASTREAM& ds )
01809     {
01810       ds >> emr >> szlExtent;
01811     }
01815     bool serialize ( DATASTREAM ds )
01816     {
01817       ds << emr << szlExtent;
01818       return true;
01819     }
01823     int size ( void ) const { return emr.nSize; }
01829     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01830     {
01831       SetWindowExtEx( dc, szlExtent.cx, szlExtent.cy, 0 );
01832     }
01833 #ifdef ENABLE_EDITING
01834 
01837     void edit ( void ) const
01838     {
01839       printf( "*SETWINDOWEXTEX*\n" );
01840       edit_sizel( "szlExtent", szlExtent );
01841     }
01842 #endif /* ENABLE_EDITING */
01843   };
01844 
01846 
01851   class EMRSCALEWINDOWEXTEX : public METARECORD, ::EMRSCALEWINDOWEXTEX {
01852   public:
01859     EMRSCALEWINDOWEXTEX ( LONG x_num, LONG x_den, LONG y_num, LONG y_den )
01860     {
01861       emr.iType = EMR_SCALEWINDOWEXTEX;
01862       emr.nSize = sizeof( ::EMRSCALEWINDOWEXTEX );
01863       xNum = x_num;
01864       xDenom = x_den;
01865       yNum = y_num;
01866       yDenom = y_den;
01867     }
01872     EMRSCALEWINDOWEXTEX ( DATASTREAM& ds )
01873     {
01874       ds >> emr >> xNum >> xDenom >> yNum >> yDenom;
01875     }
01879     bool serialize ( DATASTREAM ds )
01880     {
01881       ds << emr << xNum << xDenom << yNum << yDenom;
01882       return true;
01883     }
01887     int size ( void ) const { return emr.nSize; }
01893     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01894     {
01895       ScaleWindowExtEx( dc, xNum, xDenom, yNum, yDenom, 0 );
01896     }
01897 #ifdef ENABLE_EDITING
01898 
01901     void edit ( void ) const
01902     {
01903       printf( "*SCALEWINDOWEXTEX*\n" );
01904       printf( "\txNum\t: %ld\n", xNum );
01905       printf( "\txDenom\t: %ld\n", xDenom );
01906       printf( "\tyNum\t: %ld\n", yNum );
01907       printf( "\tyDenom\t: %ld\n", yDenom );
01908     }
01909 #endif /* ENABLE_EDITING */
01910   };
01911 
01913 
01919   class EMRMODIFYWORLDTRANSFORM : public METARECORD, ::EMRMODIFYWORLDTRANSFORM {
01920   public:
01926     EMRMODIFYWORLDTRANSFORM ( const XFORM* transform, DWORD mode )
01927     {
01928       emr.iType = EMR_MODIFYWORLDTRANSFORM;
01929       emr.nSize = sizeof( ::EMRMODIFYWORLDTRANSFORM );
01930       xform = *transform;
01931       iMode = mode;
01932     }
01937     EMRMODIFYWORLDTRANSFORM ( DATASTREAM& ds )
01938     {
01939       ds >> emr >> xform >> iMode;
01940     }
01944     bool serialize ( DATASTREAM ds )
01945     {
01946       ds << emr << xform << iMode;
01947       return true;
01948     }
01952     int size ( void ) const { return emr.nSize; }
01958     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01959     {
01960       ModifyWorldTransform( dc, &xform, iMode );
01961     }
01962 #ifdef ENABLE_EDITING
01963 
01966     void edit ( void ) const
01967     {
01968       printf( "*MODIFYWORLDTRANSFORM*\n" );
01969       edit_xform( "xform", xform );
01970       printf( "\tiMode\t\t: " );
01971       switch ( iMode ) {
01972       case MWT_IDENTITY: printf( "MWT_IDENTITY\n" ); break;
01973       case MWT_LEFTMULTIPLY: printf( "MWT_LEFTMULTIPLY\n" ); break;
01974       case MWT_RIGHTMULTIPLY: printf( "MWT_RIGHTMULTIPLY\n" ); break;
01975       default: printf( "unknown(%ld)\n", iMode );
01976       }
01977     }
01978 #endif /* ENABLE_EDITING */
01979   };
01980 
01982 
01988   class EMRSETWORLDTRANSFORM : public METARECORD, ::EMRSETWORLDTRANSFORM {
01989   public:
01993     EMRSETWORLDTRANSFORM ( const XFORM* transform )
01994     {
01995       emr.iType = EMR_SETWORLDTRANSFORM;
01996       emr.nSize = sizeof( ::EMRSETWORLDTRANSFORM );
01997       xform = *transform;
01998     }
02003     EMRSETWORLDTRANSFORM ( DATASTREAM& ds )
02004     {
02005       ds >> emr >> xform;
02006     }
02010     bool serialize ( DATASTREAM ds )
02011     {
02012       ds << emr << xform;
02013       return true;
02014     }
02018     int size ( void ) const { return emr.nSize; }
02024     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02025     {
02026       SetWorldTransform( dc, &xform );
02027     }
02028 #ifdef ENABLE_EDITING
02029 
02032     void edit ( void ) const
02033     {
02034       printf( "*SETWORLDTRANSFORM*\n" );
02035       edit_xform( "xform", xform );
02036     }
02037 #endif /* ENABLE_EDITING */
02038   };
02039 
02041 
02044   class EMRSETTEXTALIGN : public METARECORD, ::EMRSETTEXTALIGN {
02045   public:
02049     EMRSETTEXTALIGN ( UINT mode )
02050     {
02051       emr.iType = EMR_SETTEXTALIGN;
02052       emr.nSize = sizeof( ::EMRSETTEXTALIGN );
02053       iMode = mode;
02054     }
02059     EMRSETTEXTALIGN ( DATASTREAM& ds )
02060     {
02061       ds >> emr >> iMode;
02062     }
02066     bool serialize ( DATASTREAM ds )
02067     {
02068       ds << emr << iMode;
02069       return true;
02070     }
02074     int size ( void ) const { return emr.nSize; }
02080     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02081     {
02082       SetTextAlign( dc, iMode );
02083     }
02084 #ifdef ENABLE_EDITING
02085 
02088     void edit ( void ) const
02089     {
02090       unsigned int known_bits = TA_BASELINE+TA_CENTER+TA_UPDATECP+TA_RTLREADING;
02091       unsigned int unknown_bits = ~known_bits;
02092 
02093       printf( "*SETTEXTALIGN*\n" );
02094       printf( "\tiMode\t: " );
02095       if ( iMode & TA_UPDATECP )
02096         printf( "TA_UPDATECP" );
02097       else
02098         printf( "TA_NOUPDATECP" );
02099       if ( iMode & TA_CENTER )
02100         printf( " | TA_CENTER" );
02101       else if ( iMode & TA_RIGHT )
02102         printf( " | TA_RIGHT" );
02103       else
02104         printf( " | TA_LEFT" );
02105       if ( iMode & TA_BASELINE )
02106         printf( " | TA_BASELINE" );
02107       else if ( iMode & TA_BOTTOM )
02108         printf( " | TA_BOTTOM" );
02109       else
02110         printf( " | TA_TOP" );
02111       if ( iMode & TA_RTLREADING )
02112         printf( " | TA_RTLREADING" );
02113       if ( iMode & unknown_bits )
02114         printf( " | unknown bits(0x%lx)", iMode & unknown_bits );
02115       printf( "\n" );
02116     }
02117 #endif /* ENABLE_EDITING */
02118   };
02119 
02121 
02124   class EMRSETTEXTCOLOR : public METARECORD, ::EMRSETTEXTCOLOR {
02125   public:
02129     EMRSETTEXTCOLOR ( COLORREF color )
02130     {
02131       emr.iType = EMR_SETTEXTCOLOR;
02132       emr.nSize = sizeof( ::EMRSETTEXTCOLOR );
02133       crColor = color;
02134     }
02139     EMRSETTEXTCOLOR ( DATASTREAM& ds )
02140     {
02141       ds >> emr >> crColor;
02142     }
02146     bool serialize ( DATASTREAM ds )
02147     {
02148       ds << emr << crColor;
02149       return true;
02150     }
02154     int size ( void ) const { return emr.nSize; }
02160     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02161     {
02162       SetTextColor( dc, crColor );
02163     }
02164 #ifdef ENABLE_EDITING
02165 
02168     void edit ( void ) const
02169     {
02170       printf( "*SETTEXTCOLOR*\n" );
02171       edit_color( "crColor", crColor );
02172     }
02173 #endif /* ENABLE_EDITING */
02174   };
02175 
02177 
02180   class EMRSETBKCOLOR : public METARECORD, ::EMRSETBKCOLOR {
02181   public:
02185     EMRSETBKCOLOR ( COLORREF color )
02186     {
02187       emr.iType = EMR_SETBKCOLOR;
02188       emr.nSize = sizeof( ::EMRSETBKCOLOR );
02189       crColor = color;
02190     }
02195     EMRSETBKCOLOR ( DATASTREAM& ds )
02196     {
02197       ds >> emr >> crColor;
02198     }
02202     bool serialize ( DATASTREAM ds )
02203     {
02204       ds << emr << crColor;
02205       return true;
02206     }
02210     int size ( void ) const { return emr.nSize; }
02216     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02217     {
02218       SetBkColor( dc, crColor );
02219     }
02220 #ifdef ENABLE_EDITING
02221 
02224     void edit ( void ) const
02225     {
02226       printf( "*SETBKCOLOR*\n" );
02227       edit_color( "crColor", crColor );
02228     }
02229 #endif /* ENABLE_EDITING */
02230   };
02231 
02233 
02237   class EMRSETBKMODE : public METARECORD, ::EMRSETBKMODE {
02238   public:
02242     EMRSETBKMODE ( DWORD mode )
02243     {
02244       emr.iType = EMR_SETBKMODE;
02245       emr.nSize = sizeof( ::EMRSETBKMODE );
02246       iMode = mode;
02247     }
02252     EMRSETBKMODE ( DATASTREAM& ds )
02253     {
02254       ds >> emr >> iMode;
02255     }
02259     bool serialize ( DATASTREAM ds )
02260     {
02261       ds << emr << iMode;
02262       return true;
02263     }
02267     int size ( void ) const { return emr.nSize; }
02273     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02274     {
02275       SetBkMode( dc, iMode );
02276     }
02277 #ifdef ENABLE_EDITING
02278 
02281     void edit ( void ) const
02282     {
02283       printf( "*SETBKMODE*\n" );
02284       printf( "\tiMode\t: " );
02285       switch ( iMode ) {
02286       case TRANSPARENT: printf( "TRANSPARENT\n" ); break;
02287       case OPAQUE: printf( "OPAQUE\n" ); break;
02288       default: printf( "unknown(%ld)\n", iMode );
02289       }
02290     }
02291 #endif /* ENABLE_EDITING */
02292   };
02293 
02295 
02298   class EMRSETPOLYFILLMODE : public METARECORD, ::EMRSETPOLYFILLMODE {
02299   public:
02303     EMRSETPOLYFILLMODE ( DWORD mode )
02304     {
02305       emr.iType = EMR_SETPOLYFILLMODE;
02306       emr.nSize = sizeof( ::EMRSETPOLYFILLMODE );
02307       iMode = mode;
02308     }
02313     EMRSETPOLYFILLMODE ( DATASTREAM& ds )
02314     {
02315       ds >> emr >> iMode;
02316     }
02320     bool serialize ( DATASTREAM ds )
02321     {
02322       ds << emr << iMode;
02323       return true;
02324     }
02328     int size ( void ) const { return emr.nSize; }
02334     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02335     {
02336       SetPolyFillMode( dc, iMode );
02337     }
02338 #ifdef ENABLE_EDITING
02339 
02342     void edit ( void ) const
02343     {
02344       printf( "*SETPOLYFILLMODE*\n" );
02345       printf( "\tiMode: " );
02346       switch ( iMode ) {
02347       case ALTERNATE: printf( "ALTERNATE\n" ); break;
02348       case WINDING: printf( "WINDING\n" ); break;
02349       default: printf( "unknown(%ld)\n", iMode );
02350       }
02351     }
02352 #endif /* ENABLE_EDITING */
02353   };
02354 
02356 
02360   class EMRSETMAPMODE : public METARECORD, ::EMRSETMAPMODE {
02361   public:
02365     EMRSETMAPMODE ( DWORD mode )
02366     {
02367       emr.iType = EMR_SETMAPMODE;
02368       emr.nSize = sizeof( ::EMRSETMAPMODE );
02369       iMode = mode;
02370     }
02375     EMRSETMAPMODE ( DATASTREAM& ds )
02376     {
02377       ds >> emr >> iMode;
02378     }
02382     bool serialize ( DATASTREAM ds )
02383     {
02384       ds << emr << iMode;
02385       return true;
02386     }
02390     int size ( void ) const { return emr.nSize; }
02396     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02397     {
02398       SetMapMode( dc, iMode );
02399     }
02400 #ifdef ENABLE_EDITING
02401 
02404     void edit ( void ) const
02405     {
02406       printf( "*SETMAPMODE*\n" );
02407       printf( "\tiMode\t: " );
02408       switch ( iMode ) {
02409       case MM_TEXT: printf( "MM_TEXT\n" ); break;
02410       case MM_LOMETRIC: printf( "MM_LOMETRIC\n" ); break;
02411       case MM_HIMETRIC: printf( "MM_HIMETRIC\n" ); break;
02412       case MM_LOENGLISH: printf( "MM_LOENGLISH\n" ); break;
02413       case MM_HIENGLISH: printf( "MM_HIENGLISH\n" ); break;
02414       case MM_TWIPS: printf( "MM_TWIPS\n" ); break;
02415       case MM_ISOTROPIC: printf( "MM_ISOTROPIC\n" ); break;
02416       case MM_ANISOTROPIC: printf( "MM_ANISOTROPIC\n" ); break;
02417       default: printf( "unknown(%ld)\n", iMode );
02418       }
02419     }
02420 #endif /* ENABLE_EDITING */
02421   };
02422 
02424 
02427   class EMRSELECTOBJECT : public METARECORD, ::EMRSELECTOBJECT {
02428   public:
02432     EMRSELECTOBJECT ( HGDIOBJ object )
02433     {
02434       emr.iType = EMR_SELECTOBJECT;
02435       emr.nSize = sizeof( ::EMRSELECTOBJECT );
02436       ihObject = object;
02437     }
02442     EMRSELECTOBJECT ( DATASTREAM& ds )
02443     {
02444       ds >> emr >> ihObject;
02445     }
02449     bool serialize ( DATASTREAM ds )
02450     {
02451       ds << emr << ihObject;
02452       return true;
02453     }
02457     int size ( void ) const { return emr.nSize; }
02463     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
02464 #ifdef ENABLE_EDITING
02465 
02468     void edit ( void ) const
02469     {
02470       printf( "*SELECTOBJECT*\n" );
02471       printf( "\tihObject\t: 0x%lx\n", ihObject );
02472     }
02473 #endif /* ENABLE_EDITING */
02474   };
02475 
02477 
02480   class EMRDELETEOBJECT : public METARECORD, ::EMRDELETEOBJECT {
02481   public:
02485     EMRDELETEOBJECT ( HGDIOBJ object )
02486     {
02487       emr.iType = EMR_DELETEOBJECT;
02488       emr.nSize = sizeof( ::EMRDELETEOBJECT );
02489       ihObject = object;
02490     }
02495     EMRDELETEOBJECT ( DATASTREAM& ds )
02496     {
02497       ds >> emr >> ihObject;
02498     }
02502     bool serialize ( DATASTREAM ds )
02503     {
02504       ds << emr << ihObject;
02505       return true;
02506     }
02510     int size ( void ) const { return emr.nSize; }
02516     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
02517 #ifdef ENABLE_EDITING
02518 
02521     void edit ( void ) const
02522     {
02523       printf( "*DELETEOBJECT*\n" );
02524       printf( "\tihObject\t: 0x%lx\n", ihObject );
02525     }
02526 #endif /* ENABLE_EDITING */
02527   };
02528 
02530 
02533   class EMRMOVETOEX : public METARECORD, ::EMRMOVETOEX {
02534   public:
02539     EMRMOVETOEX ( INT x, INT y )
02540     {
02541       emr.iType = EMR_MOVETOEX;
02542       emr.nSize = sizeof( ::EMRMOVETOEX );
02543       ptl.x = x;
02544       ptl.y = y;
02545     }
02550     EMRMOVETOEX ( DATASTREAM& ds )
02551     {
02552       ds >> emr >> ptl;
02553     }
02557     bool serialize ( DATASTREAM ds )
02558     {
02559       ds << emr << ptl;
02560       return true;
02561     }
02565     int size ( void ) const { return emr.nSize; }
02571     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02572     {
02573       MoveToEx( dc,  ptl.x, ptl.y, 0 );
02574     }
02575 #ifdef ENABLE_EDITING
02576 
02579     void edit ( void ) const
02580     {
02581       printf( "*MOVETOEX*\n" );
02582       edit_pointl( "ptl", ptl );
02583     }
02584 #endif /* ENABLE_EDITING */
02585   };
02586 
02588 
02591   class EMRLINETO : public METARECORD, ::EMRLINETO {
02592   public:
02597     EMRLINETO ( INT x, INT y )
02598     {
02599       emr.iType = EMR_LINETO;
02600       emr.nSize = sizeof( ::EMRLINETO );
02601       ptl.x = x;
02602       ptl.y = y;
02603     }
02608     EMRLINETO ( DATASTREAM& ds )
02609     {
02610       ds >> emr >> ptl;
02611     }
02615     bool serialize ( DATASTREAM ds )
02616     {
02617       ds << emr << ptl;
02618       return true;
02619     }
02623     int size ( void ) const { return emr.nSize; }
02629     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02630     {
02631       LineTo( dc,  ptl.x, ptl.y );
02632     }
02633 #ifdef ENABLE_EDITING
02634 
02637     void edit ( void ) const
02638     {
02639       printf( "*LINETO*\n" );
02640       edit_pointl( "ptl", ptl );
02641     }
02642 #endif /* ENABLE_EDITING */
02643   };
02644 
02646 
02649   class EMRARC : public METARECORD, ::EMRARC {
02650   public:
02662     EMRARC ( INT left, INT top, INT right, INT bottom, INT xstart,
02663              INT ystart, INT xend, INT yend )
02664     {
02665       emr.iType = EMR_ARC;
02666       emr.nSize = sizeof( ::EMRARC );
02667       rclBox.left = left;
02668       rclBox.right = right;
02669       rclBox.bottom = bottom;
02670       rclBox.top = top;
02671       ptlStart.x = xstart;
02672       ptlStart.y = ystart;
02673       ptlEnd.x = xend;
02674       ptlEnd.y = yend;
02675     }
02680     EMRARC ( DATASTREAM& ds )
02681     {
02682       ds >> emr >> rclBox >> ptlStart >> ptlEnd;
02683     }
02687     bool serialize ( DATASTREAM ds )
02688     {
02689       ds << emr << rclBox << ptlStart << ptlEnd;
02690       return true;
02691     }
02695     int size ( void ) const { return emr.nSize; }
02701     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02702     {
02703       Arc( dc, rclBox.left, rclBox.top, rclBox.right, rclBox.bottom,
02704            ptlStart.x, ptlStart.y, ptlEnd.x, ptlEnd.y );
02705     }
02706 #ifdef ENABLE_EDITING
02707 
02710     void edit ( void ) const
02711     {
02712       printf( "*ARC*\n" );
02713       edit_rectl( "rclBox\t", rclBox );
02714       edit_pointl( "ptlStart", ptlStart );
02715       edit_pointl( "ptlEnd\t", ptlEnd );
02716     }
02717 #endif /* ENABLE_EDITING */
02718   };
02719 
02721 
02724   class EMRARCTO : public METARECORD, ::EMRARCTO {
02725   public:
02737     EMRARCTO ( INT left, INT top, INT right, INT bottom, INT xstart,
02738              INT ystart, INT xend, INT yend )
02739     {
02740       emr.iType = EMR_ARCTO;
02741       emr.nSize = sizeof( ::EMRARCTO );
02742       rclBox.left = left;
02743       rclBox.right = right;
02744       rclBox.bottom = bottom;
02745       rclBox.top = top;
02746       ptlStart.x = xstart;
02747       ptlStart.y = ystart;
02748       ptlEnd.x = xend;
02749       ptlEnd.y = yend;
02750     }
02755     EMRARCTO ( DATASTREAM& ds )
02756     {
02757       ds >> emr >> rclBox >> ptlStart >> ptlEnd;
02758     }
02762     bool serialize ( DATASTREAM ds )
02763     {
02764       ds << emr << rclBox << ptlStart << ptlEnd;
02765       return true;
02766     }
02770     int size ( void ) const { return emr.nSize; }
02776     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02777     {
02778       ArcTo( dc, rclBox.left, rclBox.top, rclBox.right, rclBox.bottom,
02779              ptlStart.x, ptlStart.y, ptlEnd.x, ptlEnd.y );
02780     }
02781 #ifdef ENABLE_EDITING
02782 
02785     void edit ( void ) const
02786     {
02787       printf( "*ARCTO*\n" );
02788       edit_rectl( "rclBox\t", rclBox );
02789       edit_pointl( "ptlStart", ptlStart );
02790       edit_pointl( "ptlEnd\t", ptlEnd );
02791     }
02792 #endif /* ENABLE_EDITING */
02793   };
02794 
02796 
02799   class EMRRECTANGLE : public METARECORD, ::EMRRECTANGLE {
02800   public:
02807     EMRRECTANGLE ( INT left, INT top, INT right, INT bottom )
02808     {
02809       emr.iType = EMR_RECTANGLE;
02810       emr.nSize = sizeof( ::EMRRECTANGLE );
02811       rclBox.left = left;
02812       rclBox.right = right;
02813       rclBox.bottom = bottom;
02814       rclBox.top = top;
02815     }
02820     EMRRECTANGLE ( DATASTREAM& ds )
02821     {
02822       ds >> emr >> rclBox;
02823     }
02827     bool serialize ( DATASTREAM ds )
02828     {
02829       ds << emr << rclBox;
02830       return true;
02831     }
02835     int size ( void ) const { return emr.nSize; }
02841     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02842     {
02843       Rectangle( dc, rclBox.left, rclBox.top, rclBox.right, rclBox.bottom );
02844     }
02845 #ifdef ENABLE_EDITING
02846 
02849     void edit ( void ) const
02850     {
02851       printf( "*RECTANGLE*\n" );
02852       edit_rectl( "rclBox", rclBox );
02853     }
02854 #endif /* ENABLE_EDITING */
02855   };
02856 
02858 
02861   class EMRELLIPSE : public METARECORD, ::EMRELLIPSE {
02862   public:
02870     EMRELLIPSE ( INT left, INT top, INT right, INT bottom )
02871     {
02872       emr.iType = EMR_ELLIPSE;
02873       emr.nSize = sizeof( ::EMRELLIPSE );
02874       rclBox.left = left;
02875       rclBox.right = right;
02876       rclBox.bottom = bottom;
02877       rclBox.top = top;
02878     }
02883     EMRELLIPSE ( DATASTREAM& ds )
02884     {
02885       ds >> emr >> rclBox;
02886     }
02890     bool serialize ( DATASTREAM ds )
02891     {
02892       ds << emr << rclBox;
02893       return true;
02894     }
02898     int size ( void ) const { return emr.nSize; }
02904     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02905     {
02906       Ellipse( dc, rclBox.left, rclBox.top, rclBox.right, rclBox.bottom );
02907     }
02908 #ifdef ENABLE_EDITING
02909 
02912     void edit ( void ) const
02913     {
02914       printf( "*ELLIPSE*\n" );
02915       edit_rectl( "rclBox", rclBox );
02916     }
02917 #endif /* ENABLE_EDITING */
02918   };
02919 
02921 
02924   class EMRPOLYLINE : public METARECORD, ::EMRPOLYLINE {
02925     POINTL* lpoints;
02926   public:
02932     EMRPOLYLINE ( const RECTL* bounds, const POINT* points, INT n )
02933     {
02934       cptl = n;
02935       aptl[0].x = 0;            // Really unused
02936       aptl[0].y = 0;
02937 
02938       emr.iType = EMR_POLYLINE;
02939       // The (cptl - 1) below is to account for aptl, which isn't written out
02940       emr.nSize = sizeof( ::EMRPOLYLINE ) + sizeof( POINTL ) * ( cptl - 1);
02941 
02942       lpoints = new POINTL[cptl];
02943 
02944       for (int i=0; i<n; i++) {
02945         lpoints[i].x = points[i].x;
02946         lpoints[i].y = points[i].y;
02947       }
02948 
02949       rclBounds = *bounds;
02950     }
02954     ~EMRPOLYLINE ( )
02955     {
02956       if ( lpoints ) delete[] lpoints;
02957     }
02962     EMRPOLYLINE ( DATASTREAM& ds )
02963     {
02964       ds >> emr >> rclBounds >> cptl;
02965 
02966       lpoints = new POINTL[cptl];
02967 
02968       POINTLARRAY points( lpoints, cptl );
02969 
02970       ds >> points;
02971     }
02975     bool serialize ( DATASTREAM ds )
02976     {
02977       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
02978       return true;
02979     }
02983     int size ( void ) const { return emr.nSize; }
02989     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02990     {
02991       // According to the wine windef.h header, POINT and POINTL are equivalent
02992       Polyline( dc, (POINT*)lpoints, cptl );
02993     }
02994 #ifdef ENABLE_EDITING
02995 
02998     void edit ( void ) const
02999     {
03000       printf( "*POLYLINE*\n" );
03001       edit_rectl( "rclBounds", rclBounds );
03002 #if 0
03003       printf( "\tcptl              : %ld\n", cptl );
03004       printf( "\taptl->\n" );
03005       for ( unsigned int i = 0; i < cptl; i++ )
03006         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
03007 #else
03008       edit_pointlarray( "\t", cptl, lpoints );
03009 #endif
03010     }
03011 #endif /* ENABLE_EDITING */
03012   };
03013 
03015 
03018   class EMRPOLYLINE16 : public METARECORD, ::EMRPOLYLINE16 {
03019     POINT16* lpoints;
03020   public:
03026     EMRPOLYLINE16 ( const RECTL* bounds, const POINT16* points, INT n )
03027     {
03028       cpts = n;
03029       apts[0].x = 0;            // Really unused
03030       apts[0].y = 0;
03031 
03032       emr.iType = EMR_POLYLINE16;
03033       // The (cptl - 1) below is to account for aptl, which isn't written out
03034       emr.nSize = sizeof( ::EMRPOLYLINE16 ) + sizeof( POINT16 ) * ( cpts - 1);
03035 
03036       lpoints = new POINT16[cpts];
03037 
03038       for (int i=0; i<n; i++) {
03039         lpoints[i].x = points[i].x;
03040         lpoints[i].y = points[i].y;
03041       }
03042 
03043       rclBounds = *bounds;
03044     }
03051     EMRPOLYLINE16 ( const RECTL* bounds, const POINT* points, INT n )
03052     {
03053       cpts = n;
03054       apts[0].x = 0;            // Really unused
03055       apts[0].y = 0;
03056 
03057       emr.iType = EMR_POLYLINE16;
03058       // The (cptl - 1) below is to account for aptl, which isn't written out
03059       emr.nSize = sizeof( ::EMRPOLYLINE16 ) + sizeof( POINT16 ) * ( cpts - 1);
03060 
03061       lpoints = new POINT16[cpts];
03062 
03063       for (int i=0; i<n; i++) {
03064         lpoints[i].x = points[i].x;
03065         lpoints[i].y = points[i].y;
03066       }
03067 
03068       rclBounds = *bounds;
03069     }
03073     ~EMRPOLYLINE16 ( )
03074     {
03075       if ( lpoints ) delete[] lpoints;
03076     }
03081     EMRPOLYLINE16 ( DATASTREAM& ds )
03082     {
03083       ds >> emr >> rclBounds >> cpts;
03084 
03085       lpoints = new POINT16[cpts];
03086 
03087       POINT16ARRAY points( lpoints, cpts );
03088 
03089       ds >> points;
03090     }
03094     bool serialize ( DATASTREAM ds )
03095     {
03096       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
03097       return true;
03098     }
03102     int size ( void ) const { return emr.nSize; }
03108     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03109     {
03110       // According to the wine windef.h header, POINT and POINTL are equivalent
03111       Polyline16( dc, lpoints, cpts );
03112     }
03113 #ifdef ENABLE_EDITING
03114 
03117     void edit ( void ) const
03118     {
03119       printf( "*POLYLINE16*\n" );
03120       edit_rectl( "rclBounds", rclBounds );
03121       edit_point16array( "\t", cpts, lpoints );
03122     }
03123 #endif /* ENABLE_EDITING */
03124   };
03125 
03127 
03130   class EMRPOLYGON : public METARECORD, ::EMRPOLYGON {
03131     POINTL* lpoints;
03132   public:
03138     EMRPOLYGON ( const RECTL* bounds, const POINT* points, INT n )
03139     {
03140       cptl = n;
03141       aptl[0].x = 0;            // Really unused
03142       aptl[0].y = 0;
03143 
03144       emr.iType = EMR_POLYGON;
03145       // The (cptl-1) below is to account for aptl, which isn't written out
03146       emr.nSize = sizeof( ::EMRPOLYGON ) + sizeof( POINTL ) * (cptl-1);
03147 
03148       lpoints = new POINTL[cptl];
03149 
03150       for (int i=0; i<n; i++) {
03151         lpoints[i].x = points[i].x;
03152         lpoints[i].y = points[i].y;
03153       }
03154 
03155       rclBounds = *bounds;
03156     }
03161     EMRPOLYGON ( DATASTREAM& ds )
03162     {
03163       ds >> emr >> rclBounds >> cptl;
03164 
03165       lpoints = new POINTL[cptl];
03166 
03167       POINTLARRAY points( lpoints, cptl );
03168 
03169       ds >> points;
03170     }
03174     ~EMRPOLYGON ( )
03175     {
03176       if ( lpoints ) delete[] lpoints;
03177     }
03181     bool serialize ( DATASTREAM ds )
03182     {
03183       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
03184       return true;
03185     }
03189     int size ( void ) const { return emr.nSize; }
03195     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03196     {
03197       // According to the wine windef.h header, POINT and POINTL are equivalent
03198       Polygon( dc, (POINT*)lpoints, cptl );
03199     }
03200 #ifdef ENABLE_EDITING
03201 
03204     void edit ( void ) const
03205     {
03206       printf( "*POLYGON*\n" );
03207       edit_rectl( "rclBounds", rclBounds );
03208 #if 0
03209       printf( "\tcptl              : %ld\n", cptl );
03210       printf( "\taptl->\n" );
03211       for ( unsigned int i = 0; i < cptl; i++ )
03212         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
03213 #else
03214       edit_pointlarray( "\t", cptl, lpoints );
03215 #endif
03216     }
03217 #endif /* ENABLE_EDITING */
03218   };
03219 
03221 
03224   class EMRPOLYGON16 : public METARECORD, ::EMRPOLYGON16 {
03225     POINT16* lpoints;
03226   public:
03232     EMRPOLYGON16 ( const RECTL* bounds, const POINT* points, INT16 n )
03233     {
03234       cpts = n;
03235       apts[0].x = 0;            // Really unused
03236       apts[0].y = 0;
03237 
03238       emr.iType = EMR_POLYGON16;
03239       // The (cptl-1) below is to account for aptl, which isn't written out
03240       emr.nSize = sizeof( ::EMRPOLYGON16 ) + sizeof( POINT16 ) * (cpts-1);
03241 
03242       lpoints = new POINT16[cpts];
03243 
03244       for (int i=0; i<n; i++) {
03245         lpoints[i].x = points[i].x;
03246         lpoints[i].y = points[i].y;
03247       }
03248 
03249       rclBounds = *bounds;
03250     }
03257     EMRPOLYGON16 ( const RECTL* bounds, const POINT16* points, INT16 n )
03258     {
03259       cpts = n;
03260       apts[0].x = 0;            // Really unused
03261       apts[0].y = 0;
03262 
03263       emr.iType = EMR_POLYGON16;
03264       // The (cptl-1) below is to account for aptl, which isn't written out
03265       emr.nSize = sizeof( ::EMRPOLYGON16 ) + sizeof( POINT16 ) * (cpts-1);
03266 
03267       lpoints = new POINT16[cpts];
03268 
03269       for (int i=0; i<n; i++) {
03270         lpoints[i].x = points[i].x;
03271         lpoints[i].y = points[i].y;
03272       }
03273 
03274       rclBounds = *bounds;
03275     }
03280     EMRPOLYGON16 ( DATASTREAM& ds )
03281     {
03282       ds >> emr >> rclBounds >> cpts;
03283 
03284       lpoints = new POINT16[cpts];
03285 
03286       POINT16ARRAY points( lpoints, cpts );
03287 
03288       ds >> points;
03289     }
03293     ~EMRPOLYGON16 ( )
03294     {
03295       if ( lpoints ) delete[] lpoints;
03296     }
03300     bool serialize ( DATASTREAM ds )
03301     {
03302       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
03303       return true;
03304     }
03308     int size ( void ) const { return emr.nSize; }
03314     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03315     {
03316       // According to the wine windef.h header, POINT and POINTL are equivalent
03317       Polygon16( dc, lpoints, cpts );
03318     }
03319 #ifdef ENABLE_EDITING
03320 
03323     void edit ( void ) const
03324     {
03325       printf( "*POLYGON16*\n" );
03326       edit_rectl( "rclBounds", rclBounds );
03327       edit_point16array( "\t", cpts, lpoints );
03328     }
03329 #endif /* ENABLE_EDITING */
03330   };
03331 
03333 
03336   class EMRPOLYPOLYGON : public METARECORD, ::EMRPOLYPOLYGON {
03337     DWORD* lcounts;
03338     POINTL* lpoints;
03339   public:
03346     EMRPOLYPOLYGON ( const RECTL* bounds, const POINT* points, const INT* counts,
03347                      UINT polygons )
03348     {
03349       nPolys = polygons;
03350       // Count the number of points in points
03351       int n = 0;
03352       for ( unsigned int i = 0; i < nPolys; i++ )
03353         n += counts[i];
03354 
03355       cptl = n;
03356       aPolyCounts[0] = 0;       // Really unused
03357       aptl[0].x = 0;
03358       aptl[0].y = 0;
03359 
03360       emr.iType = EMR_POLYPOLYGON;
03361       // The (#-1)'s below are to account for aPolyCounts[0] and aptl[0], which
03362       // aren't directly written out
03363       emr.nSize = sizeof( ::EMRPOLYPOLYGON ) + sizeof( POINTL ) * (cptl-1)
03364         + sizeof( DWORD ) * (nPolys-1);
03365 
03366       lcounts = new DWORD[nPolys];
03367 
03368       for ( unsigned int i = 0; i < nPolys; i++ )
03369         lcounts[i] = counts[i];
03370 
03371       lpoints = new POINTL[cptl];
03372 
03373       for (int i=0; i<n; i++) {
03374         lpoints[i].x = points[i].x;
03375         lpoints[i].y = points[i].y;
03376       }
03377 
03378       rclBounds = *bounds;
03379     }
03383     ~EMRPOLYPOLYGON ( )
03384     {
03385       if ( lcounts ) delete[] lcounts;
03386       if ( lpoints ) delete[] lpoints;
03387     }
03392     EMRPOLYPOLYGON ( DATASTREAM& ds )
03393     {
03394       ds >> emr >> rclBounds >> nPolys >> cptl;
03395 
03396       lcounts = new DWORD[nPolys];
03397 
03398       DWORDARRAY counts( lcounts, nPolys );
03399 
03400       ds >> counts;
03401 
03402       lpoints = new POINTL[cptl];
03403 
03404       POINTLARRAY points( lpoints, cptl );
03405 
03406       ds >> points;
03407     }
03411     bool serialize ( DATASTREAM ds )
03412     {
03413       ds << emr << rclBounds << nPolys << cptl << DWORDARRAY( lcounts, nPolys )
03414          << POINTLARRAY( lpoints, cptl );
03415       return true;
03416     }
03420     int size ( void ) const { return emr.nSize; }
03426     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03427     {
03428       // According to the wine windef.h header, POINT and POINTL are equivalent
03429       // (but DWORD and INT are not)
03430       INT* counts = new INT[nPolys];
03431       for ( unsigned int i = 0; i < nPolys; i++ )
03432         counts[i] = lcounts[i];
03433 
03434       PolyPolygon( dc, (POINT*)lpoints, counts, nPolys );
03435 
03436       delete[] counts;
03437     }
03438 #ifdef ENABLE_EDITING
03439 
03442     void edit ( void ) const
03443     {
03444       printf( "*POLYPOLYGON*\n" );
03445       edit_rectl( "rclBounds", rclBounds );
03446       printf( "\tnPolys\t\t: %ld\n", nPolys );
03447       printf( "\tcptl\t\t: %ld\n", cptl );
03448       printf( "\taPolyCounts\t: " );
03449       if ( nPolys > 0 )
03450         printf( "%ld\n", lcounts[0] );
03451       else
03452         puts( "" );
03453       for ( unsigned int i = 1; i < nPolys; i++ )
03454         printf( "\t\t\t  %ld\n", lcounts[i] );
03455       printf( "\tapts\t\t: " );
03456       if ( cptl > 0 )
03457         printf( "%ld, %ld\n", lpoints[0].x, lpoints[0].y );
03458       else
03459         puts( "" );
03460       for ( unsigned int i = 1; i < cptl; i++ )
03461         printf( "\t\t\t  %ld, %ld\n", lpoints[i].x, lpoints[i].y );
03462     }
03463 #endif /* ENABLE_EDITING */
03464   };
03465 
03467 
03470   class EMRPOLYPOLYGON16 : public METARECORD, ::EMRPOLYPOLYGON16 {
03471     DWORD* lcounts;
03472     POINT16* lpoints;
03473   public:
03480     EMRPOLYPOLYGON16 ( const RECTL* bounds, const POINT* points,
03481                        const INT* counts, UINT polygons )
03482     {
03483       nPolys = polygons;
03484       // Count the number of points in points
03485       int n = 0;
03486       for ( unsigned int i = 0; i < nPolys; i++ )
03487         n += counts[i];
03488 
03489       cpts = n;
03490       aPolyCounts[0] = 0;       // Really unused
03491       apts[0].x = 0;
03492       apts[0].y = 0;
03493 
03494       emr.iType = EMR_POLYPOLYGON16;
03495       // The (#-1)'s below are to account for aPolyCounts[0] and aptl[0], which
03496       // aren't directly written out
03497       emr.nSize = sizeof( ::EMRPOLYPOLYGON16 ) + sizeof( POINT16 ) * (cpts-1)
03498         + sizeof( DWORD ) * (nPolys-1);
03499 
03500       lcounts = new DWORD[nPolys];
03501 
03502       for ( unsigned int i = 0; i < nPolys; i++ )
03503         lcounts[i] = counts[i];
03504 
03505       lpoints = new POINT16[cpts];
03506 
03507       for (int i=0; i<n; i++) {
03508         lpoints[i].x = points[i].x;
03509         lpoints[i].y = points[i].y;
03510       }
03511 
03512       rclBounds = *bounds;
03513     }
03521     EMRPOLYPOLYGON16 ( const RECTL* bounds, const POINT16* points,
03522                        const INT* counts, UINT16 polygons )
03523     {
03524       nPolys = polygons;
03525       // Count the number of points in points
03526       int n = 0;
03527       for ( unsigned int i = 0; i < nPolys; i++ )
03528         n += counts[i];
03529 
03530       cpts = n;
03531       aPolyCounts[0] = 0;       // Really unused
03532       apts[0].x = 0;
03533       apts[0].y = 0;
03534 
03535       emr.iType = EMR_POLYPOLYGON16;
03536       // The (#-1)'s below are to account for aPolyCounts[0] and aptl[0], which
03537       // aren't directly written out
03538       emr.nSize = sizeof( ::EMRPOLYPOLYGON16 ) + sizeof( POINT16 ) * (cpts-1)
03539         + sizeof( DWORD ) * (nPolys-1);
03540 
03541       lcounts = new DWORD[nPolys];
03542 
03543       for ( unsigned int i = 0; i < nPolys; i++ )
03544         lcounts[i] = counts[i];
03545 
03546       lpoints = new POINT16[cpts];
03547 
03548       for (int i=0; i<n; i++) {
03549         lpoints[i].x = points[i].x;
03550         lpoints[i].y = points[i].y;
03551       }
03552 
03553       rclBounds = *bounds;
03554     }
03558     ~EMRPOLYPOLYGON16 ( )
03559     {
03560       if ( lcounts ) delete[] lcounts;
03561       if ( lpoints ) delete[] lpoints;
03562     }
03567     EMRPOLYPOLYGON16 ( DATASTREAM& ds )
03568     {
03569       ds >> emr >> rclBounds >> nPolys >> cpts;
03570 
03571       lcounts = new DWORD[nPolys];
03572 
03573       DWORDARRAY counts( lcounts, nPolys );
03574 
03575       ds >> counts;
03576 
03577       lpoints = new POINT16[cpts];
03578 
03579       POINT16ARRAY points( lpoints, cpts );
03580 
03581       ds >> points;
03582     }
03586     bool serialize ( DATASTREAM ds )
03587     {
03588       ds << emr << rclBounds << nPolys << cpts << DWORDARRAY( lcounts, nPolys )
03589          << POINT16ARRAY( lpoints, cpts );
03590       return true;
03591     }
03595     int size ( void ) const { return emr.nSize; }
03601     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03602     {
03603       // According to the wine windef.h header, POINT and POINTL are equivalent
03604       // (but DWORD and INT are not)
03605       INT* counts = new INT[nPolys];
03606       for ( unsigned int i = 0; i < nPolys; i++ )
03607         counts[i] = lcounts[i];
03608 
03609       PolyPolygon16( dc, lpoints, counts, nPolys );
03610 
03611       delete[] counts;
03612     }
03613 #ifdef ENABLE_EDITING
03614 
03617     void edit ( void ) const
03618     {
03619       printf( "*POLYPOLYGON16*\n" );
03620       edit_rectl( "rclBounds", rclBounds );
03621       printf( "\tnPolys\t\t: %ld\n", nPolys );
03622       printf( "\tcpts\t\t: %ld\n", cpts );
03623       printf( "\taPolyCounts\t: " );
03624       if ( nPolys > 0 )
03625         printf( "%ld\n", lcounts[0] );
03626       else
03627         puts( "" );
03628       for ( unsigned int i = 1; i < nPolys; i++ )
03629         printf( "\t\t\t  %ld\n", lcounts[i] );
03630       printf( "\tapts\t\t: " );
03631       if ( cpts > 0 )
03632         printf( "%d, %d\n", lpoints[0].x, lpoints[0].y );
03633       else
03634         puts( "" );
03635       for ( unsigned int i = 1; i < cpts; i++ )
03636         printf( "\t\t\t  %d, %d\n", lpoints[i].x, lpoints[i].y );
03637     }
03638 #endif /* ENABLE_EDITING */
03639   };
03640 
03642 
03645   class EMRPOLYBEZIER : public METARECORD, ::EMRPOLYBEZIER {
03646     POINTL* lpoints;
03647   public:
03653     EMRPOLYBEZIER ( const RECTL* bounds, const POINT* points, INT n )
03654     {
03655       cptl = n;
03656       aptl[0].x = 0;            // Really unused
03657       aptl[0].y = 0;
03658 
03659       emr.iType = EMR_POLYBEZIER;
03660       // The (cptl-1) below is to account for aptl, which isn't written out
03661       emr.nSize = sizeof( ::EMRPOLYBEZIER ) + sizeof( POINTL ) * (cptl-1);
03662 
03663       lpoints = new POINTL[cptl];
03664 
03665       for (int i=0; i<n; i++) {
03666         lpoints[i].x = points[i].x;
03667         lpoints[i].y = points[i].y;
03668       }
03669 
03670       rclBounds = *bounds;
03671     }
03676     EMRPOLYBEZIER ( DATASTREAM& ds )
03677     {
03678       ds >> emr >> rclBounds >> cptl;
03679 
03680       lpoints = new POINTL[cptl];
03681 
03682       POINTLARRAY points( lpoints, cptl );
03683 
03684       ds >> points;
03685     }
03689     ~EMRPOLYBEZIER ( )
03690     {
03691       if ( lpoints ) delete[] lpoints;
03692     }
03696     bool serialize ( DATASTREAM ds )
03697     {
03698       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
03699       return true;
03700     }
03704     int size ( void ) const { return emr.nSize; }
03710     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03711     {
03712       // According to the wine windef.h header, POINT and POINTL are equivalent
03713       PolyBezier( dc, (POINT*)lpoints, cptl );
03714     }
03715 #ifdef ENABLE_EDITING
03716 
03719     void edit ( void ) const
03720     {
03721       printf( "*POLYBEZIER*\n" );
03722       edit_rectl( "rclBounds", rclBounds );
03723 #if 0
03724       printf( "\tcptl              : %ld\n", cptl );
03725       printf( "\taptl->\n" );
03726       for ( unsigned int i = 0; i < cptl; i++ )
03727         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
03728 #else
03729       edit_pointlarray( "\t", cptl, lpoints );
03730 #endif
03731     }
03732 #endif /* ENABLE_EDITING */
03733   };
03734 
03736 
03739   class EMRPOLYBEZIER16 : public METARECORD, ::EMRPOLYBEZIER16 {
03740     POINT16* lpoints;
03741   public:
03747     EMRPOLYBEZIER16 ( const RECTL* bounds, const POINT16* points, INT n )
03748     {
03749       cpts = n;
03750       apts[0].x = 0;            // Really unused
03751       apts[0].y = 0;
03752 
03753       emr.iType = EMR_POLYBEZIER16;
03754       // The (cptl-1) below is to account for aptl, which isn't written out
03755       emr.nSize = sizeof( ::EMRPOLYBEZIER16 ) + sizeof( POINT16 ) * (cpts-1);
03756 
03757       lpoints = new POINT16[cpts];
03758 
03759       for (int i=0; i<n; i++) {
03760         lpoints[i].x = points[i].x;
03761         lpoints[i].y = points[i].y;
03762       }
03763 
03764       rclBounds = *bounds;
03765     }
03772     EMRPOLYBEZIER16 ( const RECTL* bounds, const POINT* points, INT n )
03773     {
03774       cpts = n;
03775       apts[0].x = 0;            // Really unused
03776       apts[0].y = 0;
03777 
03778       emr.iType = EMR_POLYBEZIER16;
03779       // The (cptl-1) below is to account for aptl, which isn't written out
03780       emr.nSize = sizeof( ::EMRPOLYBEZIER16 ) + sizeof( POINT16 ) * (cpts-1);
03781 
03782       lpoints = new POINT16[cpts];
03783 
03784       for (int i=0; i<n; i++) {
03785         lpoints[i].x = points[i].x;
03786         lpoints[i].y = points[i].y;
03787       }
03788 
03789       rclBounds = *bounds;
03790     }
03795     EMRPOLYBEZIER16 ( DATASTREAM& ds )
03796     {
03797       ds >> emr >> rclBounds >> cpts;
03798 
03799       lpoints = new POINT16[cpts];
03800 
03801       POINT16ARRAY points( lpoints, cpts );
03802 
03803       ds >> points;
03804     }
03808     ~EMRPOLYBEZIER16 ( )
03809     {
03810       if ( lpoints ) delete[] lpoints;
03811     }
03815     bool serialize ( DATASTREAM ds )
03816     {
03817       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
03818       return true;
03819     }
03823     int size ( void ) const { return emr.nSize; }
03829     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03830     {
03831       // According to the wine windef.h header, POINT and POINTL are equivalent
03832       PolyBezier16( dc, lpoints, cpts );
03833     }
03834 #ifdef ENABLE_EDITING
03835 
03838     void edit ( void ) const
03839     {
03840       printf( "*POLYBEZIER16*\n" );
03841       edit_rectl( "rclBounds", rclBounds );
03842       edit_point16array( "\t", cpts, lpoints );
03843     }
03844 #endif /* ENABLE_EDITING */
03845   };
03846 
03848 
03851   class EMRPOLYBEZIERTO : public METARECORD, ::EMRPOLYBEZIER {
03852     POINTL* lpoints;
03853   public:
03859     EMRPOLYBEZIERTO ( const RECTL* bounds, const POINT* points, INT n )
03860     {
03861       cptl = n;
03862       aptl[0].x = 0;            // Really unused
03863       aptl[0].y = 0;
03864 
03865       emr.iType = EMR_POLYBEZIERTO;
03866       // The (cptl-1) below is to account for aptl, which isn't written out
03867       emr.nSize = sizeof( ::EMRPOLYBEZIERTO ) + sizeof( POINTL ) * (cptl-1);
03868 
03869       lpoints = new POINTL[cptl];
03870 
03871       for (int i=0; i<n; i++) {
03872         lpoints[i].x = points[i].x;
03873         lpoints[i].y = points[i].y;
03874       }
03875 
03876       rclBounds = *bounds;
03877     }
03882     EMRPOLYBEZIERTO ( DATASTREAM& ds )
03883     {
03884       ds >> emr >> rclBounds >> cptl;
03885 
03886       lpoints = new POINTL[cptl];
03887 
03888       POINTLARRAY points( lpoints, cptl );
03889 
03890       ds >> points;
03891     }
03895     ~EMRPOLYBEZIERTO ( )
03896     {
03897       if ( lpoints ) delete[] lpoints;
03898     }
03902     bool serialize ( DATASTREAM ds )
03903     {
03904       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
03905       return true;
03906     }
03910     int size ( void ) const { return emr.nSize; }
03916     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03917     {
03918       // According to the wine windef.h header, POINT and POINTL are equivalent
03919       PolyBezierTo( dc, (POINT*)lpoints, cptl );
03920     }
03921 #ifdef ENABLE_EDITING
03922 
03925     void edit ( void ) const
03926     {
03927       printf( "*POLYBEZIERTO*\n" );
03928       edit_rectl( "rclBounds", rclBounds );
03929 #if 0
03930       printf( "\tcptl              : %ld\n", cptl );
03931       printf( "\taptl->\n" );
03932       for ( unsigned int i = 0; i < cptl; i++ )
03933         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
03934 #else
03935       edit_pointlarray( "\t", cptl, lpoints );
03936 #endif
03937     }
03938 #endif /* ENABLE_EDITING */
03939   };
03940 
03942 
03945   class EMRPOLYBEZIERTO16 : public METARECORD, ::EMRPOLYBEZIER16 {
03946     POINT16* lpoints;
03947   public:
03953     EMRPOLYBEZIERTO16 ( const RECTL* bounds, const POINT16* points, INT n )
03954     {
03955       cpts = n;
03956       apts[0].x = 0;            // Really unused
03957       apts[0].y = 0;
03958 
03959       emr.iType = EMR_POLYBEZIERTO16;
03960       // The (cptl-1) below is to account for aptl, which isn't written out
03961       emr.nSize = sizeof( ::EMRPOLYBEZIERTO16 ) + sizeof( POINT16 ) * (cpts-1);
03962 
03963       lpoints = new POINT16[cpts];
03964 
03965       for (int i=0; i<n; i++) {
03966         lpoints[i].x = points[i].x;
03967         lpoints[i].y = points[i].y;
03968       }
03969 
03970       rclBounds = *bounds;
03971     }
03978     EMRPOLYBEZIERTO16 ( const RECTL* bounds, const POINT* points, INT n )
03979     {
03980       cpts = n;
03981       apts[0].x = 0;            // Really unused
03982       apts[0].y = 0;
03983 
03984       emr.iType = EMR_POLYBEZIERTO16;
03985       // The (cptl-1) below is to account for aptl, which isn't written out
03986       emr.nSize = sizeof( ::EMRPOLYBEZIERTO16 ) + sizeof( POINT16 ) * (cpts-1);
03987 
03988       lpoints = new POINT16[cpts];
03989 
03990       for (int i=0; i<n; i++) {
03991         lpoints[i].x = points[i].x;
03992         lpoints[i].y = points[i].y;
03993       }
03994 
03995       rclBounds = *bounds;
03996     }
04001     EMRPOLYBEZIERTO16 ( DATASTREAM& ds )
04002     {
04003       ds >> emr >> rclBounds >> cpts;
04004 
04005       lpoints = new POINT16[cpts];
04006 
04007       POINT16ARRAY points( lpoints, cpts );
04008 
04009       ds >> points;
04010     }
04014     ~EMRPOLYBEZIERTO16 ( )
04015     {
04016       if ( lpoints ) delete[] lpoints;
04017     }
04021     bool serialize ( DATASTREAM ds )
04022     {
04023       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
04024       return true;
04025     }
04029     int size ( void ) const { return emr.nSize; }
04035     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04036     {
04037       // According to the wine windef.h header, POINT and POINTL are equivalent
04038       PolyBezierTo16( dc, lpoints, cpts );
04039     }
04040 #ifdef ENABLE_EDITING
04041 
04044     void edit ( void ) const
04045     {
04046       printf( "*POLYBEZIERTO16*\n" );
04047       edit_rectl( "rclBounds", rclBounds );
04048       edit_point16array( "\t", cpts, lpoints );
04049     }
04050 #endif /* ENABLE_EDITING */
04051   };
04052 
04054 
04057   class EMRPOLYLINETO : public METARECORD, ::EMRPOLYLINETO {
04058     POINTL* lpoints;
04059   public:
04065     EMRPOLYLINETO ( const RECTL* bounds, const POINT* points, INT n )
04066     {
04067       cptl = n;
04068       aptl[0].x = 0;
04069       aptl[0].y = 0;
04070 
04071       emr.iType = EMR_POLYLINETO;
04072       // The (cptl-1) below is to account for aptl, which isn't written out
04073       emr.nSize = sizeof( ::EMRPOLYLINETO ) + sizeof( POINTL ) * (cptl-1);
04074 
04075       lpoints = new POINTL[cptl];
04076 
04077       for (int i=0; i<n; i++) {
04078         lpoints[i].x = points[i].x;
04079         lpoints[i].y = points[i].y;
04080       }
04081 
04082       rclBounds = *bounds;
04083     }
04088     EMRPOLYLINETO ( DATASTREAM& ds )
04089     {
04090       ds >> emr >> rclBounds >> cptl;
04091 
04092       lpoints = new POINTL[cptl];
04093 
04094       POINTLARRAY points( lpoints, cptl );
04095 
04096       ds >> points;
04097     }
04101     ~EMRPOLYLINETO ( )
04102     {
04103       if ( lpoints ) delete[] lpoints;
04104     }
04108     bool serialize ( DATASTREAM ds )
04109     {
04110       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
04111       return true;
04112     }
04116     int size ( void ) const { return emr.nSize; }
04122     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04123     {
04124       // According to the wine windef.h header, POINT and POINTL are equivalent
04125       PolylineTo( dc, (POINT*)lpoints, cptl );
04126     }
04127 #ifdef ENABLE_EDITING
04128 
04131     void edit ( void ) const
04132     {
04133       printf( "*POLYLINETO*\n" );
04134       edit_rectl( "rclBounds", rclBounds );
04135 #if 0
04136       printf( "\tcptl              : %ld\n", cptl );
04137       printf( "\taptl->\n" );
04138       for ( unsigned int i = 0; i < cptl; i++ )
04139         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
04140 #else
04141       edit_pointlarray( "\t", cptl, lpoints );
04142 #endif
04143     }
04144 #endif /* ENABLE_EDITING */
04145   };
04146 
04148 
04151   class EMRPOLYLINETO16 : public METARECORD, ::EMRPOLYLINETO16 {
04152     POINT16* lpoints;
04153   public:
04159     EMRPOLYLINETO16 ( const RECTL* bounds, const POINT16* points, INT n )
04160     {
04161       cpts = n;
04162       apts[0].x = 0;
04163       apts[0].y = 0;
04164 
04165       emr.iType = EMR_POLYLINETO16;
04166       // The (cptl-1) below is to account for aptl, which isn't written out
04167       emr.nSize = sizeof( ::EMRPOLYLINETO16 ) + sizeof( POINT16 ) * (cpts-1);
04168 
04169       lpoints = new POINT16[cpts];
04170 
04171       for (int i=0; i<n; i++) {
04172         lpoints[i].x = points[i].x;
04173         lpoints[i].y = points[i].y;
04174       }
04175 
04176       rclBounds = *bounds;
04177     }
04184     EMRPOLYLINETO16 ( const RECTL* bounds, const POINT* points, INT n )
04185     {
04186       cpts = n;
04187       apts[0].x = 0;
04188       apts[0].y = 0;
04189 
04190       emr.iType = EMR_POLYLINETO16;
04191       // The (cptl-1) below is to account for aptl, which isn't written out
04192       emr.nSize = sizeof( ::EMRPOLYLINETO16 ) + sizeof( POINT16 ) * (cpts-1);
04193 
04194       lpoints = new POINT16[cpts];
04195 
04196       for (int i=0; i<n; i++) {
04197         lpoints[i].x = points[i].x;
04198         lpoints[i].y = points[i].y;
04199       }
04200 
04201       rclBounds = *bounds;
04202     }
04207     EMRPOLYLINETO16 ( DATASTREAM& ds )
04208     {
04209       ds >> emr >> rclBounds >> cpts;
04210 
04211       lpoints = new POINT16[cpts];
04212 
04213       POINT16ARRAY points( lpoints, cpts );
04214 
04215       ds >> points;
04216     }
04220     ~EMRPOLYLINETO16 ( )
04221     {
04222       if ( lpoints ) delete[] lpoints;
04223     }
04227     bool serialize ( DATASTREAM ds )
04228     {
04229       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
04230       return true;
04231     }
04235     int size ( void ) const { return emr.nSize; }
04241     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04242     {
04243       // According to the wine windef.h header, POINT and POINTL are equivalent
04244       PolylineTo16( dc, lpoints, cpts );
04245     }
04246 #ifdef ENABLE_EDITING
04247 
04250     void edit ( void ) const
04251     {
04252       printf( "*POLYLINETO16*\n" );
04253       edit_rectl( "rclBounds", rclBounds );
04254       edit_point16array( "\t", cpts, lpoints );
04255     }
04256 #endif /* ENABLE_EDITING */
04257   };
04258 
04260 
04265   class EMREXTTEXTOUTA : public METARECORD, ::EMREXTTEXTOUTA {
04266     PSTR string_a;
04267     int string_size;
04268 
04269     INT* dx_i;
04270   public:
04280     EMREXTTEXTOUTA ( const RECTL* bounds, DWORD graphicsMode, FLOAT xScale,
04281                      FLOAT yScale, const PEMRTEXT text, LPCSTR string,
04282                      const INT* dx )
04283     {
04284       emr.iType = EMR_EXTTEXTOUTA;
04285       emr.nSize = sizeof( ::EMREXTTEXTOUTA );
04286 
04287       rclBounds = *bounds;
04288 
04289       iGraphicsMode = graphicsMode;
04290       exScale = xScale;
04291       eyScale = yScale;
04292 
04293       emrtext = *text;
04294 
04295       string_size = ROUND_TO_LONG( emrtext.nChars );
04296 
04297       string_a = new CHAR[ string_size ];
04298 
04299       memset( string_a, 0, sizeof(CHAR) * string_size );
04300 
04301       for ( unsigned int i=0; i<emrtext.nChars; i++ )
04302         string_a[i] = *string++;
04303 
04304       emrtext.offString = emr.nSize;
04305       emr.nSize += string_size * sizeof(CHAR);
04306 
04307       if ( dx ) {
04308 
04309         dx_i = new INT[ emrtext.nChars ];
04310 
04311         for ( unsigned int i=0; i<emrtext.nChars; i++ )
04312           dx_i[i] = *dx++;
04313 
04314         emrtext.offDx = emr.nSize;
04315         emr.nSize += emrtext.nChars * sizeof(INT);
04316       }
04317       else {
04318         emrtext.offDx = 0;
04319         dx_i = 0;
04320       }
04321     }
04326     EMREXTTEXTOUTA ( DATASTREAM& ds )
04327     {
04328       ds >> emr >> rclBounds >> iGraphicsMode >> exScale >> eyScale >> emrtext;
04329 
04330       if ( emrtext.offString != 0 ) {
04331         string_size = ROUND_TO_LONG( emrtext.nChars );
04332 
04333         string_a = new CHAR[ string_size ];
04334 
04335         memset( string_a, 0, sizeof(CHAR) * string_size );
04336 
04337         CHARSTR string( string_a, string_size );
04338 
04339         ds >> string;
04340       }
04341       else
04342         string_a = 0;
04343 
04344       if ( emrtext.offDx ) {
04345         dx_i = new INT[ emrtext.nChars ];
04346 
04347         INTARRAY dx_is( dx_i, emrtext.nChars );
04348 
04349         ds >> dx_is;
04350       }
04351       else
04352         dx_i = 0;
04353     }
04358     ~EMREXTTEXTOUTA ( )
04359     {
04360       if ( string_a ) delete[] string_a;
04361       if ( dx_i ) delete[] dx_i;
04362     }
04366     bool serialize ( DATASTREAM ds )
04367     {
04368       ds << emr << rclBounds << iGraphicsMode << exScale << eyScale
04369          << emrtext << CHARSTR( string_a, string_size );
04370       if ( dx_i )
04371         ds << INTARRAY( dx_i, emrtext.nChars );
04372       return true;
04373     }
04377     int size ( void ) const { return emr.nSize; }
04383     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04384     {
04385       RECT rect;
04386       rect.left = emrtext.rcl.left;
04387       rect.top = emrtext.rcl.top;
04388       rect.right = emrtext.rcl.right;
04389       rect.bottom = emrtext.rcl.bottom;
04390 
04391       ExtTextOutA( dc, emrtext.ptlReference.x, emrtext.ptlReference.y,
04392                    emrtext.fOptions, &rect, string_a, emrtext.nChars,
04393                    dx_i );
04394     }
04395 #ifdef ENABLE_EDITING
04396 
04399     void edit ( void ) const
04400     {
04401       printf( "*EXTTEXTOUTA*\n" );
04402       edit_rectl( "rclBounds", rclBounds );
04403       printf( "\tiGraphicsMode\t: " );
04404       switch ( iGraphicsMode ) {
04405       case GM_COMPATIBLE: printf( "GM_COMPATIBLE\n" ); break;
04406       case GM_ADVANCED: printf( "GM_ADVANCED\n" ); break;
04407       default: printf( "unknown(%ld)\n", iGraphicsMode );
04408       }
04409       printf( "\texScale\t\t: %f\n", exScale );
04410       printf( "\teyScale\t\t: %f\n", eyScale );
04411       printf( "\tptlReference\t: (%ld,%ld)\n", emrtext.ptlReference.x,
04412               emrtext.ptlReference.y );
04413       printf( "\tnChars\t\t: %ld\n", emrtext.nChars );
04414       printf( "\toffString\t: %ld\n", emrtext.offString );
04415       printf( "\tfOptions\t: " );
04416       if ( emrtext.fOptions == 0 )
04417         printf( "None" );
04418       else {
04419         if ( emrtext.fOptions & ETO_GRAYED ) {
04420           printf( "ETO_GRAYED" );
04421           if ( emrtext.fOptions & ~ETO_GRAYED )
04422             printf( " | " );
04423         }
04424         if ( emrtext.fOptions & ETO_OPAQUE ) {
04425           printf( "ETO_OPAQUE" );
04426           if ( emrtext.fOptions & ~(ETO_GRAYED | ETO_OPAQUE) )
04427             printf( " | " );
04428         }
04429         if ( emrtext.fOptions & ETO_CLIPPED ) {
04430           printf( "ETO_CLIPPED" );
04431           if ( emrtext.fOptions & ~(ETO_GRAYED | ETO_OPAQUE | ETO_CLIPPED ) )
04432             printf( " | " );
04433         }
04434         if ( emrtext.fOptions & ETO_GLYPH_INDEX ) {
04435           printf( "ETO_GLYPH_INDEX" );
04436           if ( emrtext.fOptions &
04437                ~(ETO_GRAYED | ETO_OPAQUE | ETO_CLIPPED | ETO_GLYPH_INDEX) )
04438             printf( " | " );
04439         }
04440         if ( emrtext.fOptions & ETO_RTLREADING ) {
04441           printf( "ETO_RTLREADING" );
04442           if ( emrtext.fOptions &
04443                ~(ETO_GRAYED | ETO_OPAQUE | ETO_CLIPPED | ETO_GLYPH_INDEX |
04444                  ETO_RTLREADING) )
04445             printf( " | " );
04446         }
04447         if ( emrtext.fOptions & ETO_IGNORELANGUAGE )
04448           printf( "ETO_IGNORELANGUAGE" );
04449       }
04450       printf( "\n" );
04451       edit_rectl( "rcl\t", emrtext.rcl );
04452       printf( "\toffDx\t\t: %ld\n", emrtext.offDx );
04453       printf( "\tString:\n\t\t%s\n",  string_a );
04454 
04455       if ( emrtext.offDx != 0 ) {
04456         printf( "\tOffsets:\n\t\t" );
04457         for ( unsigned int i = 0; i < emrtext.nChars; i++ )
04458           printf( "%d ", dx_i[i] );
04459         printf( "\n" );
04460       }
04461     }
04462 #endif /* ENABLE_EDITING */
04463   };
04464 
04466 
04469   class EMRSETPIXELV : public METARECORD, ::EMRSETPIXELV {
04470   public:
04476     EMRSETPIXELV ( INT x, INT y, COLORREF color )
04477     {
04478       emr.iType = EMR_SETPIXELV;
04479       emr.nSize = sizeof( ::EMRSETPIXELV );
04480       ptlPixel.x = x;
04481       ptlPixel.y = y;
04482       crColor = color;
04483     }
04488     EMRSETPIXELV ( DATASTREAM& ds )
04489     {
04490       ds >> emr >> ptlPixel >> crColor;
04491     }
04495     bool serialize ( DATASTREAM ds )
04496     {
04497       ds << emr << ptlPixel << crColor;
04498       return true;
04499     }
04503     int size ( void ) const { return emr.nSize; }
04509     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04510     {
04511       SetPixel( dc, ptlPixel.x, ptlPixel.y, crColor );
04512     }
04513 #ifdef ENABLE_EDITING
04514 
04517     void edit ( void ) const
04518     {
04519       printf( "*SETPIXELV*\n" );
04520       edit_pointl( "ptlPixel", ptlPixel );
04521       edit_color( "crColor\t", crColor );
04522     }
04523 #endif /* ENABLE_EDITING */
04524   };
04525 
04526   class PEN;
04527   class EXTPEN;
04528   class BRUSH;
04529   class FONT;
04530   class PALETTE;
04531 
04533 
04536   class EMRCREATEPEN : public METARECORD, public ::EMRCREATEPEN
04537   {
04538   public:
04543     EMRCREATEPEN ( PEN* pen, HGDIOBJ handle );
04548     EMRCREATEPEN ( DATASTREAM& ds );
04552     bool serialize ( DATASTREAM ds )
04553     {
04554       ds << emr << ihPen << lopn;
04555       return true;
04556     }
04560     int size ( void ) const { return emr.nSize; }
04566     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
04567 #ifdef ENABLE_EDITING
04568 
04571     void edit ( void ) const
04572     {
04573       printf( "*CREATEPEN*\n" );
04574       printf( "\tihPen\t\t: 0x%lx\n", ihPen );
04575       edit_pen_style( "lopn.lopnStyle", lopn.lopnStyle );
04576       printf( "\tlopn.lopnWidth\t: %ld, %ld\n", lopn.lopnWidth.x, lopn.lopnWidth.y );
04577       edit_color( "lopn.lopnColor", lopn.lopnColor );
04578     }
04579 #endif /* ENABLE_EDITING */
04580   };
04581 
04583 
04587   class EMREXTCREATEPEN : public METARECORD, public ::EMREXTCREATEPEN
04588   {
04589   public:
04594     EMREXTCREATEPEN ( EXTPEN* pen, HGDIOBJ handle );
04599     EMREXTCREATEPEN ( DATASTREAM& ds );
04603     bool serialize ( DATASTREAM ds )
04604     {
04605       ds << emr << ihPen << offBmi << cbBmi << offBits << cbBits << elp;
04606       return true;
04607     }
04611     int size ( void ) const { return emr.nSize; }
04617     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
04618 #ifdef ENABLE_EDITING
04619 
04622     void edit ( void ) const
04623     {
04624       printf( "*EXTCREATEPEN*\n" );
04625       printf( "\tihPen\t\t\t: 0x%lx\n", ihPen );
04626       printf( "\toffBmi\t\t\t: %ld\n",  offBmi );
04627       printf( "\tcbBmi\t\t\t: %ld\n", cbBmi );
04628       printf( "\toffBits\t\t\t: %ld\n", offBits );
04629       printf( "\tcbBits\t\t\t: %ld\n", cbBits );
04630       edit_pen_style( "elp.elpPenStyle\t", elp.elpPenStyle );
04631       printf( "\telp.elpWidth\t\t: %ld\n", elp.elpWidth );
04632       edit_brush_style( "elp.elpBrushStyle", elp.elpBrushStyle );
04633       edit_color( "elp.elpColor\t", elp.elpColor );
04634       edit_brush_hatch( "elp.elpHatch\t", elp.elpHatch );
04635       printf( "\telp.elpNumEntries\t: %ld\n", elp.elpNumEntries );
04636     }
04637 #endif /* ENABLE_EDITING */
04638   };
04639 
04641 
04644   class EMRCREATEBRUSHINDIRECT : public METARECORD, public ::EMRCREATEBRUSHINDIRECT
04645   {
04646   public:
04651     EMRCREATEBRUSHINDIRECT ( BRUSH* brush, HGDIOBJ handle );
04656     EMRCREATEBRUSHINDIRECT ( DATASTREAM& ds );
04660     bool serialize ( DATASTREAM ds )
04661     {
04662       ds << emr << ihBrush << lb;
04663       return true;
04664     }
04668     int size ( void ) const { return emr.nSize; }
04674     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
04675 #ifdef ENABLE_EDITING
04676 
04679     void edit ( void ) const
04680     {
04681       printf( "*CREATEBRUSHINDIRECT*\n" );
04682       printf( "\tihBrush\t\t: 0x%lx\n", ihBrush );
04683       edit_brush_style( "lb.lbStyle", lb.lbStyle );
04684       edit_color( "lb.lbColor", lb.lbColor );
04685       edit_brush_hatch( "lb.lbHatch", lb.lbHatch );
04686     }
04687 #endif /* ENABLE_EDITING */
04688   };
04689 
04691 
04694   class EMREXTCREATEFONTINDIRECTW : public METARECORD, public ::EMREXTCREATEFONTINDIRECTW
04695   {
04696   public:
04701     EMREXTCREATEFONTINDIRECTW ( FONT* font, HGDIOBJ handle );
04706     EMREXTCREATEFONTINDIRECTW ( DATASTREAM& ds );
04710     bool serialize ( DATASTREAM ds )
04711     {
04712       // Since EMF records have to be multiples of 4 bytes, this
04713       // should perhaps be a general thing, but we know it's currently
04714       // only a problem for this structure.
04715 
04716       ds << emr << ihFont << elfw << PADDING( 2 );
04717 
04718       return true;
04719     }
04723     int size ( void ) const { return emr.nSize; }
04729     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
04730 #ifdef ENABLE_EDITING
04731 
04734     void edit ( void ) const
04735     {
04736       printf( "*EXTCREATEFONTINDIRECTW*\n" );
04737       printf( "\tihFont\t\t\t: %ld\n", ihFont );
04738       printf( "\tlfHeight\t\t: %ld\n", elfw.elfLogFont.lfHeight );
04739       printf( "\tlfWidth\t\t\t: %ld\n", elfw.elfLogFont.lfWidth );
04740       printf( "\tlfEscapement\t\t: %ld\n", elfw.elfLogFont.lfEscapement );
04741       printf( "\tlfOrientation\t\t: %ld\n", elfw.elfLogFont.lfOrientation );
04742       printf( "\tlfWeight\t\t: " );
04743       switch ( elfw.elfLogFont.lfWeight ) {
04744       case FW_DONTCARE: printf( "FW_DONTCARE\n" ); break;
04745       case FW_THIN: printf( "FW_THIN\n" ); break;
04746       case FW_EXTRALIGHT: printf( "FW_EXTRALIGHT\n" ); break;
04747       case FW_LIGHT: printf( "FW_LIGHT\n" ); break;
04748       case FW_NORMAL: printf( "FW_NORMAL\n" ); break;
04749       case FW_MEDIUM: printf( "FW_MEDIUM\n" ); break;
04750       case FW_SEMIBOLD: printf( "FW_SEMIBOLD\n" ); break;
04751       case FW_BOLD: printf( "FW_BOLD\n" ); break;
04752       case FW_EXTRABOLD: printf( "FW_EXTRABOLD\n" ); break;
04753       case FW_BLACK: printf( "FW_BLACK\n" ); break;
04754       }
04755       printf( "\tlfItalic\t\t: %d\n", elfw.elfLogFont.lfItalic );
04756       printf( "\tlfUnderline\t\t: %d\n", elfw.elfLogFont.lfUnderline );
04757       printf( "\tlfStrikeOut\t\t: %d\n", elfw.elfLogFont.lfStrikeOut );
04758       printf( "\tlfCharSet\t\t: %d\n", elfw.elfLogFont.lfCharSet );
04759       printf( "\tlfOutPrecision\t\t: %d\n", elfw.elfLogFont.lfOutPrecision );
04760       printf( "\tlfClipPrecision\t\t: %d\n", elfw.elfLogFont.lfClipPrecision );
04761       printf( "\tlfQuality\t\t: %d\n", elfw.elfLogFont.lfQuality );
04762       printf( "\tlfPitchAndFamily\t: %d\n", elfw.elfLogFont.lfPitchAndFamily );
04763       int i = 0;
04764       printf( "\tlfFaceName\t\t: '" );
04765       while ( elfw.elfLogFont.lfFaceName[i] != 0 && i < LF_FACESIZE ) {
04766         putchar( elfw.elfLogFont.lfFaceName[i] );
04767         i++;
04768       }
04769       puts( "'" );
04770 
04771       i = 0;
04772       printf( "\telfFullName\t\t: '" );
04773       while ( elfw.elfFullName[i] != 0 && i < LF_FULLFACESIZE ) {
04774         putchar( elfw.elfFullName[i] );
04775         i++;
04776       }
04777       puts( "'" );
04778 
04779       i = 0;
04780       printf( "\telfStyle\t\t: '" );
04781       while ( elfw.elfStyle[i] != 0 && i < LF_FACESIZE ) {
04782         putchar( elfw.elfStyle[i] );
04783         i++;
04784       }
04785       puts( "'" );
04786 
04787       printf( "\telfVersion\t\t: %ld\n", elfw.elfVersion );
04788       printf( "\telfStyleSize\t\t: %ld\n", elfw.elfStyleSize );
04789       printf( "\telfMatch\t\t: %ld\n", elfw.elfMatch );
04790       printf( "\telfVendorId\t\t: '%s'\n", elfw.elfVendorId );
04791       printf( "\telfCulture\t\t: %ld\n", elfw.elfCulture );
04792       printf( "\telfPanose\t\t:\n" );
04793       printf( "\t\tbFamilyType\t\t: %d\n", elfw.elfPanose.bFamilyType );
04794       printf( "\t\tbSerifStyle\t\t: %d\n", elfw.elfPanose.bSerifStyle );
04795       printf( "\t\tbWeight\t\t\t: %d\n", elfw.elfPanose.bWeight );
04796       printf( "\t\tbProportion\t\t: %d\n", elfw.elfPanose.bProportion );
04797       printf( "\t\tbContrast\t\t: %d\n", elfw.elfPanose.bContrast );
04798       printf( "\t\tbStrokeVariation\t: %d\n", elfw.elfPanose.bStrokeVariation );
04799       printf( "\t\tbArmStyle\t\t: %d\n", elfw.elfPanose.bArmStyle );
04800       printf( "\t\tbLetterform\t\t: %d\n", elfw.elfPanose.bLetterform );
04801       printf( "\t\tbMidline\t\t: %d\n", elfw.elfPanose.bMidline );
04802       printf( "\t\tbXHeight\t\t: %d\n", elfw.elfPanose.bXHeight );
04803     }
04804 #endif /* ENABLE_EDITING */
04805   };
04806 
04808 
04811   class EMRCREATEPALETTE : public METARECORD, public ::EMRCREATEPALETTE
04812   {
04813   public:
04818     EMRCREATEPALETTE ( PALETTE* palette, HGDIOBJ handle );
04823     EMRCREATEPALETTE ( DATASTREAM& ds );
04827     bool serialize ( DATASTREAM ds )
04828     {
04829       ds << emr << ihPal << lgpl;
04830       return true;
04831     }
04835     int size ( void ) const { return emr.nSize; }
04841     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
04842 #ifdef ENABLE_EDITING
04843 
04846     void edit ( void ) const
04847     {
04848       printf( "*CREATEPALETTE* (not really handled by libEMF)\n" );
04849     }
04850 #endif /* ENABLE_EDITING */
04851   };
04852 
04854 
04857   class EMRFILLPATH : public METARECORD, ::EMRFILLPATH {
04858   public:
04863     EMRFILLPATH ( const RECTL* bounds )
04864     {
04865       emr.iType = EMR_FILLPATH;
04866       emr.nSize = sizeof( ::EMRFILLPATH );
04867       rclBounds = *bounds;
04868     }
04873     EMRFILLPATH ( DATASTREAM& ds )
04874     {
04875       ds >> emr >> rclBounds;
04876     }
04880     bool serialize ( DATASTREAM ds )
04881     {
04882       ds << emr << rclBounds;
04883       return true;
04884     }
04888     int size ( void ) const { return emr.nSize; }
04894     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04895     {
04896       FillPath( dc );
04897     }
04898 #ifdef ENABLE_EDITING
04899 
04902     void edit ( void ) const
04903     {
04904       printf( "*FILLPATH*\n" );
04905       edit_rectl( "rclBounds", rclBounds );
04906     }
04907 #endif /* ENABLE_EDITING */
04908   };
04910 
04913   class EMRSTROKEPATH : public METARECORD, ::EMRSTROKEPATH {
04914   public:
04919     EMRSTROKEPATH ( const RECTL* bounds )
04920     {
04921       emr.iType = EMR_STROKEPATH;
04922       emr.nSize = sizeof( ::EMRSTROKEPATH );
04923       rclBounds = *bounds;
04924     }
04929     EMRSTROKEPATH ( DATASTREAM& ds )
04930     {
04931       ds >> emr >> rclBounds;
04932     }
04936     bool serialize ( DATASTREAM ds )
04937     {
04938       ds << emr << rclBounds;
04939       return true;
04940     }
04944     int size ( void ) const { return emr.nSize; }
04950     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04951     {
04952       StrokePath( dc );
04953     }
04954 #ifdef ENABLE_EDITING
04955 
04958     void edit ( void ) const
04959     {
04960       printf( "*STROKEPATH*\n" );
04961       edit_rectl( "rclBounds", rclBounds );
04962     }
04963 #endif /* ENABLE_EDITING */
04964   };
04966 
04969   class EMRBEGINPATH : public METARECORD, ::EMRBEGINPATH {
04970   public:
04974     EMRBEGINPATH ( void )
04975     {
04976       emr.iType = EMR_BEGINPATH;
04977       emr.nSize = sizeof( ::EMRBEGINPATH );
04978     }
04983     EMRBEGINPATH ( DATASTREAM& ds )
04984     {
04985       ds >> emr;
04986     }
04990     bool serialize ( DATASTREAM ds )
04991     {
04992       ds << emr;
04993       return true;
04994     }
04998     int size ( void ) const { return emr.nSize; }
05004     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05005     {
05006       BeginPath( dc );
05007     }
05008 #ifdef ENABLE_EDITING
05009 
05012     void edit ( void ) const
05013     {
05014       printf( "*BEGINPATH*\n" );
05015     }
05016 #endif /* ENABLE_EDITING */
05017   };
05019 
05022   class EMRENDPATH : public METARECORD, ::EMRENDPATH {
05023   public:
05027     EMRENDPATH ( void )
05028     {
05029       emr.iType = EMR_ENDPATH;
05030       emr.nSize = sizeof( ::EMRENDPATH );
05031     }
05036     EMRENDPATH ( DATASTREAM& ds )
05037     {
05038       ds >> emr;
05039     }
05043     bool serialize ( DATASTREAM ds )
05044     {
05045       ds << emr;
05046       return true;
05047     }
05051     int size ( void ) const { return emr.nSize; }
05057     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05058     {
05059       EndPath( dc );
05060     }
05061 #ifdef ENABLE_EDITING
05062 
05065     void edit ( void ) const
05066     {
05067       printf( "*ENDPATH*\n" );
05068     }
05069 #endif /* ENABLE_EDITING */
05070   };
05072 
05075   class EMRCLOSEFIGURE : public METARECORD, ::EMRCLOSEFIGURE {
05076   public:
05080     EMRCLOSEFIGURE ( void )
05081     {
05082       emr.iType = EMR_CLOSEFIGURE;
05083       emr.nSize = sizeof( ::EMRCLOSEFIGURE );
05084     }
05089     EMRCLOSEFIGURE ( DATASTREAM& ds )
05090     {
05091       ds >> emr;
05092     }
05096     bool serialize ( DATASTREAM ds )
05097     {
05098       ds << emr;
05099       return true;
05100     }
05104     int size ( void ) const { return emr.nSize; }
05110     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05111     {
05112       CloseFigure( dc );
05113     }
05114 #ifdef ENABLE_EDITING
05115 
05118     void edit ( void ) const
05119     {
05120       printf( "*CLOSEFIGURE*\n" );
05121     }
05122 #endif /* ENABLE_EDITING */
05123   };
05125 
05129   class EMRSAVEDC : public METARECORD, ::EMRSAVEDC {
05130   public:
05134     EMRSAVEDC ( void )
05135     {
05136       emr.iType = EMR_SAVEDC;
05137       emr.nSize = sizeof( ::EMRSAVEDC );
05138     }
05143     EMRSAVEDC ( DATASTREAM& ds )
05144     {
05145       ds >> emr;
05146     }
05150     bool serialize ( DATASTREAM ds )
05151     {
05152       ds << emr;
05153       return true;
05154     }
05158     int size ( void ) const { return emr.nSize; }
05164     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05165     {
05166       SaveDC( dc );
05167     }
05168 #ifdef ENABLE_EDITING
05169 
05172     void edit ( void ) const
05173     {
05174       printf( "*SAVEDC*\n" );
05175     }
05176 #endif /* ENABLE_EDITING */
05177   };
05179 
05182   class EMRRESTOREDC : public METARECORD, ::EMRRESTOREDC {
05183   public:
05187     EMRRESTOREDC ( INT n )
05188     {
05189       emr.iType = EMR_RESTOREDC;
05190       emr.nSize = sizeof( ::EMRRESTOREDC );
05191       iRelative = n;
05192     }
05197     EMRRESTOREDC ( DATASTREAM& ds )
05198     {
05199       ds >> emr >> iRelative;
05200     }
05204     bool serialize ( DATASTREAM ds )
05205     {
05206       ds << emr << iRelative;
05207       return true;
05208     }
05212     int size ( void ) const { return emr.nSize; }
05218     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05219     {
05220       RestoreDC( dc, iRelative );
05221     }
05222 #ifdef ENABLE_EDITING
05223 
05226     void edit ( void ) const
05227     {
05228       printf( "*RESTOREDC*\n" );
05229       printf( "\tiRelative: %ld\n", iRelative );
05230     }
05231 #endif /* ENABLE_EDITING */
05232   };
05234 
05237   class EMRSETMETARGN : public METARECORD, ::EMRSETMETARGN {
05238   public:
05242     EMRSETMETARGN ( void )
05243     {
05244       emr.iType = EMR_SETMETARGN;
05245       emr.nSize = sizeof( ::EMRSETMETARGN );
05246     }
05251     EMRSETMETARGN ( DATASTREAM& ds )
05252     {
05253       ds >> emr;
05254     }
05258     bool serialize ( DATASTREAM ds )
05259     {
05260       ds << emr;
05261       return true;
05262     }
05266     int size ( void ) const { return emr.nSize; }
05272     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05273     {
05274       SetMetaRgn( dc );
05275     }
05276 #ifdef ENABLE_EDITING
05277 
05280     void edit ( void ) const
05281     {
05282       printf( "*SETMETARGN*\n" );
05283     }
05284 #endif /* ENABLE_EDITING */
05285   };
05286 
05288 
05291   class PEN : public GRAPHICSOBJECT, public LOGPEN {
05292   public:
05296     PEN ( const LOGPEN* lpen )
05297     {
05298       lopnStyle = lpen->lopnStyle;
05299       lopnWidth = lpen->lopnWidth;
05300       lopnColor = lpen->lopnColor;
05301     }
05305     OBJECTTYPE getType ( void ) const { return O_PEN; }
05312     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
05313     {
05314       contexts[dc] = emf_handle;
05315       return new EMRCREATEPEN( this, emf_handle );
05316     }
05317   };
05318 
05320 
05323   class EXTPEN : public GRAPHICSOBJECT, public EXTLOGPEN {
05324   public:
05328     EXTPEN ( const EXTLOGPEN* lpen )
05329     {
05330       elpPenStyle = lpen->elpPenStyle;
05331       elpWidth = lpen->elpWidth;
05332       elpBrushStyle = lpen->elpBrushStyle;
05333       elpColor = lpen->elpColor;
05334       elpHatch = lpen->elpHatch;
05335       elpNumEntries = 0;
05336       elpStyleEntry[0] = 0;
05337     }
05341     OBJECTTYPE getType ( void ) const { return O_EXTPEN; }
05348     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
05349     {
05350       contexts[dc] = emf_handle;
05351       return new EMREXTCREATEPEN( this, emf_handle );
05352     }
05353   };
05354 
05356 
05359   class BRUSH : public GRAPHICSOBJECT, public LOGBRUSH {
05360   public:
05364     BRUSH ( const LOGBRUSH* lbrush )
05365     {
05366       lbStyle = lbrush->lbStyle;
05367       lbColor = lbrush->lbColor;
05368       lbHatch = lbrush->lbHatch;
05369     }
05373     OBJECTTYPE getType ( void ) const { return O_BRUSH; }
05380     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
05381     {
05382       contexts[dc] = emf_handle;
05383       return new EMRCREATEBRUSHINDIRECT( this, emf_handle );
05384     }
05385   };
05386 
05388 
05391   class FONT : public GRAPHICSOBJECT, public EXTLOGFONTW {
05392   public:
05396     FONT ( const LOGFONTW* lfont )
05397     {
05398       this->elfLogFont = *lfont;
05399       // There are a lot more entries in the EXTLOGFONTW structure than
05400       // the API has values for, so we invent them here
05401       memset( &elfFullName, 0, sizeof elfFullName );
05402       memset( &elfStyle, 0, sizeof elfStyle );
05403       elfVersion = ELF_VERSION;
05404       elfStyleSize = 0;
05405       elfMatch = 0;
05406       elfReserved = 0;
05407       memset( &elfVendorId, 0, sizeof elfVendorId );
05408       elfCulture = ELF_CULTURE_LATIN;
05409       memset( &elfPanose, 1, sizeof(PANOSE) );
05410     }
05414     OBJECTTYPE getType ( void ) const { return O_FONT; }
05421     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
05422     {
05423       contexts[dc] = emf_handle;
05424       return new EMREXTCREATEFONTINDIRECTW( this, emf_handle );
05425     }
05426   };
05427 
05429 
05432   class PALETTE : public GRAPHICSOBJECT, public LOGPALETTE {
05433   public:
05437     PALETTE ( const LOGPALETTE* lpalette )
05438     {
05439       (void)lpalette;
05440       palVersion = 0;
05441       palNumEntries = 0;
05442       PALETTEENTRY zero_entry = { 0, 0, 0, 0 };
05443       palPalEntry[0] = zero_entry;
05444     }
05448     OBJECTTYPE getType ( void ) const { return O_PALETTE; }
05455     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
05456     {
05457       contexts[dc] = emf_handle;
05458       return new EMRCREATEPALETTE( this, emf_handle );
05459     }
05460   };
05461 
05463 
05469   class METAFILEDEVICECONTEXT : public OBJECT {
05477     void init ( const RECT* size, LPCWSTR description_w ) {
05478 
05479       // Evidently, metafile handles are numbered from 1, so don't
05480       // ever use 0.
05481 
05482       handles.push_back( true );
05483 
05484       // Keep some of our graphics state in a header record
05485 
05486       header = new ENHMETAHEADER ( description_w );
05487       records.push_back( header );
05488 
05489       // Compute the size and position of the metafile on the "page"
05490 
05491       if ( size ) {
05492         update_frame = false;
05493 
05494         header->rclFrame.left = size->left;
05495         header->rclFrame.top = size->top;
05496         header->rclFrame.right = size->right;
05497         header->rclFrame.bottom = size->bottom;
05498 
05499         header->rclBounds.left =
05500           size->left * header->szlDevice.cx / ( header->szlMillimeters.cx * 100 );
05501         header->rclBounds.top =
05502           size->top * header->szlDevice.cy / ( header->szlMillimeters.cy * 100 );
05503         header->rclBounds.right =
05504           size->right * header->szlDevice.cx / ( header->szlMillimeters.cx * 100 );
05505         header->rclBounds.bottom =
05506           size->bottom * header->szlDevice.cy / ( header->szlMillimeters.cy * 100 );
05507       }
05508       else {
05509         update_frame = true;
05510 
05511         header->rclBounds.left = -10;
05512         header->rclBounds.top = -10;
05513         header->rclBounds.right = 10;
05514         header->rclBounds.bottom = 10;
05515 
05516         header->rclFrame.left = (LONG)floor( (float)header->rclBounds.left *
05517           header->szlMillimeters.cx * 100 / header->szlDevice.cx );
05518         header->rclFrame.top = (LONG)floor( (float)header->rclBounds.top *
05519           header->szlMillimeters.cy * 100 / header->szlDevice.cy );
05520         header->rclFrame.right = (LONG)ceil( (float)header->rclBounds.right *
05521           header->szlMillimeters.cx * 100 / header->szlDevice.cx );
05522         header->rclFrame.bottom = (LONG)ceil( (float)header->rclBounds.bottom *
05523           header->szlMillimeters.cy * 100 / header->szlDevice.cy );
05524       }
05525 
05526       // Some default graphics state (are they really, though?)
05527 
05528       SIZEL default_resolution = { RESOLUTION, RESOLUTION };
05529       resolution = default_resolution;
05530       SIZEL default_viewport_ext = { 1, 1 };
05531       viewport_ext = default_viewport_ext;
05532       POINT default_viewport_org = { 0, 0 };
05533       viewport_org = default_viewport_org;
05534       SIZEL default_window_ext = { 1, 1 };
05535       window_ext = default_window_ext;
05536       POINT default_window_org = { 0, 0 };
05537       window_org = default_window_org;
05538 
05539       min_device_point = viewport_org;
05540       max_device_point = viewport_org;
05541 
05542       pen = (PEN*)globalObjects.find( BLACK_PEN | ENHMETA_STOCK_OBJECT );
05543       brush = (BRUSH*)globalObjects.find( BLACK_BRUSH | ENHMETA_STOCK_OBJECT );
05544       font = (FONT*)globalObjects.find( DEVICE_DEFAULT_FONT | ENHMETA_STOCK_OBJECT);
05545       palette = (PALETTE*)globalObjects.find( DEFAULT_PALETTE|ENHMETA_STOCK_OBJECT);
05546 
05547       text_alignment = TA_BASELINE;
05548       text_color = RGB(0,0,0);
05549       bk_color = RGB(0xff,0xff,0xff);
05550       bk_mode = OPAQUE;
05551       polyfill_mode = ALTERNATE;
05552       map_mode = MM_TEXT;
05553 
05554       handle = globalObjects.add( this );
05555     }
05556 
05557   public:
05561     ::FILE* fp;
05566     DATASTREAM ds;
05570     ENHMETAHEADER* header;
05574     std::vector< EMF::METARECORD* > records;
05575 
05576     // Keep a small set of graphics state information
05577     SIZEL resolution;           
05578     SIZEL viewport_ext;         
05579     POINT viewport_org;         
05580     SIZEL window_ext;           
05581     POINT window_org;           
05582     bool update_frame;          
05583     POINT min_device_point;     
05584     POINT max_device_point;     
05585     POINT point;                
05586     PEN* pen;                   
05587     BRUSH* brush;               
05588     FONT* font;                 
05589     PALETTE* palette;           
05590     UINT text_alignment;        
05591     COLORREF text_color;        
05592     COLORREF bk_color;          
05593     INT bk_mode;                
05594     INT polyfill_mode;          
05595     INT map_mode;               
05596 
05602     std::vector< bool > handles;
05603 
05609     std::map< HGDIOBJ, HGDIOBJ > emf_handles;
05610 
05621       METAFILEDEVICECONTEXT ( FILE* fp_, const RECT* size,
05622                               LPCWSTR description_w )
05623         : fp(fp_), ds( fp_ )
05624     {
05625           init( size, description_w );
05626     }
05631     virtual ~METAFILEDEVICECONTEXT ( )
05632     {
05633       // Purge all the metarecords (if there are any) {this include the
05634       // header record, too}
05635       if ( records.size() > 0 )
05636         deleteMetafile();
05637     }
05641     OBJECTTYPE getType ( void ) const { return O_METAFILEDEVICECONTEXT; }
05646     DWORD nextHandle ( void )
05647     {
05648       for ( unsigned int i = 1; i < handles.size(); i++ ) {
05649         if ( !handles[i] ) {
05650           handles[i] = true;
05651           return i;
05652         }
05653       }
05654       handles.push_back( true );
05655       // Well, it appears that even StockObject handles count for something.
05656       // Not sure what the right value here is, then.
05657       header->nHandles = handles.size();
05658       return handles.size()-1;
05659     }
05663     void clearHandle ( DWORD handle )
05664     {
05665       handles[handle] = false;
05666     }
05672     void appendRecord ( METARECORD* record )
05673     {
05674       records.push_back( record );
05675 
05676       header->nBytes += record->size();
05677       header->nRecords++;
05678     }
05684     void appendHandle ( METARECORD* record )
05685     {
05686       records.push_back( record );
05687 
05688       header->nBytes += record->size();
05689       header->nRecords++;
05690     }
05695     void deleteMetafile ( void )
05696     {
05697       for ( std::vector<METARECORD*>::const_iterator r = records.begin();
05698             r != records.end();
05699             r++ ) {
05700         delete *r;
05701       }
05702       records.clear();
05703     }
05708     void mergePoint ( const LONG& x, const LONG& y )
05709     {
05710       POINT p;
05711       p.x = x;
05712       p.y = y;
05713       mergePoint( p );
05714     }
05719     void mergePoint( const POINT& p )
05720     {
05721       POINT device_point;
05722 
05723       // *** Note, it's possible for the global transformation matrix to
05724       // affect this too. ***
05725 
05726       device_point.x = (LONG)( (float)( p.x - window_org.x ) / window_ext.cx *
05727         viewport_ext.cx + viewport_org.x );
05728 
05729       device_point.y = (LONG)( (float)( p.y - window_org.y ) / window_ext.cy *
05730         viewport_ext.cy + viewport_org.y );
05731 
05732       // If the user didn't specify a bounding rectangle in the constructor,
05733       // compute one from this data, too.
05734       if ( device_point.x < min_device_point.x ) {
05735         min_device_point.x = device_point.x;
05736         if ( update_frame ) {
05737           header->rclBounds.left = min_device_point.x - 10;
05738           header->rclFrame.left = (LONG)floor( (float)header->rclBounds.left *
05739             header->szlMillimeters.cx * 100 / header->szlDevice.cx );
05740         }
05741       }
05742       else if ( device_point.x > max_device_point.x ) {
05743         max_device_point.x = device_point.x;
05744         if ( update_frame ) {
05745           header->rclBounds.right = max_device_point.x + 10;
05746           header->rclFrame.right = (LONG)ceil( (float)header->rclBounds.right *
05747             header->szlMillimeters.cx * 100 / header->szlDevice.cx );
05748         }
05749       }
05750 
05751       if ( device_point.y < min_device_point.y ) {
05752         min_device_point.y = device_point.y;
05753         if ( update_frame ) {
05754           header->rclBounds.top = min_device_point.y - 10;
05755           header->rclFrame.top = (LONG)floor( (float)header->rclBounds.top *
05756             header->szlMillimeters.cy * 100 / header->szlDevice.cy );
05757         }
05758       }
05759       else if ( device_point.y > max_device_point.y ) {
05760         max_device_point.y = device_point.y;
05761         if ( update_frame ) {
05762           header->rclBounds.bottom = max_device_point.y + 10;
05763           header->rclFrame.bottom = (LONG)ceil( (float)header->rclBounds.bottom *
05764             header->szlMillimeters.cy * 100 / header->szlDevice.cy );
05765         }
05766       }
05767     }
05768   };
05769 
05770 } // close EMF namespace
05771 
05772 #endif /* _LIBEMF_H */

Generated at Mon Jan 28 14:57:44 2002 for EMF by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001