EMF  1.0
libemf.h
00001 /* -*- c++ -*-
00002  * EMF: A library for generating ECMA-234 Enhanced Metafiles
00003  * Copyright (C) 2002, 2003 lignum Computing, Inc. <dallenbarnett@users.sourceforge.net>
00004  * $Id: libemf.h 62 2012-11-06 12:16:29Z dallenbarnett $
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 #ifndef _LIBEMF_H
00022 #define _LIBEMF_H 1
00023 
00024 #include <cmath>
00025 #include <vector>
00026 #include <map>
00027 #include <functional>
00028 #include <algorithm>
00029 
00030 #include <config.h>
00031 #include <libEMF/emf.h>
00032 
00033 #include <libEMF/wine/w16.h>
00034 
00035 namespace EMF {
00040 #if 1
00041   const int XMAX_PIXELS = 1024; /*(INT_MAX)*/
00042 #else
00043   const int XMAX_PIXELS = 1280; /*(INT_MAX)*/
00044 #endif
00045 
00049 #if 1
00050   const int YMAX_PIXELS = 768; /*(INT_MAX)*/
00051 #else
00052   const int YMAX_PIXELS = 1024; /*(INT_MAX)*/
00053 #endif
00054 
00059   const int XMAX_MM = 320;
00065   const int YMAX_MM = 240;
00069   const int RESOLUTION = 96;
00073   static inline int ROUND_TO_LONG ( int n ) { return ((n+3)/4)*4; }
00074 
00076 
00081   struct WCHARSTR {
00082     WCHAR *const string_;       
00083     const int length_;          
00084 
00089     WCHARSTR ( WCHAR *const string, const int length )
00090       : string_( string ), length_( length ) {}
00091   };
00092 
00094 
00099   struct CHARSTR {
00100     CHAR *const string_;        
00101     const int length_;          
00102 
00107     CHARSTR ( CHAR *const string, const int length )
00108       : string_( string ), length_( length ) {}
00109   };
00110 
00112 
00116   struct BYTEARRAY {
00117     BYTE *const array_;         
00118     const int n_;               
00119 
00124     BYTEARRAY ( BYTE *const array, const int n )
00125       : array_( array ), n_( n ) {}
00126   };
00127 
00129 
00132   struct POINTLARRAY {
00133     POINTL *const points_;      
00134     const DWORD n_;             
00135 
00140     POINTLARRAY ( POINTL *const points, const DWORD n )
00141       : points_( points ), n_( n ) {}
00142   };
00143 
00145 
00148   struct POINT16ARRAY {
00149     POINT16 *const points_;     
00150     const DWORD n_;             
00151 
00156     POINT16ARRAY ( POINT16 *const points, const DWORD n )
00157       : points_( points ), n_( n ) {}
00158   };
00159 
00161 
00164   struct INTARRAY {
00165     INT *const ints_;           
00166     const DWORD n_;             
00167 
00172     INTARRAY ( INT *const ints, const DWORD n )
00173       : ints_( ints ), n_( n ) {}
00174   };
00175 
00177 
00180   struct DWORDARRAY {
00181     DWORD *const dwords_;       
00182     const DWORD n_;             
00183 
00188     DWORDARRAY ( DWORD *const dwords, const DWORD n )
00189       : dwords_( dwords ), n_( n ) {}
00190   };
00191 
00193 
00196   struct PADDING {
00197     static const char padding_[4]; 
00198     const int size_;            
00199 
00203     PADDING ( const int size ) : size_( size ) {}
00204   };
00205   
00207 
00214   class DATASTREAM {
00215     bool swap_;
00216     ::FILE* fp_;
00217 
00218     static bool bigEndian ( void );
00219   public:
00225     DATASTREAM ( ::FILE* fp = 0 ) : swap_( bigEndian() ), fp_( fp ) {}
00230     void setStream ( ::FILE* fp ) { fp_ = fp; }
00235     DATASTREAM& operator<< ( const BYTE& byte )
00236     {
00237       fwrite( &byte, sizeof(BYTE), 1, fp_ );
00238       return *this;
00239     }
00244     DATASTREAM& operator>> ( BYTE& byte )
00245     {
00246       fread( &byte, sizeof(BYTE), 1, fp_ );
00247       return *this;
00248     }
00253     DATASTREAM& operator<< ( const WORD& word )
00254     {
00255       if ( swap_ ) {
00256         unsigned char const * p = (unsigned char const*)&word;
00257         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00258         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00259       }
00260       else
00261         fwrite( &word, sizeof(WORD), 1, fp_ );
00262       return *this;
00263     }
00268     DATASTREAM& operator>> ( WORD& word )
00269     {
00270       if ( swap_ ) {
00271         unsigned char* p = (unsigned char*)&word;
00272         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00273         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00274       }
00275       else
00276         fread( &word, sizeof(WORD), 1, fp_ );
00277       return *this;
00278     }
00283     DATASTREAM& operator<< ( const INT16& word )
00284     {
00285       if ( swap_ ) {
00286         unsigned char const * p = (unsigned char const*)&word;
00287         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00288         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00289       }
00290       else
00291         fwrite( &word, sizeof(INT16), 1, fp_ );
00292       return *this;
00293     }
00298     DATASTREAM& operator>> ( INT16& word )
00299     {
00300       if ( swap_ ) {
00301         unsigned char* p = (unsigned char*)&word;
00302         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00303         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00304       }
00305       else
00306         fread( &word, sizeof(INT16), 1, fp_ );
00307       return *this;
00308     }
00313     DATASTREAM& operator<< ( const DWORD& dword )
00314     {
00315       if ( swap_ ) {
00316         unsigned char const* p = (unsigned char const*)&dword;
00317         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00318         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00319         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00320         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00321       }
00322       else
00323         fwrite( &dword, sizeof(DWORD), 1, fp_ );
00324       return *this;
00325     }
00330     DATASTREAM& operator>> ( DWORD& dword )
00331     {
00332       if ( swap_ ) {
00333         unsigned char* p = (unsigned char*)&dword;
00334         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00335         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00336         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00337         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00338       }
00339       else
00340         fread( &dword, sizeof(DWORD), 1, fp_ );
00341       return *this;
00342     }
00343 #if !defined( __LP64__ )
00344 
00348     DATASTREAM& operator<< ( const LONG& long_ )
00349     {
00350       if ( swap_ ) {
00351         unsigned char const* p = (unsigned char const*)&long_;
00352         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00353         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00354         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00355         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00356       }
00357       else
00358         fwrite( &long_, sizeof(LONG), 1, fp_ );
00359       return *this;
00360     }
00365     DATASTREAM& operator>> ( LONG& long_ )
00366     {
00367       if ( swap_ ) {
00368         unsigned char* p = (unsigned char*)&long_;
00369         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00370         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00371         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00372         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00373       }
00374       else
00375         fread( &long_, sizeof(LONG), 1, fp_ );
00376       return *this;
00377     }
00378 #endif /* __x86_64__ */
00379 
00383     DATASTREAM& operator<< ( const INT& int_ )
00384     {
00385       if ( swap_ ) {
00386         unsigned char const* p = (unsigned char const*)&int_;
00387         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00388         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00389         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00390         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00391       }
00392       else
00393         fwrite( &int_, sizeof(INT), 1, fp_ );
00394       return *this;
00395     }
00400     DATASTREAM& operator>> ( INT& int_ )
00401     {
00402       if ( swap_ ) {
00403         unsigned char* p = (unsigned char*)&int_;
00404         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00405         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00406         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00407         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00408       }
00409       else
00410         fread( &int_, sizeof(INT), 1, fp_ );
00411       return *this;
00412     }
00413 #if !defined(__LP64__)
00414 
00418     DATASTREAM& operator<< ( const UINT& uint )
00419     {
00420       if ( swap_ ) {
00421         unsigned char const* p = (unsigned char const*)&uint;
00422         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00423         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00424         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00425         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00426       }
00427       else
00428         fwrite( &uint, sizeof(UINT), 1, fp_ );
00429       return *this;
00430     }
00435     DATASTREAM& operator>> ( UINT& uint )
00436     {
00437       if ( swap_ ) {
00438         unsigned char* p = (unsigned char*)&uint;
00439         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00440         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00441         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00442         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00443       }
00444       else
00445         fread( &uint, sizeof(UINT), 1, fp_ );
00446       return *this;
00447     }
00448 #endif /* !__x86_64__ */
00449 
00453     DATASTREAM& operator<< ( const FLOAT& float_ )
00454     {
00455       if ( swap_ ) {
00456         unsigned char const* p = (unsigned char const*)&float_;
00457         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00458         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00459         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00460         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00461       }
00462       else
00463         fwrite( &float_, sizeof(FLOAT), 1, fp_ );
00464       return *this;
00465     }
00470     DATASTREAM& operator>> ( FLOAT& float_ )
00471     {
00472       if ( swap_ ) {
00473         unsigned char* p = (unsigned char*)&float_;
00474         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00475         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00476         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00477         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00478       }
00479       else
00480         fread( &float_, sizeof(FLOAT), 1, fp_ );
00481       return *this;
00482     }
00487     DATASTREAM& operator<< ( const PADDING& padding )
00488     {
00489       if ( padding.size_ != 0 )
00490         fwrite( &padding.padding_, sizeof(CHAR), padding.size_, fp_ );
00491       return *this;
00492     }
00497     DATASTREAM& operator<< ( const RECTL& rectl )
00498     {
00499       *this << rectl.left << rectl.top << rectl.right << rectl.bottom;
00500       return *this;
00501     }
00506     DATASTREAM& operator>> ( RECTL& rectl )
00507     {
00508       *this >> rectl.left >> rectl.top >> rectl.right >> rectl.bottom;
00509       return *this;
00510     }
00515     DATASTREAM& operator<< ( const SIZEL& sizel )
00516     {
00517       *this << sizel.cx << sizel.cy;
00518       return *this;
00519     }
00524     DATASTREAM& operator>> ( SIZEL& sizel )
00525     {
00526       *this >> sizel.cx >> sizel.cy;
00527       return *this;
00528     }
00533     DATASTREAM& operator<< ( const WCHARSTR& wcharstr )
00534     {
00535       for ( int i = 0; i < wcharstr.length_; i++ )
00536         *this << wcharstr.string_[i];
00537       return *this;
00538     }
00543     DATASTREAM& operator>> ( WCHARSTR& wcharstr )
00544     {
00545       for ( int i = 0; i < wcharstr.length_; i++ )
00546         *this >> wcharstr.string_[i];
00547       return *this;
00548     }
00553     DATASTREAM& operator<< ( const CHARSTR& charstr )
00554     {
00555       fwrite( charstr.string_, sizeof(CHAR), charstr.length_, fp_ );
00556       return *this;
00557     }
00562     DATASTREAM& operator>> ( CHARSTR& charstr )
00563     {
00564       fread( charstr.string_, sizeof(CHAR), charstr.length_, fp_ );
00565       return *this;
00566     }
00571     DATASTREAM& operator<< ( const ::EMR& emr )
00572     {
00573       *this << emr.iType << emr.nSize;
00574       return *this;
00575     }
00580     DATASTREAM& operator>> ( ::EMR& emr )
00581     {
00582       *this >> emr.iType >> emr.nSize;
00583       return *this;
00584     }
00589     DATASTREAM& operator<< ( const POINT& point )
00590     {
00591       *this << point.x << point.y;
00592       return *this;
00593     }
00598     DATASTREAM& operator>> ( POINT& point )
00599     {
00600       *this >> point.x >> point.y;
00601       return *this;
00602     }
00607     DATASTREAM& operator<< ( const POINTL& pointl )
00608     {
00609       *this << pointl.x << pointl.y;
00610       return *this;
00611     }
00616     DATASTREAM& operator>> ( POINTL& pointl )
00617     {
00618       *this >> pointl.x >> pointl.y;
00619       return *this;
00620     }
00625     DATASTREAM& operator<< ( const POINT16& point )
00626     {
00627       *this << point.x << point.y;
00628       return *this;
00629     }
00634     DATASTREAM& operator>> ( POINT16& point )
00635     {
00636       *this >> point.x >> point.y;
00637       return *this;
00638     }
00643     DATASTREAM& operator<< ( const XFORM& xform )
00644     {
00645       *this << xform.eM11 << xform.eM12 << xform.eM21 << xform.eM22
00646             << xform.eDx << xform.eDy;
00647       return *this;
00648     }
00653     DATASTREAM& operator>> ( XFORM& xform )
00654     {
00655       *this >> xform.eM11 >> xform.eM12 >> xform.eM21 >> xform.eM22
00656             >> xform.eDx >> xform.eDy;
00657       return *this;
00658     }
00663     DATASTREAM& operator<< ( const BYTEARRAY& array )
00664     {
00665       fwrite( array.array_, sizeof(BYTE), array.n_, fp_ );
00666       return *this;
00667     }
00672     DATASTREAM& operator>> ( BYTEARRAY& array )
00673     {
00674       fread( array.array_, sizeof(BYTE), array.n_, fp_ );
00675       return *this;
00676     }
00681     DATASTREAM& operator<< ( const POINTLARRAY& array )
00682     {
00683       for ( unsigned int i = 0; i < array.n_; i++ )
00684         *this << array.points_[i];
00685       return *this;
00686     }
00691     DATASTREAM& operator>> ( POINTLARRAY& array )
00692     {
00693       for ( unsigned int i = 0; i < array.n_; i++ )
00694         *this >> array.points_[i];
00695       return *this;
00696     }
00701     DATASTREAM& operator<< ( const POINT16ARRAY& array )
00702     {
00703       for ( unsigned int i = 0; i < array.n_; i++ )
00704         *this << array.points_[i];
00705       return *this;
00706     }
00711     DATASTREAM& operator>> ( POINT16ARRAY& array )
00712     {
00713       for ( unsigned int i = 0; i < array.n_; i++ )
00714         *this >> array.points_[i];
00715       return *this;
00716     }
00721     DATASTREAM& operator<< ( const INTARRAY& array )
00722     {
00723       for ( unsigned int i = 0; i < array.n_; i++ )
00724         *this << array.ints_[i];
00725       return *this;
00726     }
00731     DATASTREAM& operator>> ( INTARRAY& array )
00732     {
00733       for ( unsigned int i = 0; i < array.n_; i++ )
00734         *this >> array.ints_[i];
00735       return *this;
00736     }
00741     DATASTREAM& operator<< ( const DWORDARRAY& array )
00742     {
00743       for ( unsigned int i = 0; i < array.n_; i++ )
00744         *this << array.dwords_[i];
00745       return *this;
00746     }
00751     DATASTREAM& operator>> ( DWORDARRAY& array )
00752     {
00753       for ( unsigned int i = 0; i < array.n_; i++ )
00754         *this >> array.dwords_[i];
00755       return *this;
00756     }
00761     DATASTREAM& operator<< ( const ::EMRTEXT& text )
00762     {
00763       *this << text.ptlReference << text.nChars << text.offString << text.fOptions
00764          << text.rcl << text.offDx;
00765       return *this;
00766     }
00771     DATASTREAM& operator>> ( ::EMRTEXT& text )
00772     {
00773       *this >> text.ptlReference >> text.nChars >> text.offString >> text.fOptions
00774             >> text.rcl >> text.offDx;
00775       return *this;
00776     }
00781     DATASTREAM& operator<< ( const LOGPEN& pen )
00782     {
00783       *this << pen.lopnStyle << pen.lopnWidth << pen.lopnColor;
00784       return *this;
00785     }
00790     DATASTREAM& operator>> ( LOGPEN& pen )
00791     {
00792       *this >> pen.lopnStyle >> pen.lopnWidth >> pen.lopnColor;
00793       return *this;
00794     }
00799     DATASTREAM& operator<< ( const EXTLOGPEN& pen )
00800     {
00801       // *** How big is this structure if there are no style entries? ***
00802       *this << pen.elpPenStyle << pen.elpWidth << pen.elpBrushStyle << pen.elpColor
00803             << pen.elpHatch << pen.elpNumEntries;
00804       return *this;
00805     }
00810     DATASTREAM& operator>> ( EXTLOGPEN& pen )
00811     {
00812       // *** How big is this structure if there are no style entries? ***
00813       *this >> pen.elpPenStyle >> pen.elpWidth >> pen.elpBrushStyle >> pen.elpColor
00814             >> pen.elpHatch >> pen.elpNumEntries;
00815       return *this;
00816     }
00821     DATASTREAM& operator<< ( const LOGBRUSH& brush )
00822     {
00823       *this << brush.lbStyle << brush.lbColor << brush.lbHatch;
00824       return *this;
00825     }
00830     DATASTREAM& operator>> ( LOGBRUSH& brush )
00831     {
00832       *this >> brush.lbStyle >> brush.lbColor >> brush.lbHatch;
00833       return *this;
00834     }
00839     DATASTREAM& operator<< ( const LOGFONTW& font )
00840     {
00841       *this << font.lfHeight << font.lfWidth << font.lfEscapement
00842             << font.lfOrientation << font.lfWeight << font.lfItalic
00843             << font.lfUnderline << font.lfStrikeOut << font.lfCharSet
00844             << font.lfOutPrecision << font.lfClipPrecision << font.lfQuality
00845             << font.lfPitchAndFamily
00846             << WCHARSTR( const_cast<WCHAR*const>(font.lfFaceName), LF_FACESIZE );
00847       return *this;
00848     }
00853     DATASTREAM& operator>> ( LOGFONTW& font )
00854     {
00855       WCHARSTR wFaceName( font.lfFaceName, LF_FACESIZE );
00856 
00857       *this >> font.lfHeight >> font.lfWidth >> font.lfEscapement
00858             >> font.lfOrientation >> font.lfWeight >> font.lfItalic
00859             >> font.lfUnderline >> font.lfStrikeOut >> font.lfCharSet
00860             >> font.lfOutPrecision >> font.lfClipPrecision >> font.lfQuality
00861             >> font.lfPitchAndFamily
00862             >> wFaceName;
00863       return *this;
00864     }
00869     DATASTREAM& operator<< ( const PANOSE& panose )
00870     {
00871       fwrite( &panose, sizeof(PANOSE), 1, fp_ );
00872       return *this;
00873     }
00878     DATASTREAM& operator>> ( PANOSE& panose )
00879     {
00880       fread( &panose, sizeof(PANOSE), 1, fp_ );
00881       return *this;
00882     }
00887     DATASTREAM& operator<< ( const EXTLOGFONTW& font )
00888     {
00889       *this << font.elfLogFont
00890             << WCHARSTR( const_cast<WCHAR*const>(font.elfFullName),
00891                          LF_FULLFACESIZE )
00892             << WCHARSTR( const_cast<WCHAR*const>(font.elfStyle), LF_FACESIZE )
00893             << font.elfVersion << font.elfStyleSize << font.elfMatch
00894             << font.elfReserved
00895             << BYTEARRAY( const_cast<BYTE*const>(font.elfVendorId),
00896                           ELF_VENDOR_SIZE )
00897             << font.elfCulture << font.elfPanose;
00898       return *this;
00899     }
00904     DATASTREAM& operator>> ( EXTLOGFONTW& font )
00905     {
00906       WCHARSTR wFullName( font.elfFullName, LF_FULLFACESIZE );
00907       WCHARSTR wStyle( font.elfStyle, LF_FACESIZE );
00908       BYTEARRAY bVendorId( font.elfVendorId, ELF_VENDOR_SIZE );
00909       *this >> font.elfLogFont
00910             >> wFullName >> wStyle
00911             >> font.elfVersion >> font.elfStyleSize >> font.elfMatch
00912             >> font.elfReserved >> bVendorId
00913             >> font.elfCulture >> font.elfPanose;
00914       return *this;
00915     }
00920     DATASTREAM& operator<< ( const LOGPALETTE& palette )
00921     {
00922       // *** How big is this structure if the palette is empty? ***
00923       *this << palette.palVersion << palette.palNumEntries;
00924       return *this;
00925     }
00930     DATASTREAM& operator>> ( LOGPALETTE& palette )
00931     {
00932       // *** How big is this structure if the palette is empty? ***
00933       *this >> palette.palVersion >> palette.palNumEntries;
00934       return *this;
00935     }
00936   };
00937 
00938   class METAFILEDEVICECONTEXT;
00939 
00941 
00947   class METARECORD {
00948   public:
00955     virtual void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const = 0;
00962     virtual bool serialize ( DATASTREAM ds ) = 0;
00968     virtual int size ( void ) const = 0;
00974     virtual ~METARECORD( ) { }
00975 #ifdef ENABLE_EDITING
00976 
00980     virtual void edit ( void ) const {}
00981 #endif
00982   };
00983 
00984 #ifdef ENABLE_EDITING
00985   /* Miscellaneous editing routines */
00986   inline void edit_rectl ( const char* tag, const RECTL& rectl )
00987   {
00988 #if defined(__LP64__)
00989     const char* FMT = "\t%s\t: (%d, %d) - (%d, %d)\n";
00990 #else
00991     const char* FMT = "\t%s\t: (%ld, %ld) - (%ld, %ld)\n";
00992 #endif /* __x86_64__ */
00993     printf( FMT, tag, rectl.left, rectl.top, rectl.right, rectl.bottom );
00994   }
00995 
00996   inline void edit_xform ( const char* tag, const XFORM& xform )
00997   {
00998     printf( "\t%s.eM11\t: %f\n", tag, xform.eM11 );
00999     printf( "\t%s.eM12\t: %f\n", tag, xform.eM12 );
01000     printf( "\t%s.eM21\t: %f\n", tag, xform.eM21 );
01001     printf( "\t%s.eM22\t: %f\n", tag, xform.eM22 );
01002     printf( "\t%s.eDx\t: %f\n", tag, xform.eDx );
01003     printf( "\t%s.eDy\t: %f\n", tag, xform.eDy );
01004   }
01005 
01006   inline void edit_color ( const char* tag, const COLORREF& color )
01007   {
01008 #if defined(__LP64__)
01009     const char* FMT = "\t%s\t: R(0x%02x) G(0x%02x) B(0x%02x)\n";
01010 #else
01011     const char* FMT = "\t%s\t: R(0x%02lx) G(0x%02lx) B(0x%02lx)\n";
01012 #endif /* __x86_64__ */
01013     printf( FMT, tag,
01014             GetRValue( color ), GetGValue( color ), GetBValue( color ) );
01015   }
01016 
01017   inline void edit_sizel ( const char* tag, const SIZEL& size )
01018   {
01019 #if defined(__LP64__)
01020     const char* FMT = "\t%s\t: (%d, %d)\n";
01021 #else
01022     const char* FMT = "\t%s\t: (%ld, %ld)\n";
01023 #endif /* __x86_64__ */
01024     printf( FMT, tag, size.cx, size.cy );
01025   }
01026 
01027   inline void edit_pointl ( const char* tag, const POINTL& point )
01028   {
01029 #if defined(__LP64__)
01030     const char* FMT = "\t%s\t: (%d, %d)\n";
01031 #else
01032     const char* FMT = "\t%s\t: (%ld, %ld)\n";
01033 #endif /* __x86_64__ */
01034     printf( FMT, tag, point.x, point.y );
01035   }
01036 
01037   inline void edit_pointlarray ( const char* tag, const DWORD cptl,
01038                                   const POINTL* points )
01039   {
01040 #if defined(__LP64__)
01041     const char* FMT0 = "\tcptl%s\t: %d\n";
01042     const char* FMT1 = "%d, %d\n";
01043     const char* FMT2 = "\t\t%s  %d, %d\n";
01044 #else
01045     const char* FMT0 = "\tcptl%s\t: %ld\n";
01046     const char* FMT1 = "%ld, %ld\n";
01047     const char* FMT2 = "\t\t%s  %ld, %ld\n";
01048 #endif /* __x86_64__ */
01049     printf( FMT0, tag, cptl );
01050     printf( "\taptl%s\t: ", tag );
01051     if ( cptl > 0 )
01052       printf( FMT1, points[0].x, points[0].y );
01053     else
01054       puts( "" );
01055     for ( DWORD i = 1; i < cptl; i++ )
01056       printf( FMT2, tag, points[i].x, points[i].y );
01057   }
01058 
01059   inline void edit_point16array ( const char* tag, const unsigned int cpts,
01060                                   const POINT16* points )
01061   {
01062     printf( "\tcpts%s\t: %d\n", tag, cpts );
01063     printf( "\tapts%s\t: ", tag );
01064     if ( cpts > 0 )
01065       printf( "%d, %d\n", points[0].x, points[0].y );
01066     else
01067       puts( "" );
01068     for ( unsigned int i = 1; i < cpts; i++ )
01069       printf( "\t\t%s  %d, %d\n", tag, points[i].x, points[i].y );
01070   }
01071 
01072   inline void edit_pen_style ( const char* tag, DWORD style )
01073   {
01074     printf( "\t%s\t: ", tag );
01075     switch ( style & PS_STYLE_MASK ) {
01076     case PS_SOLID: printf( "PS_SOLID" ); break;
01077     case PS_DASH: printf( "PS_DASH" ); break;
01078     case PS_DOT: printf( "PS_DOT" ); break;
01079     case PS_DASHDOT: printf( "PS_DASHDOT" ); break;
01080     case PS_DASHDOTDOT: printf( "PS_DASHDOTDOT" ); break;
01081     case PS_NULL: printf( "PS_NULL" ); break;
01082     case PS_INSIDEFRAME: printf( "PS_INSIDEFRAME" ); break;
01083     case PS_USERSTYLE: printf( "PS_USERSTYLE" ); break;
01084     case PS_ALTERNATE: printf( "PS_ALTERNATE" ); break;
01085     }
01086     switch ( style & PS_ENDCAP_MASK ) {
01087     case PS_ENDCAP_ROUND: printf( " | PS_ENDCAP_ROUND" ); break;
01088     case PS_ENDCAP_SQUARE: printf( " | PS_ENDCAP_SQUARE" ); break;
01089     case PS_ENDCAP_FLAT: printf( " | PS_ENDCAP_FLAT" ); break;
01090     }
01091     switch ( style & PS_JOIN_MASK ) {
01092     case PS_JOIN_ROUND: printf( " | PS_JOIN_ROUND" ); break;
01093     case PS_JOIN_BEVEL: printf( " | PS_JOIN_BEVEL" ); break;
01094     case PS_JOIN_MITER: printf( " | PS_JOIN_MITER" ); break;
01095     }
01096     switch ( style & PS_TYPE_MASK ) {
01097     case PS_COSMETIC: printf( " | PS_COSMETIC" ); break;
01098     case PS_GEOMETRIC: printf( " | PS_GEOMETRIC" ); break;
01099     }
01100     printf( "\n" );
01101   }
01102 
01103   inline void edit_brush_style ( const char* tag, DWORD style )
01104   {
01105 #if defined(__LP64__)
01106     const char* FMT = "unknown(%d)";
01107 #else
01108     const char* FMT = "unknown(%ld)";
01109 #endif /* __x86_64__ */
01110     printf( "\t%s\t: ", tag );
01111     switch ( style ) {
01112     case BS_SOLID: printf( "BS_SOLID" ); break;
01113     case BS_NULL: printf( "BS_NULL" ); break;
01114     case BS_HATCHED: printf( "BS_HATCHED" ); break;
01115     case BS_PATTERN: printf( "BS_PATTERN" ); break;
01116     case BS_INDEXED: printf( "BS_INDEXED" ); break;
01117     case BS_DIBPATTERN: printf( "BS_DIBPATTERN" ); break;
01118     case BS_DIBPATTERNPT: printf( "BS_DIBPATTERNPT" ); break;
01119     case BS_PATTERN8X8: printf( "BS_PATTERN8X8" ); break;
01120     case BS_DIBPATTERN8X8: printf( "BS_DIBPATTERN8X8" ); break;
01121     case BS_MONOPATTERN: printf( "BS_DIBPATTERN8X8" ); break;
01122     default: printf( FMT, style );
01123     }
01124     printf( "\n" );
01125   }
01126 
01127   inline void edit_brush_hatch ( const char* tag, DWORD hatch )
01128   {
01129 #if defined(__LP64__)
01130     const char* FMT = "unknown(%d)";
01131 #else
01132     const char* FMT = "unknown(%ld)";
01133 #endif /* __x86_64__ */
01134     printf( "\t%s\t: ", tag );
01135     switch ( hatch ) {
01136     case HS_HORIZONTAL: printf( "HS_HORIZONTAL" ); break;
01137     case HS_VERTICAL: printf( "HS_VERTICAL" ); break;
01138     case HS_FDIAGONAL: printf( "HS_FDIAGONAL" ); break;
01139     case HS_BDIAGONAL: printf( "HS_BDIAGONAL" ); break;
01140     case HS_CROSS: printf( "HS_CROSS" ); break;
01141     case HS_DIAGCROSS: printf( "HS_DIAGCROSS" ); break;
01142     default: printf( FMT, hatch );
01143     }
01144     printf( "\n" );
01145   }
01146 #endif
01147 
01154   enum OBJECTTYPE { O_METAFILEDEVICECONTEXT     = OBJ_METADC,
01155                     O_FONT                      = OBJ_FONT,
01156                     O_PEN                       = OBJ_PEN,
01157                     O_EXTPEN                    = OBJ_EXTPEN,
01158                     O_BRUSH                     = OBJ_BRUSH,
01159                     O_PALETTE                   = OBJ_PAL };
01160 #if 0
01161 
01164   static char* typStr ( OBJECTTYPE type )
01165   {
01166     switch (type) {
01167     case O_METAFILEDEVICECONTEXT:
01168       return "metafile device context";
01169     case O_FONT:
01170       return "font";
01171     case O_PEN:
01172       return "pen";
01173     case O_EXTPEN:
01174       return "extended pen";
01175     case O_BRUSH:
01176       return "brush";
01177     case O_PALETTE:
01178       return "palette";
01179     }
01180     return "unknown object";
01181   }
01182 #endif
01183 
01184 
01189   class OBJECT {
01190   public:
01191     HGDIOBJ handle;             
01192 
01193     virtual ~OBJECT () {}
01198     OBJECT ( void ) : handle( 0 ) {}
01202     virtual OBJECTTYPE getType ( void ) const = 0;
01203   };
01204 
01206 
01211   class GRAPHICSOBJECT : public OBJECT {
01212   public:
01214     virtual ~GRAPHICSOBJECT () {}
01219     std::map< HDC, HGDIOBJ > contexts;
01225     virtual METARECORD* newEMR ( HDC dc, HGDIOBJ handle ) = 0;
01226   };
01227 
01228   typedef METARECORD*(*METARECORDCTOR)(DATASTREAM&);
01229 
01230   class GLOBALOBJECTS {
01234     std::vector<OBJECT*> objects;
01235 
01242     std::map< DWORD, METARECORDCTOR > new_records;
01243 
01244   public:
01245     GLOBALOBJECTS ( void );
01246     ~GLOBALOBJECTS ( void );
01247     HGDIOBJ add ( OBJECT* object );
01248     OBJECT* find ( const HGDIOBJ handle );
01249     void remove ( const OBJECT* object );
01250 
01251     std::vector<EMF::OBJECT*>::const_iterator begin ( void ) const
01252     { return objects.begin(); }
01253     std::vector<EMF::OBJECT*>::const_iterator end ( void ) const
01254     { return objects.end(); }
01255 
01256     METARECORDCTOR newRecord ( DWORD iType ) const;
01257 
01258     static EMF::METARECORD* new_eof ( DATASTREAM& ds );
01259     static EMF::METARECORD* new_setviewportorgex ( DATASTREAM& ds );
01260     static EMF::METARECORD* new_setwindoworgex ( DATASTREAM& ds );
01261     static EMF::METARECORD* new_setviewportextex ( DATASTREAM& ds );
01262     static EMF::METARECORD* new_setwindowextex ( DATASTREAM& ds );
01263     static EMF::METARECORD* new_scaleviewportextex ( DATASTREAM& ds );
01264     static EMF::METARECORD* new_scalewindowextex ( DATASTREAM& ds );
01265     static EMF::METARECORD* new_modifyworldtransform ( DATASTREAM& ds );
01266     static EMF::METARECORD* new_setworldtransform ( DATASTREAM& ds );
01267     static EMF::METARECORD* new_settextalign ( DATASTREAM& ds );
01268     static EMF::METARECORD* new_settextcolor ( DATASTREAM& ds );
01269     static EMF::METARECORD* new_setbkcolor ( DATASTREAM& ds );
01270     static EMF::METARECORD* new_setbkmode ( DATASTREAM& ds );
01271     static EMF::METARECORD* new_setpolyfillmode ( DATASTREAM& ds );
01272     static EMF::METARECORD* new_setmapmode ( DATASTREAM& ds );
01273     static EMF::METARECORD* new_selectobject ( DATASTREAM& ds );
01274     static EMF::METARECORD* new_deleteobject ( DATASTREAM& ds );
01275     static EMF::METARECORD* new_movetoex ( DATASTREAM& ds );
01276     static EMF::METARECORD* new_lineto ( DATASTREAM& ds );
01277     static EMF::METARECORD* new_arc ( DATASTREAM& ds );
01278     static EMF::METARECORD* new_arcto ( DATASTREAM& ds );
01279     static EMF::METARECORD* new_rectangle ( DATASTREAM& ds );
01280     static EMF::METARECORD* new_ellipse ( DATASTREAM& ds );
01281     static EMF::METARECORD* new_polyline ( DATASTREAM& ds );
01282     static EMF::METARECORD* new_polyline16 ( DATASTREAM& ds );
01283     static EMF::METARECORD* new_polygon ( DATASTREAM& ds );
01284     static EMF::METARECORD* new_polygon16 ( DATASTREAM& ds );
01285     static EMF::METARECORD* new_polypolygon ( DATASTREAM& ds );
01286     static EMF::METARECORD* new_polypolygon16 ( DATASTREAM& ds );
01287     static EMF::METARECORD* new_polybezier ( DATASTREAM& ds );
01288     static EMF::METARECORD* new_polybezier16 ( DATASTREAM& ds );
01289     static EMF::METARECORD* new_polybezierto ( DATASTREAM& ds );
01290     static EMF::METARECORD* new_polybezierto16 ( DATASTREAM& ds );
01291     static EMF::METARECORD* new_polylineto ( DATASTREAM& ds );
01292     static EMF::METARECORD* new_polylineto16 ( DATASTREAM& ds );
01293     static EMF::METARECORD* new_exttextouta ( DATASTREAM& ds );
01294     static EMF::METARECORD* new_setpixelv ( DATASTREAM& ds );
01295     static EMF::METARECORD* new_createpen ( DATASTREAM& ds );
01296     static EMF::METARECORD* new_extcreatepen ( DATASTREAM& ds );
01297     static EMF::METARECORD* new_createbrushindirect ( DATASTREAM& ds );
01298     static EMF::METARECORD* new_extcreatefontindirectw ( DATASTREAM& ds );
01299     static EMF::METARECORD* new_fillpath ( DATASTREAM& ds );
01300     static EMF::METARECORD* new_strokepath ( DATASTREAM& ds );
01301     static EMF::METARECORD* new_strokeandfillpath ( DATASTREAM& ds );
01302     static EMF::METARECORD* new_beginpath ( DATASTREAM& ds );
01303     static EMF::METARECORD* new_endpath ( DATASTREAM& ds );
01304     static EMF::METARECORD* new_closefigure ( DATASTREAM& ds );
01305     static EMF::METARECORD* new_savedc ( DATASTREAM& ds );
01306     static EMF::METARECORD* new_restoredc ( DATASTREAM& ds );
01307     static EMF::METARECORD* new_setmetargn ( DATASTREAM& ds );
01308     static EMF::METARECORD* new_setmiterlimit ( DATASTREAM& ds );
01309   };
01310 
01311   extern GLOBALOBJECTS globalObjects;
01312 
01314 
01320   class ENHMETAHEADER : public METARECORD, public ::ENHMETAHEADER {
01321 
01322     LPWSTR description_w;
01323     int description_size;
01324 
01325   public:
01332     ENHMETAHEADER ( LPCWSTR description = 0 )
01333       : description_w( 0 ), description_size( 0 )
01334     {
01335       iType = EMR_HEADER;
01336       nSize = sizeof( ::ENHMETAHEADER );
01337 
01338       // Compute the bounds
01339       RECTL default_bounds = { 0, 0, 0, 0 };
01340       rclBounds = default_bounds;
01341       RECTL default_frame = { 0, 0, 0, 0 };
01342       rclFrame = default_frame;
01343       dSignature = ENHMETA_SIGNATURE;
01344       nVersion = 0x10000;
01345       nBytes = nSize;
01346       nRecords = 1;
01347       nHandles = 0;
01348       sReserved = 0;
01349       nDescription = 0;
01350       offDescription = 0;
01351       nPalEntries = 0;
01352       szlDevice.cx = XMAX_PIXELS;
01353       szlDevice.cy = YMAX_PIXELS;
01354       szlMillimeters.cx = XMAX_MM;
01355       szlMillimeters.cy = YMAX_MM;
01356       //
01357       cbPixelFormat = 0;
01358       offPixelFormat = 0;
01359       bOpenGL = FALSE;
01360       //
01361 #if 1
01362       szlMicrometers.cx = 1000 * szlMillimeters.cx;
01363       szlMicrometers.cy = 1000 * szlMillimeters.cy;
01364 #endif
01365       if ( description ) {
01366         // Count the number of characters in the description
01367         int description_count = 0, nulls = 0;
01368         LPCWSTR description_p = description;
01369         while ( nulls < 3 ) {
01370           description_count++;
01371           if ( (*description_p++) == 0 ) nulls++;
01372         }
01373 
01374         // Make sure that the TOTAL record length will be a multiple of 4
01375 
01376         int record_size = ROUND_TO_LONG( sizeof( ::ENHMETAHEADER ) +
01377                                          sizeof( WCHAR ) * description_count );
01378         description_size =
01379           (record_size - sizeof( ::ENHMETAHEADER )) / sizeof( WCHAR );
01380 
01381         description_w = new WCHAR[ description_size ];
01382 
01383         memset( description_w, 0, sizeof(WCHAR) * description_size );
01384 
01385         for ( int i=0; i<description_count; i++ )
01386           description_w[i] = *description++;
01387 
01388         nSize = nBytes = record_size;
01389         nDescription = description_count;
01390         offDescription = sizeof( ::ENHMETAHEADER );
01391       }
01392     }
01393     
01397     ~ENHMETAHEADER ( )
01398     {
01399       if ( description_w ) delete[] description_w;
01400     }
01405     bool serialize ( DATASTREAM ds )
01406     {
01407       ds << iType << nSize
01408          << rclBounds << rclFrame
01409          << dSignature << nVersion << nBytes << nRecords << nHandles << sReserved
01410          << nDescription << offDescription << nPalEntries
01411          << szlDevice << szlMillimeters
01412          << cbPixelFormat << offPixelFormat << bOpenGL
01413 #if 1
01414          << szlMicrometers
01415 #endif
01416          << WCHARSTR( description_w, description_size );
01417       return true;
01418     }
01422     bool unserialize ( DATASTREAM ds )
01423     {
01424       ds >> iType >> nSize
01425          >> rclBounds >> rclFrame
01426          >> dSignature >> nVersion >> nBytes >> nRecords >> nHandles >> sReserved
01427          >> nDescription >> offDescription >> nPalEntries
01428          >> szlDevice >> szlMillimeters;
01429 
01430       // Some elements of the metafile header were added at later dates
01431 
01432 #define OffsetOf( a, b ) ((unsigned int)(((char*)&(((::ENHMETAHEADER*)a)->b)) - \
01433 (char*)((::ENHMETAHEADER*)a)))
01434 #if 1
01435       if ( OffsetOf( this, szlMicrometers ) <= offDescription )
01436         ds >> cbPixelFormat >> offPixelFormat >> bOpenGL;
01437 #else
01438       if ( sizeof(::ENHMETAHEADER) <= offDescription )
01439         ds >> cbPixelFormat >> offPixelFormat >> bOpenGL;
01440 #endif
01441 #undef OffsetOf
01442 #if 1
01443       if ( sizeof(::ENHMETAHEADER) <= offDescription )
01444         ds >> szlMicrometers;
01445 #endif
01446       // Should now probably check that the offset is correct...
01447 
01448       description_size = ( nSize - offDescription ) / sizeof(WCHAR);
01449       description_w = new WCHAR[ description_size ];
01450 
01451       WCHARSTR description( description_w, description_size );
01452 
01453       ds >> description;
01454 
01455       return true;
01456     }
01460     int size ( void ) const { return nSize; }
01466     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC /*dc*/ ) const
01467     {
01468       // Actually handled by the destination device context.
01469     }
01470 #ifdef ENABLE_EDITING
01471 
01474     void edit ( void ) const
01475     {
01476 #if defined(__LP64__)
01477       const char* FMT0 = "\tiType\t\t\t: %d\n";
01478       const char* FMT1 = "\tnSize\t\t\t: %d\n";
01479       const char* FMT2 = "\tnBytes\t\t\t: %d\n";
01480       const char* FMT3 = "\tnRecords\t\t: %d\n";
01481       const char* FMT4 = "\tnDescription\t\t: %d\n";
01482       const char* FMT5 = "\toffDescription\t\t: %d\n";
01483       const char* FMT6 = "\tnPalEntries\t\t: %d\n";
01484       const char* FMT7 = "\tcbPixelFormat\t\t: %d\n";
01485       const char* FMT8 = "\toffPixelFormat\t\t: %d\n";
01486       const char* FMT9 = "\tbOpenGL\t\t\t: %d\n";
01487 #else
01488       const char* FMT0 = "\tiType\t\t\t: %ld\n";
01489       const char* FMT1 = "\tnSize\t\t\t: %ld\n";
01490       const char* FMT2 = "\tnBytes\t\t\t: %ld\n";
01491       const char* FMT3 = "\tnRecords\t\t: %ld\n";
01492       const char* FMT4 = "\tnDescription\t\t: %ld\n";
01493       const char* FMT5 = "\toffDescription\t\t: %ld\n";
01494       const char* FMT6 = "\tnPalEntries\t\t: %ld\n";
01495       const char* FMT7 = "\tcbPixelFormat\t\t: %ld\n";
01496       const char* FMT8 = "\toffPixelFormat\t\t: %ld\n";
01497       const char* FMT9 = "\tbOpenGL\t\t\t: %ld\n";
01498 #endif
01499       printf( "*HEADER*\n" );
01500       printf( FMT0, iType );
01501       printf( FMT1, nSize );
01502       edit_rectl( "rclBounds\t", rclBounds );
01503       edit_rectl( "rclFrame\t", rclFrame );
01504       printf( "\tdSignature\t\t: %.4s\n", (const char*)&dSignature );
01505       printf( "\tnVersion\t\t: 0x%x\n", (unsigned int)nVersion );
01506       printf( FMT2, nBytes );
01507       printf( FMT3, nRecords );
01508       printf( "\tnHandles\t\t: %d\n", nHandles );
01509       printf( FMT4, nDescription );
01510       printf( FMT5, offDescription );
01511       printf( FMT6, nPalEntries );
01512       edit_sizel( "szlDevice\t", szlDevice );
01513       edit_sizel( "szlMillimeters\t", szlMillimeters );
01514 
01515       /* Make a crude guess as to the age of this file */
01516 #define OffsetOf( a, b ) ((unsigned int)(((const char*)&(((const ::ENHMETAHEADER*)a)->b)) - \
01517 (const char*)((const ::ENHMETAHEADER*)a)))
01518 
01519       if ( OffsetOf( this, cbPixelFormat ) <= offDescription ) {
01520         printf( FMT7, cbPixelFormat );
01521         printf( FMT8, offPixelFormat );
01522         printf( FMT9, bOpenGL );
01523 #if 1
01524         if ( sizeof(::ENHMETAHEADER) <= offDescription ) {
01525           edit_sizel( "szlMicrometers\t", szlMicrometers );
01526         }
01527 #endif
01528       }
01529 
01530 #undef OffsetOf
01531 
01532       if ( nDescription != 0 ) {
01533 
01534         wchar_t last_w = 0;
01535         WCHAR* description = description_w;
01536 
01537         printf( "\tDescription:" );
01538 
01539         for ( DWORD i = 0; i < nDescription; i++ ) {
01540 
01541           wchar_t w = *description++; /* This is not true, really. UNICODE is not
01542                                        * glibc's wide character representation */
01543 
01544           if ( w != 0 ) {
01545             if ( last_w == 0 ) printf( "\n\t\t" );
01546             putchar( w );
01547           }
01548           
01549           last_w = w;
01550         }
01551         printf( "\n" );
01552       }
01553     }
01554 #endif /* ENABLE_EDITING */
01555   };
01556 
01558 
01563   class EMREOF : public METARECORD, ::EMREOF {
01564   public:
01568     EMREOF ( void )
01569     {
01570       emr.iType = EMR_EOF;
01571       emr.nSize = sizeof( ::EMREOF );
01572       nPalEntries = 0;
01573       offPalEntries = 0;
01574       nSizeLast = 0;
01575     }
01576 
01581     EMREOF ( DATASTREAM& ds )
01582     {
01583       ds >> emr >> nPalEntries >> offPalEntries >> nSizeLast;
01584     }
01585 
01589     bool serialize ( DATASTREAM ds )
01590     {
01591       ds << emr << nPalEntries << offPalEntries << nSizeLast;
01592       return true;
01593     }
01597     int size ( void ) const { return emr.nSize; }
01603     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC /*dc*/ ) const
01604     {
01605       // Actually handled by the destination device context.
01606     }
01607 #ifdef ENABLE_EDITING
01608 
01611     void edit ( void ) const
01612     {
01613       printf( "*EOF*\n" );
01614     }
01615 #endif /* ENABLE_EDITING */
01616   };
01617 
01619 
01624   class EMRSETVIEWPORTORGEX : public METARECORD, ::EMRSETVIEWPORTORGEX {
01625   public:
01630     EMRSETVIEWPORTORGEX ( INT x, INT y )
01631     {
01632       emr.iType = EMR_SETVIEWPORTORGEX;
01633       emr.nSize = sizeof( ::EMRSETVIEWPORTORGEX );
01634       ptlOrigin.x = x;
01635       ptlOrigin.y = y;
01636     }
01641     EMRSETVIEWPORTORGEX ( DATASTREAM& ds )
01642     {
01643       ds >> emr >> ptlOrigin;
01644     }
01648     bool serialize ( DATASTREAM ds )
01649     {
01650       ds << emr << ptlOrigin;
01651       return true;
01652     }
01656     int size ( void ) const { return emr.nSize; }
01662     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01663     {
01664       SetViewportOrgEx( dc, ptlOrigin.x, ptlOrigin.y, 0 );
01665     }
01666 #ifdef ENABLE_EDITING
01667 
01670     void edit ( void ) const
01671     {
01672       printf( "*SETVIEWPORTORGEX*\n" );
01673       edit_pointl( "ptlOrigin", ptlOrigin );
01674     }
01675 #endif /* ENABLE_EDITING */
01676   };
01677 
01679 
01686   class EMRSETWINDOWORGEX : public METARECORD, ::EMRSETWINDOWORGEX {
01687   public:
01692     EMRSETWINDOWORGEX ( INT x, INT y )
01693     {
01694       emr.iType = EMR_SETWINDOWORGEX;
01695       emr.nSize = sizeof( ::EMRSETWINDOWORGEX );
01696       ptlOrigin.x = x;
01697       ptlOrigin.y = y;
01698     }
01703     EMRSETWINDOWORGEX ( DATASTREAM& ds )
01704     {
01705       ds >> emr >> ptlOrigin;
01706     }
01710     bool serialize ( DATASTREAM ds )
01711     {
01712       ds << emr << ptlOrigin;
01713       return true;
01714     }
01718     int size ( void ) const { return emr.nSize; }
01724     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01725     {
01726       SetWindowOrgEx( dc, ptlOrigin.x, ptlOrigin.y, 0 );
01727     }
01728 #ifdef ENABLE_EDITING
01729 
01732     void edit ( void ) const
01733     {
01734       printf( "*SETWINDOWORGEX*\n" );
01735       edit_pointl( "ptlOrigin", ptlOrigin );
01736     }
01737 #endif /* ENABLE_EDITING */
01738   };
01739 
01741 
01746   class EMRSETVIEWPORTEXTEX : public METARECORD, ::EMRSETVIEWPORTEXTEX {
01747   public:
01752     EMRSETVIEWPORTEXTEX ( INT cx, INT cy )
01753     {
01754       emr.iType = EMR_SETVIEWPORTEXTEX;
01755       emr.nSize = sizeof( ::EMRSETVIEWPORTEXTEX );
01756       szlExtent.cx = cx;
01757       szlExtent.cy = cy;
01758     }
01763     EMRSETVIEWPORTEXTEX ( DATASTREAM& ds )
01764     {
01765       ds >> emr >> szlExtent;
01766     }
01770     bool serialize ( DATASTREAM ds )
01771     {
01772       ds << emr << szlExtent;
01773       return true;
01774     }
01778     int size ( void ) const { return emr.nSize; }
01784     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01785     {
01786       SetViewportExtEx( dc, szlExtent.cx, szlExtent.cy, 0 );
01787     }
01788 #ifdef ENABLE_EDITING
01789 
01792     void edit ( void ) const
01793     {
01794       printf( "*SETVIEWPORTEXTEX*\n" );
01795       edit_sizel( "szlExtent", szlExtent );
01796     }
01797 #endif /* ENABLE_EDITING */
01798   };
01799 
01801 
01806   class EMRSCALEVIEWPORTEXTEX : public METARECORD, ::EMRSCALEVIEWPORTEXTEX {
01807   public:
01814     EMRSCALEVIEWPORTEXTEX ( LONG x_num, LONG x_den, LONG y_num, LONG y_den )
01815     {
01816       emr.iType = EMR_SCALEVIEWPORTEXTEX;
01817       emr.nSize = sizeof( ::EMRSCALEVIEWPORTEXTEX );
01818       xNum = x_num;
01819       xDenom = x_den;
01820       yNum = y_num;
01821       yDenom = y_den;
01822     }
01827     EMRSCALEVIEWPORTEXTEX ( DATASTREAM& ds )
01828     {
01829       ds >> emr >> xNum >> xDenom >> yNum >> yDenom;
01830     }
01834     bool serialize ( DATASTREAM ds )
01835     {
01836       ds << emr << xNum << xDenom << yNum << yDenom;
01837       return true;
01838     }
01842     int size ( void ) const { return emr.nSize; }
01848     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01849     {
01850       ScaleViewportExtEx( dc, xNum, xDenom, yNum, yDenom, 0 );
01851     }
01852 #ifdef ENABLE_EDITING
01853 
01856     void edit ( void ) const
01857     {
01858 #if defined(__LP64__)
01859       const char* FMT0 = "\txNum\t: %d\n";
01860       const char* FMT1 = "\txDenom\t: %d\n";
01861       const char* FMT2 = "\tyNum\t: %d\n";
01862       const char* FMT3 = "\tyDenom\t: %d\n";
01863 #else
01864       const char* FMT0 = "\txNum\t: %ld\n";
01865       const char* FMT1 = "\txDenom\t: %ld\n";
01866       const char* FMT2 = "\tyNum\t: %ld\n";
01867       const char* FMT3 = "\tyDenom\t: %ld\n";
01868 #endif
01869       printf( "*SCALEVIEWPORTEXTEX*\n" );
01870       printf( FMT0, xNum );
01871       printf( FMT1, xDenom );
01872       printf( FMT2, yNum );
01873       printf( FMT3, yDenom );
01874     }
01875 #endif /* ENABLE_EDITING */
01876   };
01877 
01879 
01884   class EMRSETWINDOWEXTEX : public METARECORD, ::EMRSETWINDOWEXTEX {
01885   public:
01890     EMRSETWINDOWEXTEX ( INT cx, INT cy )
01891     {
01892       emr.iType = EMR_SETWINDOWEXTEX;
01893       emr.nSize = sizeof( ::EMRSETWINDOWEXTEX );
01894       szlExtent.cx = cx;
01895       szlExtent.cy = cy;
01896     }
01901     EMRSETWINDOWEXTEX ( DATASTREAM& ds )
01902     {
01903       ds >> emr >> szlExtent;
01904     }
01908     bool serialize ( DATASTREAM ds )
01909     {
01910       ds << emr << szlExtent;
01911       return true;
01912     }
01916     int size ( void ) const { return emr.nSize; }
01922     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01923     {
01924       SetWindowExtEx( dc, szlExtent.cx, szlExtent.cy, 0 );
01925     }
01926 #ifdef ENABLE_EDITING
01927 
01930     void edit ( void ) const
01931     {
01932       printf( "*SETWINDOWEXTEX*\n" );
01933       edit_sizel( "szlExtent", szlExtent );
01934     }
01935 #endif /* ENABLE_EDITING */
01936   };
01937 
01939 
01944   class EMRSCALEWINDOWEXTEX : public METARECORD, ::EMRSCALEWINDOWEXTEX {
01945   public:
01952     EMRSCALEWINDOWEXTEX ( LONG x_num, LONG x_den, LONG y_num, LONG y_den )
01953     {
01954       emr.iType = EMR_SCALEWINDOWEXTEX;
01955       emr.nSize = sizeof( ::EMRSCALEWINDOWEXTEX );
01956       xNum = x_num;
01957       xDenom = x_den;
01958       yNum = y_num;
01959       yDenom = y_den;
01960     }
01965     EMRSCALEWINDOWEXTEX ( DATASTREAM& ds )
01966     {
01967       ds >> emr >> xNum >> xDenom >> yNum >> yDenom;
01968     }
01972     bool serialize ( DATASTREAM ds )
01973     {
01974       ds << emr << xNum << xDenom << yNum << yDenom;
01975       return true;
01976     }
01980     int size ( void ) const { return emr.nSize; }
01986     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01987     {
01988       ScaleWindowExtEx( dc, xNum, xDenom, yNum, yDenom, 0 );
01989     }
01990 #ifdef ENABLE_EDITING
01991 
01994     void edit ( void ) const
01995     {
01996 #if defined(__LP64__)
01997       const char* FMT0 = "\txNum\t: %d\n";
01998       const char* FMT1 = "\txDenom\t: %d\n";
01999       const char* FMT2 = "\tyNum\t: %d\n";
02000       const char* FMT3 = "\tyDenom\t: %d\n";
02001 #else
02002       const char* FMT0 = "\txNum\t: %ld\n";
02003       const char* FMT1 = "\txDenom\t: %ld\n";
02004       const char* FMT2 = "\tyNum\t: %ld\n";
02005       const char* FMT3 = "\tyDenom\t: %ld\n";
02006 #endif
02007       printf( "*SCALEWINDOWEXTEX*\n" );
02008       printf( FMT0, xNum );
02009       printf( FMT1, xDenom );
02010       printf( FMT2, yNum );
02011       printf( FMT3, yDenom );
02012     }
02013 #endif /* ENABLE_EDITING */
02014   };
02015 
02017 
02023   class EMRMODIFYWORLDTRANSFORM : public METARECORD, ::EMRMODIFYWORLDTRANSFORM {
02024   public:
02030     EMRMODIFYWORLDTRANSFORM ( const XFORM* transform, DWORD mode )
02031     {
02032       emr.iType = EMR_MODIFYWORLDTRANSFORM;
02033       emr.nSize = sizeof( ::EMRMODIFYWORLDTRANSFORM );
02034       xform = *transform;
02035       iMode = mode;
02036     }
02041     EMRMODIFYWORLDTRANSFORM ( DATASTREAM& ds )
02042     {
02043       ds >> emr >> xform >> iMode;
02044     }
02048     bool serialize ( DATASTREAM ds )
02049     {
02050       ds << emr << xform << iMode;
02051       return true;
02052     }
02056     int size ( void ) const { return emr.nSize; }
02062     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02063     {
02064       ModifyWorldTransform( dc, &xform, iMode );
02065     }
02066 #ifdef ENABLE_EDITING
02067 
02070     void edit ( void ) const
02071     {
02072 #if defined(__LP64__)
02073     const char* FMT = "unknown(%d)\n";
02074 #else
02075     const char* FMT = "unknown(%ld)\n";
02076 #endif /* __x86_64__ */
02077       printf( "*MODIFYWORLDTRANSFORM*\n" );
02078       edit_xform( "xform", xform );
02079       printf( "\tiMode\t\t: " );
02080       switch ( iMode ) {
02081       case MWT_IDENTITY: printf( "MWT_IDENTITY\n" ); break;
02082       case MWT_LEFTMULTIPLY: printf( "MWT_LEFTMULTIPLY\n" ); break;
02083       case MWT_RIGHTMULTIPLY: printf( "MWT_RIGHTMULTIPLY\n" ); break;
02084       default: printf( FMT, iMode );
02085       }
02086     }
02087 #endif /* ENABLE_EDITING */
02088   };
02089 
02091 
02097   class EMRSETWORLDTRANSFORM : public METARECORD, ::EMRSETWORLDTRANSFORM {
02098   public:
02102     EMRSETWORLDTRANSFORM ( const XFORM* transform )
02103     {
02104       emr.iType = EMR_SETWORLDTRANSFORM;
02105       emr.nSize = sizeof( ::EMRSETWORLDTRANSFORM );
02106       xform = *transform;
02107     }
02112     EMRSETWORLDTRANSFORM ( DATASTREAM& ds )
02113     {
02114       ds >> emr >> xform;
02115     }
02119     bool serialize ( DATASTREAM ds )
02120     {
02121       ds << emr << xform;
02122       return true;
02123     }
02127     int size ( void ) const { return emr.nSize; }
02133     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02134     {
02135       SetWorldTransform( dc, &xform );
02136     }
02137 #ifdef ENABLE_EDITING
02138 
02141     void edit ( void ) const
02142     {
02143       printf( "*SETWORLDTRANSFORM*\n" );
02144       edit_xform( "xform", xform );
02145     }
02146 #endif /* ENABLE_EDITING */
02147   };
02148 
02150 
02153   class EMRSETTEXTALIGN : public METARECORD, ::EMRSETTEXTALIGN {
02154   public:
02158     EMRSETTEXTALIGN ( UINT mode )
02159     {
02160       emr.iType = EMR_SETTEXTALIGN;
02161       emr.nSize = sizeof( ::EMRSETTEXTALIGN );
02162       iMode = mode;
02163     }
02168     EMRSETTEXTALIGN ( DATASTREAM& ds )
02169     {
02170       ds >> emr >> iMode;
02171     }
02175     bool serialize ( DATASTREAM ds )
02176     {
02177       ds << emr << iMode;
02178       return true;
02179     }
02183     int size ( void ) const { return emr.nSize; }
02189     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02190     {
02191       SetTextAlign( dc, iMode );
02192     }
02193 #ifdef ENABLE_EDITING
02194 
02197     void edit ( void ) const
02198     {
02199 #if defined(__LP64__)
02200     const char* FMT = "| unknown bits(0x%x)";
02201 #else
02202     const char* FMT = "| unknown bits(0x%lx)";
02203 #endif /* __x86_64__ */
02204       unsigned int known_bits = TA_BASELINE+TA_CENTER+TA_UPDATECP+TA_RTLREADING;
02205       unsigned int unknown_bits = ~known_bits;
02206 
02207       printf( "*SETTEXTALIGN*\n" );
02208       printf( "\tiMode\t: " );
02209       if ( iMode & TA_UPDATECP )
02210         printf( "TA_UPDATECP" );
02211       else
02212         printf( "TA_NOUPDATECP" );
02213       if ( iMode & TA_CENTER )
02214         printf( " | TA_CENTER" );
02215       else if ( iMode & TA_RIGHT )
02216         printf( " | TA_RIGHT" );
02217       else
02218         printf( " | TA_LEFT" );
02219       if ( iMode & TA_BASELINE )
02220         printf( " | TA_BASELINE" );
02221       else if ( iMode & TA_BOTTOM )
02222         printf( " | TA_BOTTOM" );
02223       else
02224         printf( " | TA_TOP" );
02225       if ( iMode & TA_RTLREADING )
02226         printf( " | TA_RTLREADING" );
02227       if ( iMode & unknown_bits )
02228         printf( FMT, iMode & unknown_bits );
02229       printf( "\n" );
02230     }
02231 #endif /* ENABLE_EDITING */
02232   };
02233 
02235 
02238   class EMRSETTEXTCOLOR : public METARECORD, ::EMRSETTEXTCOLOR {
02239   public:
02243     EMRSETTEXTCOLOR ( COLORREF color )
02244     {
02245       emr.iType = EMR_SETTEXTCOLOR;
02246       emr.nSize = sizeof( ::EMRSETTEXTCOLOR );
02247       crColor = color;
02248     }
02253     EMRSETTEXTCOLOR ( DATASTREAM& ds )
02254     {
02255       ds >> emr >> crColor;
02256     }
02260     bool serialize ( DATASTREAM ds )
02261     {
02262       ds << emr << crColor;
02263       return true;
02264     }
02268     int size ( void ) const { return emr.nSize; }
02274     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02275     {
02276       SetTextColor( dc, crColor );
02277     }
02278 #ifdef ENABLE_EDITING
02279 
02282     void edit ( void ) const
02283     {
02284       printf( "*SETTEXTCOLOR*\n" );
02285       edit_color( "crColor", crColor );
02286     }
02287 #endif /* ENABLE_EDITING */
02288   };
02289 
02291 
02294   class EMRSETBKCOLOR : public METARECORD, ::EMRSETBKCOLOR {
02295   public:
02299     EMRSETBKCOLOR ( COLORREF color )
02300     {
02301       emr.iType = EMR_SETBKCOLOR;
02302       emr.nSize = sizeof( ::EMRSETBKCOLOR );
02303       crColor = color;
02304     }
02309     EMRSETBKCOLOR ( DATASTREAM& ds )
02310     {
02311       ds >> emr >> crColor;
02312     }
02316     bool serialize ( DATASTREAM ds )
02317     {
02318       ds << emr << crColor;
02319       return true;
02320     }
02324     int size ( void ) const { return emr.nSize; }
02330     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02331     {
02332       SetBkColor( dc, crColor );
02333     }
02334 #ifdef ENABLE_EDITING
02335 
02338     void edit ( void ) const
02339     {
02340       printf( "*SETBKCOLOR*\n" );
02341       edit_color( "crColor", crColor );
02342     }
02343 #endif /* ENABLE_EDITING */
02344   };
02345 
02347 
02351   class EMRSETBKMODE : public METARECORD, ::EMRSETBKMODE {
02352   public:
02356     EMRSETBKMODE ( DWORD mode )
02357     {
02358       emr.iType = EMR_SETBKMODE;
02359       emr.nSize = sizeof( ::EMRSETBKMODE );
02360       iMode = mode;
02361     }
02366     EMRSETBKMODE ( DATASTREAM& ds )
02367     {
02368       ds >> emr >> iMode;
02369     }
02373     bool serialize ( DATASTREAM ds )
02374     {
02375       ds << emr << iMode;
02376       return true;
02377     }
02381     int size ( void ) const { return emr.nSize; }
02387     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02388     {
02389       SetBkMode( dc, iMode );
02390     }
02391 #ifdef ENABLE_EDITING
02392 
02395     void edit ( void ) const
02396     {
02397 #if defined(__LP64__)
02398     const char* FMT = "unknown(%d)\n";
02399 #else
02400     const char* FMT = "unknown(%ld)\n";
02401 #endif /* __x86_64__ */
02402       printf( "*SETBKMODE*\n" );
02403       printf( "\tiMode\t: " );
02404       switch ( iMode ) {
02405       case TRANSPARENT: printf( "TRANSPARENT\n" ); break;
02406       case OPAQUE: printf( "OPAQUE\n" ); break;
02407       default: printf( FMT, iMode );
02408       }
02409     }
02410 #endif /* ENABLE_EDITING */
02411   };
02412 
02414 
02417   class EMRSETPOLYFILLMODE : public METARECORD, ::EMRSETPOLYFILLMODE {
02418   public:
02422     EMRSETPOLYFILLMODE ( DWORD mode )
02423     {
02424       emr.iType = EMR_SETPOLYFILLMODE;
02425       emr.nSize = sizeof( ::EMRSETPOLYFILLMODE );
02426       iMode = mode;
02427     }
02432     EMRSETPOLYFILLMODE ( DATASTREAM& ds )
02433     {
02434       ds >> emr >> iMode;
02435     }
02439     bool serialize ( DATASTREAM ds )
02440     {
02441       ds << emr << iMode;
02442       return true;
02443     }
02447     int size ( void ) const { return emr.nSize; }
02453     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02454     {
02455       SetPolyFillMode( dc, iMode );
02456     }
02457 #ifdef ENABLE_EDITING
02458 
02461     void edit ( void ) const
02462     {
02463 #if defined(__LP64__)
02464     const char* FMT = "unknown(%d)\n";
02465 #else
02466     const char* FMT = "unknown(%ld)\n";
02467 #endif /* __x86_64__ */
02468       printf( "*SETPOLYFILLMODE*\n" );
02469       printf( "\tiMode: " );
02470       switch ( iMode ) {
02471       case ALTERNATE: printf( "ALTERNATE\n" ); break;
02472       case WINDING: printf( "WINDING\n" ); break;
02473       default: printf( FMT, iMode );
02474       }
02475     }
02476 #endif /* ENABLE_EDITING */
02477   };
02478 
02480 
02484   class EMRSETMAPMODE : public METARECORD, ::EMRSETMAPMODE {
02485   public:
02489     EMRSETMAPMODE ( DWORD mode )
02490     {
02491       emr.iType = EMR_SETMAPMODE;
02492       emr.nSize = sizeof( ::EMRSETMAPMODE );
02493       iMode = mode;
02494     }
02499     EMRSETMAPMODE ( DATASTREAM& ds )
02500     {
02501       ds >> emr >> iMode;
02502     }
02506     bool serialize ( DATASTREAM ds )
02507     {
02508       ds << emr << iMode;
02509       return true;
02510     }
02514     int size ( void ) const { return emr.nSize; }
02520     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02521     {
02522       SetMapMode( dc, iMode );
02523     }
02524 #ifdef ENABLE_EDITING
02525 
02528     void edit ( void ) const
02529     {
02530 #if defined(__LP64__)
02531     const char* FMT = "unknown(%d)\n";
02532 #else
02533     const char* FMT = "unknown(%ld)\n";
02534 #endif /* __x86_64__ */
02535       printf( "*SETMAPMODE*\n" );
02536       printf( "\tiMode\t: " );
02537       switch ( iMode ) {
02538       case MM_TEXT: printf( "MM_TEXT\n" ); break;
02539       case MM_LOMETRIC: printf( "MM_LOMETRIC\n" ); break;
02540       case MM_HIMETRIC: printf( "MM_HIMETRIC\n" ); break;
02541       case MM_LOENGLISH: printf( "MM_LOENGLISH\n" ); break;
02542       case MM_HIENGLISH: printf( "MM_HIENGLISH\n" ); break;
02543       case MM_TWIPS: printf( "MM_TWIPS\n" ); break;
02544       case MM_ISOTROPIC: printf( "MM_ISOTROPIC\n" ); break;
02545       case MM_ANISOTROPIC: printf( "MM_ANISOTROPIC\n" ); break;
02546       default: printf( FMT, iMode );
02547       }
02548     }
02549 #endif /* ENABLE_EDITING */
02550   };
02551 
02553 
02556   class EMRSELECTOBJECT : public METARECORD, ::EMRSELECTOBJECT {
02557   public:
02561     EMRSELECTOBJECT ( HGDIOBJ object )
02562     {
02563       emr.iType = EMR_SELECTOBJECT;
02564       emr.nSize = sizeof( ::EMRSELECTOBJECT );
02565       ihObject = object;
02566     }
02571     EMRSELECTOBJECT ( DATASTREAM& ds )
02572     {
02573       ds >> emr >> ihObject;
02574     }
02578     bool serialize ( DATASTREAM ds )
02579     {
02580       ds << emr << ihObject;
02581       return true;
02582     }
02586     int size ( void ) const { return emr.nSize; }
02592     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
02593 #ifdef ENABLE_EDITING
02594 
02597     void edit ( void ) const
02598     {
02599 #if defined(__LP64__)
02600       const char* FMT = "\tihObject\t: 0x%x\n";
02601 #else
02602       const char* FMT = "\tihObject\t: 0x%lx\n";
02603 #endif /* __x86_64__ */
02604       printf( "*SELECTOBJECT*\n" );
02605       printf( FMT, ihObject );
02606     }
02607 #endif /* ENABLE_EDITING */
02608   };
02609 
02611 
02614   class EMRDELETEOBJECT : public METARECORD, ::EMRDELETEOBJECT {
02615   public:
02619     EMRDELETEOBJECT ( HGDIOBJ object )
02620     {
02621       emr.iType = EMR_DELETEOBJECT;
02622       emr.nSize = sizeof( ::EMRDELETEOBJECT );
02623       ihObject = object;
02624     }
02629     EMRDELETEOBJECT ( DATASTREAM& ds )
02630     {
02631       ds >> emr >> ihObject;
02632     }
02636     bool serialize ( DATASTREAM ds )
02637     {
02638       ds << emr << ihObject;
02639       return true;
02640     }
02644     int size ( void ) const { return emr.nSize; }
02650     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
02651 #ifdef ENABLE_EDITING
02652 
02655     void edit ( void ) const
02656     {
02657 #if defined(__LP64__)
02658       const char* FMT = "\tihObject\t: 0x%x\n";
02659 #else
02660       const char* FMT = "\tihObject\t: 0x%lx\n";
02661 #endif /* __x86_64__ */
02662       printf( "*DELETEOBJECT*\n" );
02663       printf( FMT, ihObject );
02664     }
02665 #endif /* ENABLE_EDITING */
02666   };
02667 
02669 
02672   class EMRMOVETOEX : public METARECORD, ::EMRMOVETOEX {
02673   public:
02678     EMRMOVETOEX ( INT x, INT y )
02679     {
02680       emr.iType = EMR_MOVETOEX;
02681       emr.nSize = sizeof( ::EMRMOVETOEX );
02682       ptl.x = x;
02683       ptl.y = y;
02684     }
02689     EMRMOVETOEX ( DATASTREAM& ds )
02690     {
02691       ds >> emr >> ptl;
02692     }
02696     bool serialize ( DATASTREAM ds )
02697     {
02698       ds << emr << ptl;
02699       return true;
02700     }
02704     int size ( void ) const { return emr.nSize; }
02710     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02711     {
02712       MoveToEx( dc,  ptl.x, ptl.y, 0 );
02713     }
02714 #ifdef ENABLE_EDITING
02715 
02718     void edit ( void ) const
02719     {
02720       printf( "*MOVETOEX*\n" );
02721       edit_pointl( "ptl", ptl );
02722     }
02723 #endif /* ENABLE_EDITING */
02724   };
02725 
02727 
02730   class EMRLINETO : public METARECORD, ::EMRLINETO {
02731   public:
02736     EMRLINETO ( INT x, INT y )
02737     {
02738       emr.iType = EMR_LINETO;
02739       emr.nSize = sizeof( ::EMRLINETO );
02740       ptl.x = x;
02741       ptl.y = y;
02742     }
02747     EMRLINETO ( DATASTREAM& ds )
02748     {
02749       ds >> emr >> ptl;
02750     }
02754     bool serialize ( DATASTREAM ds )
02755     {
02756       ds << emr << ptl;
02757       return true;
02758     }
02762     int size ( void ) const { return emr.nSize; }
02768     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02769     {
02770       LineTo( dc,  ptl.x, ptl.y );
02771     }
02772 #ifdef ENABLE_EDITING
02773 
02776     void edit ( void ) const
02777     {
02778       printf( "*LINETO*\n" );
02779       edit_pointl( "ptl", ptl );
02780     }
02781 #endif /* ENABLE_EDITING */
02782   };
02783 
02785 
02788   class EMRARC : public METARECORD, ::EMRARC {
02789   public:
02801     EMRARC ( INT left, INT top, INT right, INT bottom, INT xstart,
02802              INT ystart, INT xend, INT yend )
02803     {
02804       emr.iType = EMR_ARC;
02805       emr.nSize = sizeof( ::EMRARC );
02806       rclBox.left = left;
02807       rclBox.right = right;
02808       rclBox.bottom = bottom;
02809       rclBox.top = top;
02810       ptlStart.x = xstart;
02811       ptlStart.y = ystart;
02812       ptlEnd.x = xend;
02813       ptlEnd.y = yend;
02814     }
02819     EMRARC ( DATASTREAM& ds )
02820     {
02821       ds >> emr >> rclBox >> ptlStart >> ptlEnd;
02822     }
02826     bool serialize ( DATASTREAM ds )
02827     {
02828       ds << emr << rclBox << ptlStart << ptlEnd;
02829       return true;
02830     }
02834     int size ( void ) const { return emr.nSize; }
02840     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02841     {
02842       Arc( dc, rclBox.left, rclBox.top, rclBox.right, rclBox.bottom,
02843            ptlStart.x, ptlStart.y, ptlEnd.x, ptlEnd.y );
02844     }
02845 #ifdef ENABLE_EDITING
02846 
02849     void edit ( void ) const
02850     {
02851       printf( "*ARC*\n" );
02852       edit_rectl( "rclBox\t", rclBox );
02853       edit_pointl( "ptlStart", ptlStart );
02854       edit_pointl( "ptlEnd\t", ptlEnd );
02855     }
02856 #endif /* ENABLE_EDITING */
02857   };
02858 
02860 
02863   class EMRARCTO : public METARECORD, ::EMRARCTO {
02864   public:
02876     EMRARCTO ( INT left, INT top, INT right, INT bottom, INT xstart,
02877              INT ystart, INT xend, INT yend )
02878     {
02879       emr.iType = EMR_ARCTO;
02880       emr.nSize = sizeof( ::EMRARCTO );
02881       rclBox.left = left;
02882       rclBox.right = right;
02883       rclBox.bottom = bottom;
02884       rclBox.top = top;
02885       ptlStart.x = xstart;
02886       ptlStart.y = ystart;
02887       ptlEnd.x = xend;
02888       ptlEnd.y = yend;
02889     }
02894     EMRARCTO ( DATASTREAM& ds )
02895     {
02896       ds >> emr >> rclBox >> ptlStart >> ptlEnd;
02897     }
02901     bool serialize ( DATASTREAM ds )
02902     {
02903       ds << emr << rclBox << ptlStart << ptlEnd;
02904       return true;
02905     }
02909     int size ( void ) const { return emr.nSize; }
02915     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02916     {
02917       ArcTo( dc, rclBox.left, rclBox.top, rclBox.right, rclBox.bottom,
02918              ptlStart.x, ptlStart.y, ptlEnd.x, ptlEnd.y );
02919     }
02920 #ifdef ENABLE_EDITING
02921 
02924     void edit ( void ) const
02925     {
02926       printf( "*ARCTO*\n" );
02927       edit_rectl( "rclBox\t", rclBox );
02928       edit_pointl( "ptlStart", ptlStart );
02929       edit_pointl( "ptlEnd\t", ptlEnd );
02930     }
02931 #endif /* ENABLE_EDITING */
02932   };
02933 
02935 
02938   class EMRRECTANGLE : public METARECORD, ::EMRRECTANGLE {
02939   public:
02946     EMRRECTANGLE ( INT left, INT top, INT right, INT bottom )
02947     {
02948       emr.iType = EMR_RECTANGLE;
02949       emr.nSize = sizeof( ::EMRRECTANGLE );
02950       rclBox.left = left;
02951       rclBox.right = right;
02952       rclBox.bottom = bottom;
02953       rclBox.top = top;
02954     }
02959     EMRRECTANGLE ( DATASTREAM& ds )
02960     {
02961       ds >> emr >> rclBox;
02962     }
02966     bool serialize ( DATASTREAM ds )
02967     {
02968       ds << emr << rclBox;
02969       return true;
02970     }
02974     int size ( void ) const { return emr.nSize; }
02980     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02981     {
02982       Rectangle( dc, rclBox.left, rclBox.top, rclBox.right, rclBox.bottom );
02983     }
02984 #ifdef ENABLE_EDITING
02985 
02988     void edit ( void ) const
02989     {
02990       printf( "*RECTANGLE*\n" );
02991       edit_rectl( "rclBox", rclBox );
02992     }
02993 #endif /* ENABLE_EDITING */
02994   };
02995 
02997 
03000   class EMRELLIPSE : public METARECORD, ::EMRELLIPSE {
03001   public:
03009     EMRELLIPSE ( INT left, INT top, INT right, INT bottom )
03010     {
03011       emr.iType = EMR_ELLIPSE;
03012       emr.nSize = sizeof( ::EMRELLIPSE );
03013       rclBox.left = left;
03014       rclBox.right = right;
03015       rclBox.bottom = bottom;
03016       rclBox.top = top;
03017     }
03022     EMRELLIPSE ( DATASTREAM& ds )
03023     {
03024       ds >> emr >> rclBox;
03025     }
03029     bool serialize ( DATASTREAM ds )
03030     {
03031       ds << emr << rclBox;
03032       return true;
03033     }
03037     int size ( void ) const { return emr.nSize; }
03043     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03044     {
03045       Ellipse( dc, rclBox.left, rclBox.top, rclBox.right, rclBox.bottom );
03046     }
03047 #ifdef ENABLE_EDITING
03048 
03051     void edit ( void ) const
03052     {
03053       printf( "*ELLIPSE*\n" );
03054       edit_rectl( "rclBox", rclBox );
03055     }
03056 #endif /* ENABLE_EDITING */
03057   };
03058 
03060 
03063   class EMRPOLYLINE : public METARECORD, ::EMRPOLYLINE {
03064     POINTL* lpoints;
03065   public:
03071     EMRPOLYLINE ( const RECTL* bounds, const POINT* points, INT n )
03072     {
03073       cptl = n;
03074       aptl[0].x = 0;            // Really unused
03075       aptl[0].y = 0;
03076 
03077       emr.iType = EMR_POLYLINE;
03078       // The (cptl - 1) below is to account for aptl, which isn't written out
03079       emr.nSize = sizeof( ::EMRPOLYLINE ) + sizeof( POINTL ) * ( cptl - 1);
03080 
03081       lpoints = new POINTL[cptl];
03082 
03083       for (int i=0; i<n; i++) {
03084         lpoints[i].x = points[i].x;
03085         lpoints[i].y = points[i].y;
03086       }
03087 
03088       rclBounds = *bounds;
03089     }
03093     ~EMRPOLYLINE ( )
03094     {
03095       if ( lpoints ) delete[] lpoints;
03096     }
03101     EMRPOLYLINE ( DATASTREAM& ds )
03102     {
03103       ds >> emr >> rclBounds >> cptl;
03104 
03105       lpoints = new POINTL[cptl];
03106 
03107       POINTLARRAY points( lpoints, cptl );
03108 
03109       ds >> points;
03110     }
03114     bool serialize ( DATASTREAM ds )
03115     {
03116       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
03117       return true;
03118     }
03122     int size ( void ) const { return emr.nSize; }
03128     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03129     {
03130       // According to the wine windef.h header, POINT and POINTL are equivalent
03131       Polyline( dc, (POINT*)lpoints, cptl );
03132     }
03133 #ifdef ENABLE_EDITING
03134 
03137     void edit ( void ) const
03138     {
03139       printf( "*POLYLINE*\n" );
03140       edit_rectl( "rclBounds", rclBounds );
03141 #if 0
03142       printf( "\tcptl              : %ld\n", cptl );
03143       printf( "\taptl->\n" );
03144       for ( unsigned int i = 0; i < cptl; i++ )
03145         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
03146 #else
03147       edit_pointlarray( "\t", cptl, lpoints );
03148 #endif
03149     }
03150 #endif /* ENABLE_EDITING */
03151   };
03152 
03154 
03157   class EMRPOLYLINE16 : public METARECORD, ::EMRPOLYLINE16 {
03158     POINT16* lpoints;
03159   public:
03165     EMRPOLYLINE16 ( const RECTL* bounds, const POINT16* points, INT n )
03166     {
03167       cpts = n;
03168       apts[0].x = 0;            // Really unused
03169       apts[0].y = 0;
03170 
03171       emr.iType = EMR_POLYLINE16;
03172       // The (cptl - 1) below is to account for aptl, which isn't written out
03173       emr.nSize = sizeof( ::EMRPOLYLINE16 ) + sizeof( POINT16 ) * ( cpts - 1);
03174 
03175       lpoints = new POINT16[cpts];
03176 
03177       for (int i=0; i<n; i++) {
03178         lpoints[i].x = points[i].x;
03179         lpoints[i].y = points[i].y;
03180       }
03181 
03182       rclBounds = *bounds;
03183     }
03190     EMRPOLYLINE16 ( const RECTL* bounds, const POINT* points, INT n )
03191     {
03192       cpts = n;
03193       apts[0].x = 0;            // Really unused
03194       apts[0].y = 0;
03195 
03196       emr.iType = EMR_POLYLINE16;
03197       // The (cptl - 1) below is to account for aptl, which isn't written out
03198       emr.nSize = sizeof( ::EMRPOLYLINE16 ) + sizeof( POINT16 ) * ( cpts - 1);
03199 
03200       lpoints = new POINT16[cpts];
03201 
03202       for (int i=0; i<n; i++) {
03203         lpoints[i].x = points[i].x;
03204         lpoints[i].y = points[i].y;
03205       }
03206 
03207       rclBounds = *bounds;
03208     }
03212     ~EMRPOLYLINE16 ( )
03213     {
03214       if ( lpoints ) delete[] lpoints;
03215     }
03220     EMRPOLYLINE16 ( DATASTREAM& ds )
03221     {
03222       ds >> emr >> rclBounds >> cpts;
03223 
03224       lpoints = new POINT16[cpts];
03225 
03226       POINT16ARRAY points( lpoints, cpts );
03227 
03228       ds >> points;
03229     }
03233     bool serialize ( DATASTREAM ds )
03234     {
03235       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
03236       return true;
03237     }
03241     int size ( void ) const { return emr.nSize; }
03247     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03248     {
03249       // According to the wine windef.h header, POINT and POINTL are equivalent
03250       Polyline16( dc, lpoints, cpts );
03251     }
03252 #ifdef ENABLE_EDITING
03253 
03256     void edit ( void ) const
03257     {
03258       printf( "*POLYLINE16*\n" );
03259       edit_rectl( "rclBounds", rclBounds );
03260       edit_point16array( "\t", cpts, lpoints );
03261     }
03262 #endif /* ENABLE_EDITING */
03263   };
03264 
03266 
03269   class EMRPOLYGON : public METARECORD, ::EMRPOLYGON {
03270     POINTL* lpoints;
03271   public:
03277     EMRPOLYGON ( const RECTL* bounds, const POINT* points, INT n )
03278     {
03279       cptl = n;
03280       aptl[0].x = 0;            // Really unused
03281       aptl[0].y = 0;
03282 
03283       emr.iType = EMR_POLYGON;
03284       // The (cptl-1) below is to account for aptl, which isn't written out
03285       emr.nSize = sizeof( ::EMRPOLYGON ) + sizeof( POINTL ) * (cptl-1);
03286 
03287       lpoints = new POINTL[cptl];
03288 
03289       for (int i=0; i<n; i++) {
03290         lpoints[i].x = points[i].x;
03291         lpoints[i].y = points[i].y;
03292       }
03293 
03294       rclBounds = *bounds;
03295     }
03300     EMRPOLYGON ( DATASTREAM& ds )
03301     {
03302       ds >> emr >> rclBounds >> cptl;
03303 
03304       lpoints = new POINTL[cptl];
03305 
03306       POINTLARRAY points( lpoints, cptl );
03307 
03308       ds >> points;
03309     }
03313     ~EMRPOLYGON ( )
03314     {
03315       if ( lpoints ) delete[] lpoints;
03316     }
03320     bool serialize ( DATASTREAM ds )
03321     {
03322       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
03323       return true;
03324     }
03328     int size ( void ) const { return emr.nSize; }
03334     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03335     {
03336       // According to the wine windef.h header, POINT and POINTL are equivalent
03337       Polygon( dc, (POINT*)lpoints, cptl );
03338     }
03339 #ifdef ENABLE_EDITING
03340 
03343     void edit ( void ) const
03344     {
03345       printf( "*POLYGON*\n" );
03346       edit_rectl( "rclBounds", rclBounds );
03347 #if 0
03348       printf( "\tcptl              : %ld\n", cptl );
03349       printf( "\taptl->\n" );
03350       for ( unsigned int i = 0; i < cptl; i++ )
03351         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
03352 #else
03353       edit_pointlarray( "\t", cptl, lpoints );
03354 #endif
03355     }
03356 #endif /* ENABLE_EDITING */
03357   };
03358 
03360 
03363   class EMRPOLYGON16 : public METARECORD, ::EMRPOLYGON16 {
03364     POINT16* lpoints;
03365   public:
03371     EMRPOLYGON16 ( const RECTL* bounds, const POINT* points, INT16 n )
03372     {
03373       cpts = n;
03374       apts[0].x = 0;            // Really unused
03375       apts[0].y = 0;
03376 
03377       emr.iType = EMR_POLYGON16;
03378       // The (cptl-1) below is to account for aptl, which isn't written out
03379       emr.nSize = sizeof( ::EMRPOLYGON16 ) + sizeof( POINT16 ) * (cpts-1);
03380 
03381       lpoints = new POINT16[cpts];
03382 
03383       for (int i=0; i<n; i++) {
03384         lpoints[i].x = points[i].x;
03385         lpoints[i].y = points[i].y;
03386       }
03387 
03388       rclBounds = *bounds;
03389     }
03396     EMRPOLYGON16 ( const RECTL* bounds, const POINT16* points, INT16 n )
03397     {
03398       cpts = n;
03399       apts[0].x = 0;            // Really unused
03400       apts[0].y = 0;
03401 
03402       emr.iType = EMR_POLYGON16;
03403       // The (cptl-1) below is to account for aptl, which isn't written out
03404       emr.nSize = sizeof( ::EMRPOLYGON16 ) + sizeof( POINT16 ) * (cpts-1);
03405 
03406       lpoints = new POINT16[cpts];
03407 
03408       for (int i=0; i<n; i++) {
03409         lpoints[i].x = points[i].x;
03410         lpoints[i].y = points[i].y;
03411       }
03412 
03413       rclBounds = *bounds;
03414     }
03419     EMRPOLYGON16 ( DATASTREAM& ds )
03420     {
03421       ds >> emr >> rclBounds >> cpts;
03422 
03423       lpoints = new POINT16[cpts];
03424 
03425       POINT16ARRAY points( lpoints, cpts );
03426 
03427       ds >> points;
03428     }
03432     ~EMRPOLYGON16 ( )
03433     {
03434       if ( lpoints ) delete[] lpoints;
03435     }
03439     bool serialize ( DATASTREAM ds )
03440     {
03441       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
03442       return true;
03443     }
03447     int size ( void ) const { return emr.nSize; }
03453     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03454     {
03455       // According to the wine windef.h header, POINT and POINTL are equivalent
03456       Polygon16( dc, lpoints, cpts );
03457     }
03458 #ifdef ENABLE_EDITING
03459 
03462     void edit ( void ) const
03463     {
03464       printf( "*POLYGON16*\n" );
03465       edit_rectl( "rclBounds", rclBounds );
03466       edit_point16array( "\t", cpts, lpoints );
03467     }
03468 #endif /* ENABLE_EDITING */
03469   };
03470 
03472 
03475   class EMRPOLYPOLYGON : public METARECORD, ::EMRPOLYPOLYGON {
03476     DWORD* lcounts;
03477     POINTL* lpoints;
03478   public:
03485     EMRPOLYPOLYGON ( const RECTL* bounds, const POINT* points, const INT* counts,
03486                      UINT polygons )
03487     {
03488       nPolys = polygons;
03489       // Count the number of points in points
03490       int n = 0;
03491       for ( unsigned int i = 0; i < nPolys; i++ )
03492         n += counts[i];
03493 
03494       cptl = n;
03495       aPolyCounts[0] = 0;       // Really unused
03496       aptl[0].x = 0;
03497       aptl[0].y = 0;
03498 
03499       emr.iType = EMR_POLYPOLYGON;
03500       // The (#-1)'s below are to account for aPolyCounts[0] and aptl[0], which
03501       // aren't directly written out
03502       emr.nSize = sizeof( ::EMRPOLYPOLYGON ) + sizeof( POINTL ) * (cptl-1)
03503         + sizeof( DWORD ) * (nPolys-1);
03504 
03505       lcounts = new DWORD[nPolys];
03506 
03507       for ( unsigned int i = 0; i < nPolys; i++ )
03508         lcounts[i] = counts[i];
03509 
03510       lpoints = new POINTL[cptl];
03511 
03512       for (int i=0; i<n; i++) {
03513         lpoints[i].x = points[i].x;
03514         lpoints[i].y = points[i].y;
03515       }
03516 
03517       rclBounds = *bounds;
03518     }
03522     ~EMRPOLYPOLYGON ( )
03523     {
03524       if ( lcounts ) delete[] lcounts;
03525       if ( lpoints ) delete[] lpoints;
03526     }
03531     EMRPOLYPOLYGON ( DATASTREAM& ds )
03532     {
03533       ds >> emr >> rclBounds >> nPolys >> cptl;
03534 
03535       lcounts = new DWORD[nPolys];
03536 
03537       DWORDARRAY counts( lcounts, nPolys );
03538 
03539       ds >> counts;
03540 
03541       lpoints = new POINTL[cptl];
03542 
03543       POINTLARRAY points( lpoints, cptl );
03544 
03545       ds >> points;
03546     }
03550     bool serialize ( DATASTREAM ds )
03551     {
03552       ds << emr << rclBounds << nPolys << cptl << DWORDARRAY( lcounts, nPolys )
03553          << POINTLARRAY( lpoints, cptl );
03554       return true;
03555     }
03559     int size ( void ) const { return emr.nSize; }
03565     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03566     {
03567       // According to the wine windef.h header, POINT and POINTL are equivalent
03568       // (but DWORD and INT are not)
03569       INT* counts = new INT[nPolys];
03570       for ( unsigned int i = 0; i < nPolys; i++ )
03571         counts[i] = lcounts[i];
03572 
03573       PolyPolygon( dc, (POINT*)lpoints, counts, nPolys );
03574 
03575       delete[] counts;
03576     }
03577 #ifdef ENABLE_EDITING
03578 
03581     void edit ( void ) const
03582     {
03583 #if defined(__LP64__)
03584       const char* FMT0 = "\tnPolys\t\t: %d\n";
03585       const char* FMT1 = "\tcptl\t\t: %d\n";
03586       const char* FMT2 = "%d\n";
03587       const char* FMT3 = "\t\t\t  %d\n";
03588       const char* FMT4 = "%d, %d\n";
03589       const char* FMT5 = "\t\t\t  %d, %d\n";
03590 #else
03591       const char* FMT0 = "\tnPolys\t\t: %ld\n";
03592       const char* FMT1 = "\tcptl\t\t: %ld\n";
03593       const char* FMT2 = "%ld\n";
03594       const char* FMT3 = "\t\t\t  %ld\n";
03595       const char* FMT4 = "%ld, %ld\n";
03596       const char* FMT5 = "\t\t\t  %ld, %ld\n";
03597 #endif /* __x86_64__ */
03598       printf( "*POLYPOLYGON*\n" );
03599       edit_rectl( "rclBounds", rclBounds );
03600       printf( FMT0, nPolys );
03601       printf( FMT1, cptl );
03602       printf( "\taPolyCounts\t: " );
03603       if ( nPolys > 0 )
03604         printf( FMT2, lcounts[0] );
03605       else
03606         puts( "" );
03607       for ( unsigned int i = 1; i < nPolys; i++ )
03608         printf( FMT3, lcounts[i] );
03609       printf( "\tapts\t\t: " );
03610       if ( cptl > 0 )
03611         printf( FMT4, lpoints[0].x, lpoints[0].y );
03612       else
03613         puts( "" );
03614       for ( unsigned int i = 1; i < cptl; i++ )
03615         printf( FMT5, lpoints[i].x, lpoints[i].y );
03616     }
03617 #endif /* ENABLE_EDITING */
03618   };
03619 
03621 
03624   class EMRPOLYPOLYGON16 : public METARECORD, ::EMRPOLYPOLYGON16 {
03625     DWORD* lcounts;
03626     POINT16* lpoints;
03627   public:
03634     EMRPOLYPOLYGON16 ( const RECTL* bounds, const POINT* points,
03635                        const INT* counts, UINT polygons )
03636     {
03637       nPolys = polygons;
03638       // Count the number of points in points
03639       int n = 0;
03640       for ( unsigned int i = 0; i < nPolys; i++ )
03641         n += counts[i];
03642 
03643       cpts = n;
03644       aPolyCounts[0] = 0;       // Really unused
03645       apts[0].x = 0;
03646       apts[0].y = 0;
03647 
03648       emr.iType = EMR_POLYPOLYGON16;
03649       // The (#-1)'s below are to account for aPolyCounts[0] and aptl[0], which
03650       // aren't directly written out
03651       emr.nSize = sizeof( ::EMRPOLYPOLYGON16 ) + sizeof( POINT16 ) * (cpts-1)
03652         + sizeof( DWORD ) * (nPolys-1);
03653 
03654       lcounts = new DWORD[nPolys];
03655 
03656       for ( unsigned int i = 0; i < nPolys; i++ )
03657         lcounts[i] = counts[i];
03658 
03659       lpoints = new POINT16[cpts];
03660 
03661       for (int i=0; i<n; i++) {
03662         lpoints[i].x = points[i].x;
03663         lpoints[i].y = points[i].y;
03664       }
03665 
03666       rclBounds = *bounds;
03667     }
03675     EMRPOLYPOLYGON16 ( const RECTL* bounds, const POINT16* points,
03676                        const INT* counts, UINT16 polygons )
03677     {
03678       nPolys = polygons;
03679       // Count the number of points in points
03680       int n = 0;
03681       for ( unsigned int i = 0; i < nPolys; i++ )
03682         n += counts[i];
03683 
03684       cpts = n;
03685       aPolyCounts[0] = 0;       // Really unused
03686       apts[0].x = 0;
03687       apts[0].y = 0;
03688 
03689       emr.iType = EMR_POLYPOLYGON16;
03690       // The (#-1)'s below are to account for aPolyCounts[0] and aptl[0], which
03691       // aren't directly written out
03692       emr.nSize = sizeof( ::EMRPOLYPOLYGON16 ) + sizeof( POINT16 ) * (cpts-1)
03693         + sizeof( DWORD ) * (nPolys-1);
03694 
03695       lcounts = new DWORD[nPolys];
03696 
03697       for ( unsigned int i = 0; i < nPolys; i++ )
03698         lcounts[i] = counts[i];
03699 
03700       lpoints = new POINT16[cpts];
03701 
03702       for (int i=0; i<n; i++) {
03703         lpoints[i].x = points[i].x;
03704         lpoints[i].y = points[i].y;
03705       }
03706 
03707       rclBounds = *bounds;
03708     }
03712     ~EMRPOLYPOLYGON16 ( )
03713     {
03714       if ( lcounts ) delete[] lcounts;
03715       if ( lpoints ) delete[] lpoints;
03716     }
03721     EMRPOLYPOLYGON16 ( DATASTREAM& ds )
03722     {
03723       ds >> emr >> rclBounds >> nPolys >> cpts;
03724 
03725       lcounts = new DWORD[nPolys];
03726 
03727       DWORDARRAY counts( lcounts, nPolys );
03728 
03729       ds >> counts;
03730 
03731       lpoints = new POINT16[cpts];
03732 
03733       POINT16ARRAY points( lpoints, cpts );
03734 
03735       ds >> points;
03736     }
03740     bool serialize ( DATASTREAM ds )
03741     {
03742       ds << emr << rclBounds << nPolys << cpts << DWORDARRAY( lcounts, nPolys )
03743          << POINT16ARRAY( lpoints, cpts );
03744       return true;
03745     }
03749     int size ( void ) const { return emr.nSize; }
03755     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03756     {
03757       // According to the wine windef.h header, POINT and POINTL are equivalent
03758       // (but DWORD and INT are not)
03759       INT* counts = new INT[nPolys];
03760       for ( unsigned int i = 0; i < nPolys; i++ )
03761         counts[i] = lcounts[i];
03762 
03763       PolyPolygon16( dc, lpoints, counts, nPolys );
03764 
03765       delete[] counts;
03766     }
03767 #ifdef ENABLE_EDITING
03768 
03771     void edit ( void ) const
03772     {
03773 #if defined(__LP64__)
03774       const char* FMT0 = "\tnPolys\t\t: %d\n";
03775       const char* FMT1 = "\tcptl\t\t: %d\n";
03776       const char* FMT2 = "%d\n";
03777       const char* FMT3 = "\t\t\t  %d\n";
03778 #else
03779       const char* FMT0 = "\tnPolys\t\t: %ld\n";
03780       const char* FMT1 = "\tcptl\t\t: %ld\n";
03781       const char* FMT2 = "%ld\n";
03782       const char* FMT3 = "\t\t\t  %ld\n";
03783 #endif /* __x86_64__ */
03784       printf( "*POLYPOLYGON16*\n" );
03785       edit_rectl( "rclBounds", rclBounds );
03786       printf( FMT0, nPolys );
03787       printf( FMT1, cpts );
03788       printf( "\taPolyCounts\t: " );
03789       if ( nPolys > 0 )
03790         printf( FMT2, lcounts[0] );
03791       else
03792         puts( "" );
03793       for ( unsigned int i = 1; i < nPolys; i++ )
03794         printf( FMT3, lcounts[i] );
03795       printf( "\tapts\t\t: " );
03796       if ( cpts > 0 )
03797         printf( "%d, %d\n", lpoints[0].x, lpoints[0].y );
03798       else
03799         puts( "" );
03800       for ( unsigned int i = 1; i < cpts; i++ )
03801         printf( "\t\t\t  %d, %d\n", lpoints[i].x, lpoints[i].y );
03802     }
03803 #endif /* ENABLE_EDITING */
03804   };
03805 
03807 
03810   class EMRPOLYBEZIER : public METARECORD, ::EMRPOLYBEZIER {
03811     POINTL* lpoints;
03812   public:
03818     EMRPOLYBEZIER ( const RECTL* bounds, const POINT* points, INT n )
03819     {
03820       cptl = n;
03821       aptl[0].x = 0;            // Really unused
03822       aptl[0].y = 0;
03823 
03824       emr.iType = EMR_POLYBEZIER;
03825       // The (cptl-1) below is to account for aptl, which isn't written out
03826       emr.nSize = sizeof( ::EMRPOLYBEZIER ) + sizeof( POINTL ) * (cptl-1);
03827 
03828       lpoints = new POINTL[cptl];
03829 
03830       for (int i=0; i<n; i++) {
03831         lpoints[i].x = points[i].x;
03832         lpoints[i].y = points[i].y;
03833       }
03834 
03835       rclBounds = *bounds;
03836     }
03841     EMRPOLYBEZIER ( DATASTREAM& ds )
03842     {
03843       ds >> emr >> rclBounds >> cptl;
03844 
03845       lpoints = new POINTL[cptl];
03846 
03847       POINTLARRAY points( lpoints, cptl );
03848 
03849       ds >> points;
03850     }
03854     ~EMRPOLYBEZIER ( )
03855     {
03856       if ( lpoints ) delete[] lpoints;
03857     }
03861     bool serialize ( DATASTREAM ds )
03862     {
03863       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
03864       return true;
03865     }
03869     int size ( void ) const { return emr.nSize; }
03875     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03876     {
03877       // According to the wine windef.h header, POINT and POINTL are equivalent
03878       PolyBezier( dc, (POINT*)lpoints, cptl );
03879     }
03880 #ifdef ENABLE_EDITING
03881 
03884     void edit ( void ) const
03885     {
03886       printf( "*POLYBEZIER*\n" );
03887       edit_rectl( "rclBounds", rclBounds );
03888 #if 0
03889       printf( "\tcptl              : %ld\n", cptl );
03890       printf( "\taptl->\n" );
03891       for ( unsigned int i = 0; i < cptl; i++ )
03892         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
03893 #else
03894       edit_pointlarray( "\t", cptl, lpoints );
03895 #endif
03896     }
03897 #endif /* ENABLE_EDITING */
03898   };
03899 
03901 
03904   class EMRPOLYBEZIER16 : public METARECORD, ::EMRPOLYBEZIER16 {
03905     POINT16* lpoints;
03906   public:
03912     EMRPOLYBEZIER16 ( const RECTL* bounds, const POINT16* points, INT n )
03913     {
03914       cpts = n;
03915       apts[0].x = 0;            // Really unused
03916       apts[0].y = 0;
03917 
03918       emr.iType = EMR_POLYBEZIER16;
03919       // The (cptl-1) below is to account for aptl, which isn't written out
03920       emr.nSize = sizeof( ::EMRPOLYBEZIER16 ) + sizeof( POINT16 ) * (cpts-1);
03921 
03922       lpoints = new POINT16[cpts];
03923 
03924       for (int i=0; i<n; i++) {
03925         lpoints[i].x = points[i].x;
03926         lpoints[i].y = points[i].y;
03927       }
03928 
03929       rclBounds = *bounds;
03930     }
03937     EMRPOLYBEZIER16 ( const RECTL* bounds, const POINT* points, INT n )
03938     {
03939       cpts = n;
03940       apts[0].x = 0;            // Really unused
03941       apts[0].y = 0;
03942 
03943       emr.iType = EMR_POLYBEZIER16;
03944       // The (cptl-1) below is to account for aptl, which isn't written out
03945       emr.nSize = sizeof( ::EMRPOLYBEZIER16 ) + sizeof( POINT16 ) * (cpts-1);
03946 
03947       lpoints = new POINT16[cpts];
03948 
03949       for (int i=0; i<n; i++) {
03950         lpoints[i].x = points[i].x;
03951         lpoints[i].y = points[i].y;
03952       }
03953 
03954       rclBounds = *bounds;
03955     }
03960     EMRPOLYBEZIER16 ( DATASTREAM& ds )
03961     {
03962       ds >> emr >> rclBounds >> cpts;
03963 
03964       lpoints = new POINT16[cpts];
03965 
03966       POINT16ARRAY points( lpoints, cpts );
03967 
03968       ds >> points;
03969     }
03973     ~EMRPOLYBEZIER16 ( )
03974     {
03975       if ( lpoints ) delete[] lpoints;
03976     }
03980     bool serialize ( DATASTREAM ds )
03981     {
03982       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
03983       return true;
03984     }
03988     int size ( void ) const { return emr.nSize; }
03994     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
03995     {
03996       // According to the wine windef.h header, POINT and POINTL are equivalent
03997       PolyBezier16( dc, lpoints, cpts );
03998     }
03999 #ifdef ENABLE_EDITING
04000 
04003     void edit ( void ) const
04004     {
04005       printf( "*POLYBEZIER16*\n" );
04006       edit_rectl( "rclBounds", rclBounds );
04007       edit_point16array( "\t", cpts, lpoints );
04008     }
04009 #endif /* ENABLE_EDITING */
04010   };
04011 
04013 
04016   class EMRPOLYBEZIERTO : public METARECORD, ::EMRPOLYBEZIER {
04017     POINTL* lpoints;
04018   public:
04024     EMRPOLYBEZIERTO ( const RECTL* bounds, const POINT* points, INT n )
04025     {
04026       cptl = n;
04027       aptl[0].x = 0;            // Really unused
04028       aptl[0].y = 0;
04029 
04030       emr.iType = EMR_POLYBEZIERTO;
04031       // The (cptl-1) below is to account for aptl, which isn't written out
04032       emr.nSize = sizeof( ::EMRPOLYBEZIERTO ) + sizeof( POINTL ) * (cptl-1);
04033 
04034       lpoints = new POINTL[cptl];
04035 
04036       for (int i=0; i<n; i++) {
04037         lpoints[i].x = points[i].x;
04038         lpoints[i].y = points[i].y;
04039       }
04040 
04041       rclBounds = *bounds;
04042     }
04047     EMRPOLYBEZIERTO ( DATASTREAM& ds )
04048     {
04049       ds >> emr >> rclBounds >> cptl;
04050 
04051       lpoints = new POINTL[cptl];
04052 
04053       POINTLARRAY points( lpoints, cptl );
04054 
04055       ds >> points;
04056     }
04060     ~EMRPOLYBEZIERTO ( )
04061     {
04062       if ( lpoints ) delete[] lpoints;
04063     }
04067     bool serialize ( DATASTREAM ds )
04068     {
04069       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
04070       return true;
04071     }
04075     int size ( void ) const { return emr.nSize; }
04081     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04082     {
04083       // According to the wine windef.h header, POINT and POINTL are equivalent
04084       PolyBezierTo( dc, (POINT*)lpoints, cptl );
04085     }
04086 #ifdef ENABLE_EDITING
04087 
04090     void edit ( void ) const
04091     {
04092       printf( "*POLYBEZIERTO*\n" );
04093       edit_rectl( "rclBounds", rclBounds );
04094 #if 0
04095       printf( "\tcptl              : %ld\n", cptl );
04096       printf( "\taptl->\n" );
04097       for ( unsigned int i = 0; i < cptl; i++ )
04098         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
04099 #else
04100       edit_pointlarray( "\t", cptl, lpoints );
04101 #endif
04102     }
04103 #endif /* ENABLE_EDITING */
04104   };
04105 
04107 
04110   class EMRPOLYBEZIERTO16 : public METARECORD, ::EMRPOLYBEZIER16 {
04111     POINT16* lpoints;
04112   public:
04118     EMRPOLYBEZIERTO16 ( const RECTL* bounds, const POINT16* points, INT n )
04119     {
04120       cpts = n;
04121       apts[0].x = 0;            // Really unused
04122       apts[0].y = 0;
04123 
04124       emr.iType = EMR_POLYBEZIERTO16;
04125       // The (cptl-1) below is to account for aptl, which isn't written out
04126       emr.nSize = sizeof( ::EMRPOLYBEZIERTO16 ) + sizeof( POINT16 ) * (cpts-1);
04127 
04128       lpoints = new POINT16[cpts];
04129 
04130       for (int i=0; i<n; i++) {
04131         lpoints[i].x = points[i].x;
04132         lpoints[i].y = points[i].y;
04133       }
04134 
04135       rclBounds = *bounds;
04136     }
04143     EMRPOLYBEZIERTO16 ( const RECTL* bounds, const POINT* points, INT n )
04144     {
04145       cpts = n;
04146       apts[0].x = 0;            // Really unused
04147       apts[0].y = 0;
04148 
04149       emr.iType = EMR_POLYBEZIERTO16;
04150       // The (cptl-1) below is to account for aptl, which isn't written out
04151       emr.nSize = sizeof( ::EMRPOLYBEZIERTO16 ) + sizeof( POINT16 ) * (cpts-1);
04152 
04153       lpoints = new POINT16[cpts];
04154 
04155       for (int i=0; i<n; i++) {
04156         lpoints[i].x = points[i].x;
04157         lpoints[i].y = points[i].y;
04158       }
04159 
04160       rclBounds = *bounds;
04161     }
04166     EMRPOLYBEZIERTO16 ( DATASTREAM& ds )
04167     {
04168       ds >> emr >> rclBounds >> cpts;
04169 
04170       lpoints = new POINT16[cpts];
04171 
04172       POINT16ARRAY points( lpoints, cpts );
04173 
04174       ds >> points;
04175     }
04179     ~EMRPOLYBEZIERTO16 ( )
04180     {
04181       if ( lpoints ) delete[] lpoints;
04182     }
04186     bool serialize ( DATASTREAM ds )
04187     {
04188       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
04189       return true;
04190     }
04194     int size ( void ) const { return emr.nSize; }
04200     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04201     {
04202       // According to the wine windef.h header, POINT and POINTL are equivalent
04203       PolyBezierTo16( dc, lpoints, cpts );
04204     }
04205 #ifdef ENABLE_EDITING
04206 
04209     void edit ( void ) const
04210     {
04211       printf( "*POLYBEZIERTO16*\n" );
04212       edit_rectl( "rclBounds", rclBounds );
04213       edit_point16array( "\t", cpts, lpoints );
04214     }
04215 #endif /* ENABLE_EDITING */
04216   };
04217 
04219 
04222   class EMRPOLYLINETO : public METARECORD, ::EMRPOLYLINETO {
04223     POINTL* lpoints;
04224   public:
04230     EMRPOLYLINETO ( const RECTL* bounds, const POINT* points, INT n )
04231     {
04232       cptl = n;
04233       aptl[0].x = 0;
04234       aptl[0].y = 0;
04235 
04236       emr.iType = EMR_POLYLINETO;
04237       // The (cptl-1) below is to account for aptl, which isn't written out
04238       emr.nSize = sizeof( ::EMRPOLYLINETO ) + sizeof( POINTL ) * (cptl-1);
04239 
04240       lpoints = new POINTL[cptl];
04241 
04242       for (int i=0; i<n; i++) {
04243         lpoints[i].x = points[i].x;
04244         lpoints[i].y = points[i].y;
04245       }
04246 
04247       rclBounds = *bounds;
04248     }
04253     EMRPOLYLINETO ( DATASTREAM& ds )
04254     {
04255       ds >> emr >> rclBounds >> cptl;
04256 
04257       lpoints = new POINTL[cptl];
04258 
04259       POINTLARRAY points( lpoints, cptl );
04260 
04261       ds >> points;
04262     }
04266     ~EMRPOLYLINETO ( )
04267     {
04268       if ( lpoints ) delete[] lpoints;
04269     }
04273     bool serialize ( DATASTREAM ds )
04274     {
04275       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
04276       return true;
04277     }
04281     int size ( void ) const { return emr.nSize; }
04287     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04288     {
04289       // According to the wine windef.h header, POINT and POINTL are equivalent
04290       PolylineTo( dc, (POINT*)lpoints, cptl );
04291     }
04292 #ifdef ENABLE_EDITING
04293 
04296     void edit ( void ) const
04297     {
04298       printf( "*POLYLINETO*\n" );
04299       edit_rectl( "rclBounds", rclBounds );
04300 #if 0
04301       printf( "\tcptl              : %ld\n", cptl );
04302       printf( "\taptl->\n" );
04303       for ( unsigned int i = 0; i < cptl; i++ )
04304         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
04305 #else
04306       edit_pointlarray( "\t", cptl, lpoints );
04307 #endif
04308     }
04309 #endif /* ENABLE_EDITING */
04310   };
04311 
04313 
04316   class EMRPOLYLINETO16 : public METARECORD, ::EMRPOLYLINETO16 {
04317     POINT16* lpoints;
04318   public:
04324     EMRPOLYLINETO16 ( const RECTL* bounds, const POINT16* points, INT n )
04325     {
04326       cpts = n;
04327       apts[0].x = 0;
04328       apts[0].y = 0;
04329 
04330       emr.iType = EMR_POLYLINETO16;
04331       // The (cptl-1) below is to account for aptl, which isn't written out
04332       emr.nSize = sizeof( ::EMRPOLYLINETO16 ) + sizeof( POINT16 ) * (cpts-1);
04333 
04334       lpoints = new POINT16[cpts];
04335 
04336       for (int i=0; i<n; i++) {
04337         lpoints[i].x = points[i].x;
04338         lpoints[i].y = points[i].y;
04339       }
04340 
04341       rclBounds = *bounds;
04342     }
04349     EMRPOLYLINETO16 ( const RECTL* bounds, const POINT* points, INT n )
04350     {
04351       cpts = n;
04352       apts[0].x = 0;
04353       apts[0].y = 0;
04354 
04355       emr.iType = EMR_POLYLINETO16;
04356       // The (cptl-1) below is to account for aptl, which isn't written out
04357       emr.nSize = sizeof( ::EMRPOLYLINETO16 ) + sizeof( POINT16 ) * (cpts-1);
04358 
04359       lpoints = new POINT16[cpts];
04360 
04361       for (int i=0; i<n; i++) {
04362         lpoints[i].x = points[i].x;
04363         lpoints[i].y = points[i].y;
04364       }
04365 
04366       rclBounds = *bounds;
04367     }
04372     EMRPOLYLINETO16 ( DATASTREAM& ds )
04373     {
04374       ds >> emr >> rclBounds >> cpts;
04375 
04376       lpoints = new POINT16[cpts];
04377 
04378       POINT16ARRAY points( lpoints, cpts );
04379 
04380       ds >> points;
04381     }
04385     ~EMRPOLYLINETO16 ( )
04386     {
04387       if ( lpoints ) delete[] lpoints;
04388     }
04392     bool serialize ( DATASTREAM ds )
04393     {
04394       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
04395       return true;
04396     }
04400     int size ( void ) const { return emr.nSize; }
04406     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04407     {
04408       // According to the wine windef.h header, POINT and POINTL are equivalent
04409       PolylineTo16( dc, lpoints, cpts );
04410     }
04411 #ifdef ENABLE_EDITING
04412 
04415     void edit ( void ) const
04416     {
04417       printf( "*POLYLINETO16*\n" );
04418       edit_rectl( "rclBounds", rclBounds );
04419       edit_point16array( "\t", cpts, lpoints );
04420     }
04421 #endif /* ENABLE_EDITING */
04422   };
04423 
04425 
04430   class EMREXTTEXTOUTA : public METARECORD, ::EMREXTTEXTOUTA {
04431     PSTR string_a;
04432     int string_size;
04433 
04434     INT* dx_i;
04435   public:
04445     EMREXTTEXTOUTA ( const RECTL* bounds, DWORD graphicsMode, FLOAT xScale,
04446                      FLOAT yScale, const PEMRTEXT text, LPCSTR string,
04447                      const INT* dx )
04448     {
04449       emr.iType = EMR_EXTTEXTOUTA;
04450       emr.nSize = sizeof( ::EMREXTTEXTOUTA );
04451 
04452       rclBounds = *bounds;
04453 
04454       iGraphicsMode = graphicsMode;
04455       exScale = xScale;
04456       eyScale = yScale;
04457 
04458       emrtext = *text;
04459 
04460       string_size = ROUND_TO_LONG( emrtext.nChars );
04461 
04462       string_a = new CHAR[ string_size ];
04463 
04464       memset( string_a, 0, sizeof(CHAR) * string_size );
04465 
04466       for ( unsigned int i=0; i<emrtext.nChars; i++ )
04467         string_a[i] = *string++;
04468 
04469       emrtext.offString = emr.nSize;
04470       emr.nSize += string_size * sizeof(CHAR);
04471 #if 0
04472 /* 
04473 Test only - Problem: Windows requires this dx to be set - at least from 2K on
04474 but to calculate real dx values is hard 
04475 For pstoedit - this is "fixed" now by estimating dx in pstoedit
04476 */
04477       if ( !dx ) {
04478         int * dxn = new  int [string_size];
04479         for (unsigned int i=0; i < string_size; i++) dxn[i] = 10;
04480         dx = dxn;
04481       }
04482 #endif
04483 
04484       if ( dx ) {
04485 
04486         dx_i = new INT[ emrtext.nChars ];
04487 
04488         for ( unsigned int i=0; i<emrtext.nChars; i++ )
04489           dx_i[i] = *dx++;
04490 
04491         emrtext.offDx = emr.nSize;
04492         emr.nSize += emrtext.nChars * sizeof(INT);
04493       }
04494       else {
04495         emrtext.offDx = 0;
04496         dx_i = 0;
04497       }
04498     }
04503     EMREXTTEXTOUTA ( DATASTREAM& ds )
04504     {
04505       ds >> emr >> rclBounds >> iGraphicsMode >> exScale >> eyScale >> emrtext;
04506 
04507       if ( emrtext.offString != 0 ) {
04508         string_size = ROUND_TO_LONG( emrtext.nChars );
04509 
04510         string_a = new CHAR[ string_size ];
04511 
04512         memset( string_a, 0, sizeof(CHAR) * string_size );
04513 
04514         CHARSTR string( string_a, string_size );
04515 
04516         ds >> string;
04517       }
04518       else
04519         string_a = 0;
04520 
04521       if ( emrtext.offDx ) {
04522         dx_i = new INT[ emrtext.nChars ];
04523 
04524         INTARRAY dx_is( dx_i, emrtext.nChars );
04525 
04526         ds >> dx_is;
04527       }
04528       else
04529         dx_i = 0;
04530     }
04535     ~EMREXTTEXTOUTA ( )
04536     {
04537       if ( string_a ) delete[] string_a;
04538       if ( dx_i ) delete[] dx_i;
04539     }
04543     bool serialize ( DATASTREAM ds )
04544     {
04545       ds << emr << rclBounds << iGraphicsMode << exScale << eyScale
04546          << emrtext << CHARSTR( string_a, string_size );
04547       if ( dx_i )
04548         ds << INTARRAY( dx_i, emrtext.nChars );
04549       return true;
04550     }
04554     int size ( void ) const { return emr.nSize; }
04560     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04561     {
04562       RECT rect;
04563       rect.left = emrtext.rcl.left;
04564       rect.top = emrtext.rcl.top;
04565       rect.right = emrtext.rcl.right;
04566       rect.bottom = emrtext.rcl.bottom;
04567 
04568       ExtTextOutA( dc, emrtext.ptlReference.x, emrtext.ptlReference.y,
04569                    emrtext.fOptions, &rect, string_a, emrtext.nChars,
04570                    dx_i );
04571     }
04572 #ifdef ENABLE_EDITING
04573 
04576     void edit ( void ) const
04577     {
04578 #if defined(__LP64__)
04579     const char* FMT0 = "unknown(%d)\n";
04580     const char* FMT1 = "\tptlReference\t: (%d,%d)\n";
04581     const char* FMT2 = "\tnChars\t\t: %d\n";
04582     const char* FMT3 = "\toffString\t: %d\n";
04583     const char* FMT4 = "\toffDx\t\t: %d\n";
04584 #else
04585     const char* FMT0 = "unknown(%ld)\n";
04586     const char* FMT1 = "\tptlReference\t: (%ld,%ld)\n";
04587     const char* FMT2 = "\tnChars\t\t: %ld\n";
04588     const char* FMT3 = "\toffString\t: %ld\n";
04589     const char* FMT4 = "\toffDx\t\t: %ld\n";
04590 #endif /* __x86_64__ */
04591       printf( "*EXTTEXTOUTA*\n" );
04592       edit_rectl( "rclBounds", rclBounds );
04593       printf( "\tiGraphicsMode\t: " );
04594       switch ( iGraphicsMode ) {
04595       case GM_COMPATIBLE: printf( "GM_COMPATIBLE\n" ); break;
04596       case GM_ADVANCED: printf( "GM_ADVANCED\n" ); break;
04597       default: printf( FMT0, iGraphicsMode );
04598       }
04599       printf( "\texScale\t\t: %f\n", exScale );
04600       printf( "\teyScale\t\t: %f\n", eyScale );
04601       printf( FMT1, emrtext.ptlReference.x, emrtext.ptlReference.y );
04602       printf( FMT2, emrtext.nChars );
04603       printf( FMT3, emrtext.offString );
04604       printf( "\tfOptions\t: " );
04605       if ( emrtext.fOptions == 0 )
04606         printf( "None" );
04607       else {
04608         if ( emrtext.fOptions & ETO_GRAYED ) {
04609           printf( "ETO_GRAYED" );
04610           if ( emrtext.fOptions & ~ETO_GRAYED )
04611             printf( " | " );
04612         }
04613         if ( emrtext.fOptions & ETO_OPAQUE ) {
04614           printf( "ETO_OPAQUE" );
04615           if ( emrtext.fOptions & ~(ETO_GRAYED | ETO_OPAQUE) )
04616             printf( " | " );
04617         }
04618         if ( emrtext.fOptions & ETO_CLIPPED ) {
04619           printf( "ETO_CLIPPED" );
04620           if ( emrtext.fOptions & ~(ETO_GRAYED | ETO_OPAQUE | ETO_CLIPPED ) )
04621             printf( " | " );
04622         }
04623         if ( emrtext.fOptions & ETO_GLYPH_INDEX ) {
04624           printf( "ETO_GLYPH_INDEX" );
04625           if ( emrtext.fOptions &
04626                ~(ETO_GRAYED | ETO_OPAQUE | ETO_CLIPPED | ETO_GLYPH_INDEX) )
04627             printf( " | " );
04628         }
04629         if ( emrtext.fOptions & ETO_RTLREADING ) {
04630           printf( "ETO_RTLREADING" );
04631           if ( emrtext.fOptions &
04632                ~(ETO_GRAYED | ETO_OPAQUE | ETO_CLIPPED | ETO_GLYPH_INDEX |
04633                  ETO_RTLREADING) )
04634             printf( " | " );
04635         }
04636         if ( emrtext.fOptions & ETO_IGNORELANGUAGE )
04637           printf( "ETO_IGNORELANGUAGE" );
04638       }
04639       printf( "\n" );
04640       edit_rectl( "rcl\t", emrtext.rcl );
04641       printf( FMT4, emrtext.offDx );
04642       printf( "\tString:\n\t\t%s\n",  string_a );
04643 
04644       if ( emrtext.offDx != 0 ) {
04645         printf( "\tOffsets:\n\t\t" );
04646         for ( unsigned int i = 0; i < emrtext.nChars; i++ )
04647           printf( "%d ", dx_i[i] );
04648         printf( "\n" );
04649       }
04650     }
04651 #endif /* ENABLE_EDITING */
04652   };
04653 
04655 
04658   class EMRSETPIXELV : public METARECORD, ::EMRSETPIXELV {
04659   public:
04665     EMRSETPIXELV ( INT x, INT y, COLORREF color )
04666     {
04667       emr.iType = EMR_SETPIXELV;
04668       emr.nSize = sizeof( ::EMRSETPIXELV );
04669       ptlPixel.x = x;
04670       ptlPixel.y = y;
04671       crColor = color;
04672     }
04677     EMRSETPIXELV ( DATASTREAM& ds )
04678     {
04679       ds >> emr >> ptlPixel >> crColor;
04680     }
04684     bool serialize ( DATASTREAM ds )
04685     {
04686       ds << emr << ptlPixel << crColor;
04687       return true;
04688     }
04692     int size ( void ) const { return emr.nSize; }
04698     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
04699     {
04700       SetPixel( dc, ptlPixel.x, ptlPixel.y, crColor );
04701     }
04702 #ifdef ENABLE_EDITING
04703 
04706     void edit ( void ) const
04707     {
04708       printf( "*SETPIXELV*\n" );
04709       edit_pointl( "ptlPixel", ptlPixel );
04710       edit_color( "crColor\t", crColor );
04711     }
04712 #endif /* ENABLE_EDITING */
04713   };
04714 
04715   class PEN;
04716   class EXTPEN;
04717   class BRUSH;
04718   class FONT;
04719   class PALETTE;
04720 
04722 
04725   class EMRCREATEPEN : public METARECORD, public ::EMRCREATEPEN
04726   {
04727   public:
04732     EMRCREATEPEN ( PEN* pen, HGDIOBJ handle );
04737     EMRCREATEPEN ( DATASTREAM& ds );
04741     bool serialize ( DATASTREAM ds )
04742     {
04743       ds << emr << ihPen << lopn;
04744       return true;
04745     }
04749     int size ( void ) const { return emr.nSize; }
04755     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
04756 #ifdef ENABLE_EDITING
04757 
04760     void edit ( void ) const
04761     {
04762 #if defined(__LP64__)
04763       const char* FMT0 = "\tihPen\t\t: 0x%x\n";
04764       const char* FMT1 = "\tlopn.lopnWidth\t: %d, %d\n";
04765 #else
04766       const char* FMT0 = "\tihPen\t\t: 0x%lx\n";
04767       const char* FMT1 = "\tlopn.lopnWidth\t: %ld, %ld\n";
04768 #endif /* __x86_64__ */
04769       printf( "*CREATEPEN*\n" );
04770       printf( FMT0, ihPen );
04771       edit_pen_style( "lopn.lopnStyle", lopn.lopnStyle );
04772       printf( FMT1, lopn.lopnWidth.x, lopn.lopnWidth.y );
04773       edit_color( "lopn.lopnColor", lopn.lopnColor );
04774     }
04775 #endif /* ENABLE_EDITING */
04776   };
04777 
04779 
04783   class EMREXTCREATEPEN : public METARECORD, public ::EMREXTCREATEPEN
04784   {
04785   public:
04790     EMREXTCREATEPEN ( EXTPEN* pen, HGDIOBJ handle );
04795     EMREXTCREATEPEN ( DATASTREAM& ds );
04799     bool serialize ( DATASTREAM ds )
04800     {
04801       ds << emr << ihPen << offBmi << cbBmi << offBits << cbBits << elp;
04802       return true;
04803     }
04807     int size ( void ) const { return emr.nSize; }
04813     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
04814 #ifdef ENABLE_EDITING
04815 
04818     void edit ( void ) const
04819     {
04820 #if defined(__LP64__)
04821       const char* FMT0 = "\tihPen\t\t\t: 0x%x\n";
04822       const char* FMT1 = "\toffBmi\t\t\t: %d\n";
04823       const char* FMT2 = "\tcbBmi\t\t\t: %d\n";
04824       const char* FMT3 = "\toffBits\t\t\t: %d\n";
04825       const char* FMT4 = "\tcbBits\t\t\t: %d\n";
04826       const char* FMT5 = "\telp.elpWidth\t\t: %d\n";
04827       const char* FMT6 = "\telp.elpNumEntries\t: %d\n";
04828 #else
04829       const char* FMT0 = "\tihPen\t\t\t: 0x%lx\n";
04830       const char* FMT1 = "\toffBmi\t\t\t: %ld\n";
04831       const char* FMT2 = "\tcbBmi\t\t\t: %ld\n";
04832       const char* FMT3 = "\toffBits\t\t\t: %ld\n";
04833       const char* FMT4 = "\tcbBits\t\t\t: %ld\n";
04834       const char* FMT5 = "\telp.elpWidth\t\t: %ld\n";
04835       const char* FMT6 = "\telp.elpNumEntries\t: %ld\n";
04836 #endif /* __x86_64__ */
04837       printf( "*EXTCREATEPEN*\n" );
04838       printf( FMT0, ihPen );
04839       printf( FMT1,  offBmi );
04840       printf( FMT2, cbBmi );
04841       printf( FMT3, offBits );
04842       printf( FMT4, cbBits );
04843       edit_pen_style( "elp.elpPenStyle\t", elp.elpPenStyle );
04844       printf( FMT5, elp.elpWidth );
04845       edit_brush_style( "elp.elpBrushStyle", elp.elpBrushStyle );
04846       edit_color( "elp.elpColor\t", elp.elpColor );
04847       edit_brush_hatch( "elp.elpHatch\t", elp.elpHatch );
04848       printf( FMT6, elp.elpNumEntries );
04849     }
04850 #endif /* ENABLE_EDITING */
04851   };
04852 
04854 
04857   class EMRCREATEBRUSHINDIRECT : public METARECORD, public ::EMRCREATEBRUSHINDIRECT
04858   {
04859   public:
04864     EMRCREATEBRUSHINDIRECT ( BRUSH* brush, HGDIOBJ handle );
04869     EMRCREATEBRUSHINDIRECT ( DATASTREAM& ds );
04873     bool serialize ( DATASTREAM ds )
04874     {
04875       ds << emr << ihBrush << lb;
04876       return true;
04877     }
04881     int size ( void ) const { return emr.nSize; }
04887     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
04888 #ifdef ENABLE_EDITING
04889 
04892     void edit ( void ) const
04893     {
04894 #if defined(__LP64__)
04895       const char* FMT = "\tihBrush\t\t: 0x%x\n";
04896 #else
04897       const char* FMT = "\tihBrush\t\t: 0x%lx\n";
04898 #endif /* __x86_64__ */
04899       printf( "*CREATEBRUSHINDIRECT*\n" );
04900       printf( FMT, ihBrush );
04901       edit_brush_style( "lb.lbStyle", lb.lbStyle );
04902       edit_color( "lb.lbColor", lb.lbColor );
04903       edit_brush_hatch( "lb.lbHatch", lb.lbHatch );
04904     }
04905 #endif /* ENABLE_EDITING */
04906   };
04907 
04909 
04912   class EMREXTCREATEFONTINDIRECTW : public METARECORD, public ::EMREXTCREATEFONTINDIRECTW
04913   {
04914   public:
04919     EMREXTCREATEFONTINDIRECTW ( FONT* font, HGDIOBJ handle );
04924     EMREXTCREATEFONTINDIRECTW ( DATASTREAM& ds );
04928     bool serialize ( DATASTREAM ds )
04929     {
04930       // Since EMF records have to be multiples of 4 bytes, this
04931       // should perhaps be a general thing, but we know it's currently
04932       // only a problem for this structure.
04933 
04934       ds << emr << ihFont << elfw << PADDING( 2 );
04935 
04936       return true;
04937     }
04941     int size ( void ) const { return emr.nSize; }
04947     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
04948 #ifdef ENABLE_EDITING
04949 
04952     void edit ( void ) const
04953     {
04954 #if defined(__LP64__)
04955       const char* FMT0 = "\tihFont\t\t\t: %d\n";
04956       const char* FMT1 = "\tlfHeight\t\t: %d\n";
04957       const char* FMT2 = "\tlfWidth\t\t\t: %d\n";
04958       const char* FMT3 = "\tlfEscapement\t\t: %d\n";
04959       const char* FMT4 = "\tlfOrientation\t\t: %d\n";
04960       const char* FMT5 = "\telfVersion\t\t: %d\n";
04961       const char* FMT6 = "\telfStyleSize\t\t: %d\n";
04962       const char* FMT7 = "\telfMatch\t\t: %d\n";
04963       const char* FMT8 = "\telfCulture\t\t: %d\n";
04964 #else
04965       const char* FMT0 = "\tihFont\t\t\t: %ld\n";
04966       const char* FMT1 = "\tlfHeight\t\t: %ld\n";
04967       const char* FMT2 = "\tlfWidth\t\t\t: %ld\n";
04968       const char* FMT3 = "\tlfEscapement\t\t: %ld\n";
04969       const char* FMT4 = "\tlfOrientation\t\t: %ld\n";
04970       const char* FMT5 = "\telfVersion\t\t: %ld\n";
04971       const char* FMT6 = "\telfStyleSize\t\t: %ld\n";
04972       const char* FMT7 = "\telfMatch\t\t: %ld\n";
04973       const char* FMT8 = "\telfCulture\t\t: %ld\n";
04974 #endif /* __x86_64__ */
04975       printf( "*EXTCREATEFONTINDIRECTW*\n" );
04976       printf( FMT0, ihFont );
04977       printf( FMT1, elfw.elfLogFont.lfHeight );
04978       printf( FMT2, elfw.elfLogFont.lfWidth );
04979       printf( FMT3, elfw.elfLogFont.lfEscapement );
04980       printf( FMT4, elfw.elfLogFont.lfOrientation );
04981       printf( "\tlfWeight\t\t: " );
04982       switch ( elfw.elfLogFont.lfWeight ) {
04983       case FW_DONTCARE: printf( "FW_DONTCARE\n" ); break;
04984       case FW_THIN: printf( "FW_THIN\n" ); break;
04985       case FW_EXTRALIGHT: printf( "FW_EXTRALIGHT\n" ); break;
04986       case FW_LIGHT: printf( "FW_LIGHT\n" ); break;
04987       case FW_NORMAL: printf( "FW_NORMAL\n" ); break;
04988       case FW_MEDIUM: printf( "FW_MEDIUM\n" ); break;
04989       case FW_SEMIBOLD: printf( "FW_SEMIBOLD\n" ); break;
04990       case FW_BOLD: printf( "FW_BOLD\n" ); break;
04991       case FW_EXTRABOLD: printf( "FW_EXTRABOLD\n" ); break;
04992       case FW_BLACK: printf( "FW_BLACK\n" ); break;
04993       }
04994       printf( "\tlfItalic\t\t: %d\n", elfw.elfLogFont.lfItalic );
04995       printf( "\tlfUnderline\t\t: %d\n", elfw.elfLogFont.lfUnderline );
04996       printf( "\tlfStrikeOut\t\t: %d\n", elfw.elfLogFont.lfStrikeOut );
04997       printf( "\tlfCharSet\t\t: %d\n", elfw.elfLogFont.lfCharSet );
04998       printf( "\tlfOutPrecision\t\t: %d\n", elfw.elfLogFont.lfOutPrecision );
04999       printf( "\tlfClipPrecision\t\t: %d\n", elfw.elfLogFont.lfClipPrecision );
05000       printf( "\tlfQuality\t\t: %d\n", elfw.elfLogFont.lfQuality );
05001       printf( "\tlfPitchAndFamily\t: %d\n", elfw.elfLogFont.lfPitchAndFamily );
05002       int i = 0;
05003       printf( "\tlfFaceName\t\t: '" );
05004       while ( elfw.elfLogFont.lfFaceName[i] != 0 && i < LF_FACESIZE ) {
05005         putchar( elfw.elfLogFont.lfFaceName[i] );
05006         i++;
05007       }
05008       puts( "'" );
05009 
05010       i = 0;
05011       printf( "\telfFullName\t\t: '" );
05012       while ( elfw.elfFullName[i] != 0 && i < LF_FULLFACESIZE ) {
05013         putchar( elfw.elfFullName[i] );
05014         i++;
05015       }
05016       puts( "'" );
05017 
05018       i = 0;
05019       printf( "\telfStyle\t\t: '" );
05020       while ( elfw.elfStyle[i] != 0 && i < LF_FACESIZE ) {
05021         putchar( elfw.elfStyle[i] );
05022         i++;
05023       }
05024       puts( "'" );
05025 
05026       printf( FMT5, elfw.elfVersion );
05027       printf( FMT6, elfw.elfStyleSize );
05028       printf( FMT7, elfw.elfMatch );
05029       printf( "\telfVendorId\t\t: '%s'\n", elfw.elfVendorId );
05030       printf( FMT8, elfw.elfCulture );
05031       printf( "\telfPanose\t\t:\n" );
05032       printf( "\t\tbFamilyType\t\t: %d\n", elfw.elfPanose.bFamilyType );
05033       printf( "\t\tbSerifStyle\t\t: %d\n", elfw.elfPanose.bSerifStyle );
05034       printf( "\t\tbWeight\t\t\t: %d\n", elfw.elfPanose.bWeight );
05035       printf( "\t\tbProportion\t\t: %d\n", elfw.elfPanose.bProportion );
05036       printf( "\t\tbContrast\t\t: %d\n", elfw.elfPanose.bContrast );
05037       printf( "\t\tbStrokeVariation\t: %d\n", elfw.elfPanose.bStrokeVariation );
05038       printf( "\t\tbArmStyle\t\t: %d\n", elfw.elfPanose.bArmStyle );
05039       printf( "\t\tbLetterform\t\t: %d\n", elfw.elfPanose.bLetterform );
05040       printf( "\t\tbMidline\t\t: %d\n", elfw.elfPanose.bMidline );
05041       printf( "\t\tbXHeight\t\t: %d\n", elfw.elfPanose.bXHeight );
05042     }
05043 #endif /* ENABLE_EDITING */
05044   };
05045 
05047 
05050   class EMRCREATEPALETTE : public METARECORD, public ::EMRCREATEPALETTE
05051   {
05052   public:
05057     EMRCREATEPALETTE ( PALETTE* palette, HGDIOBJ handle );
05062     EMRCREATEPALETTE ( DATASTREAM& ds );
05066     bool serialize ( DATASTREAM ds )
05067     {
05068       ds << emr << ihPal << lgpl;
05069       return true;
05070     }
05074     int size ( void ) const { return emr.nSize; }
05080     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
05081 #ifdef ENABLE_EDITING
05082 
05085     void edit ( void ) const
05086     {
05087       printf( "*CREATEPALETTE* (not really handled by libEMF)\n" );
05088     }
05089 #endif /* ENABLE_EDITING */
05090   };
05091 
05093 
05096   class EMRFILLPATH : public METARECORD, ::EMRFILLPATH {
05097   public:
05102     EMRFILLPATH ( const RECTL* bounds )
05103     {
05104       emr.iType = EMR_FILLPATH;
05105       emr.nSize = sizeof( ::EMRFILLPATH );
05106       rclBounds = *bounds;
05107     }
05112     EMRFILLPATH ( DATASTREAM& ds )
05113     {
05114       ds >> emr >> rclBounds;
05115     }
05119     bool serialize ( DATASTREAM ds )
05120     {
05121       ds << emr << rclBounds;
05122       return true;
05123     }
05127     int size ( void ) const { return emr.nSize; }
05133     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05134     {
05135       FillPath( dc );
05136     }
05137 #ifdef ENABLE_EDITING
05138 
05141     void edit ( void ) const
05142     {
05143       printf( "*FILLPATH*\n" );
05144       edit_rectl( "rclBounds", rclBounds );
05145     }
05146 #endif /* ENABLE_EDITING */
05147   };
05149 
05152   class EMRSTROKEPATH : public METARECORD, ::EMRSTROKEPATH {
05153   public:
05158     EMRSTROKEPATH ( const RECTL* bounds )
05159     {
05160       emr.iType = EMR_STROKEPATH;
05161       emr.nSize = sizeof( ::EMRSTROKEPATH );
05162       rclBounds = *bounds;
05163     }
05168     EMRSTROKEPATH ( DATASTREAM& ds )
05169     {
05170       ds >> emr >> rclBounds;
05171     }
05175     bool serialize ( DATASTREAM ds )
05176     {
05177       ds << emr << rclBounds;
05178       return true;
05179     }
05183     int size ( void ) const { return emr.nSize; }
05189     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05190     {
05191       StrokePath( dc );
05192     }
05193 #ifdef ENABLE_EDITING
05194 
05197     void edit ( void ) const
05198     {
05199       printf( "*STROKEPATH*\n" );
05200       edit_rectl( "rclBounds", rclBounds );
05201     }
05202 #endif /* ENABLE_EDITING */
05203   };
05205 
05208   class EMRSTROKEANDFILLPATH : public METARECORD, ::EMRSTROKEANDFILLPATH {
05209   public:
05214     EMRSTROKEANDFILLPATH ( const RECTL* bounds )
05215     {
05216       emr.iType = EMR_STROKEANDFILLPATH;
05217       emr.nSize = sizeof( ::EMRSTROKEANDFILLPATH );
05218       rclBounds = *bounds;
05219     }
05224     EMRSTROKEANDFILLPATH ( DATASTREAM& ds )
05225     {
05226       ds >> emr >> rclBounds;
05227     }
05231     bool serialize ( DATASTREAM ds )
05232     {
05233       ds << emr << rclBounds;
05234       return true;
05235     }
05239     int size ( void ) const { return emr.nSize; }
05245     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05246     {
05247       StrokeAndFillPath( dc );
05248     }
05249 #ifdef ENABLE_EDITING
05250 
05253     void edit ( void ) const
05254     {
05255       printf( "*STROKEANDFILLPATH*\n" );
05256       edit_rectl( "rclBounds", rclBounds );
05257     }
05258 #endif /* ENABLE_EDITING */
05259   };
05261 
05264   class EMRBEGINPATH : public METARECORD, ::EMRBEGINPATH {
05265   public:
05269     EMRBEGINPATH ( void )
05270     {
05271       emr.iType = EMR_BEGINPATH;
05272       emr.nSize = sizeof( ::EMRBEGINPATH );
05273     }
05278     EMRBEGINPATH ( DATASTREAM& ds )
05279     {
05280       ds >> emr;
05281     }
05285     bool serialize ( DATASTREAM ds )
05286     {
05287       ds << emr;
05288       return true;
05289     }
05293     int size ( void ) const { return emr.nSize; }
05299     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05300     {
05301       BeginPath( dc );
05302     }
05303 #ifdef ENABLE_EDITING
05304 
05307     void edit ( void ) const
05308     {
05309       printf( "*BEGINPATH*\n" );
05310     }
05311 #endif /* ENABLE_EDITING */
05312   };
05314 
05317   class EMRENDPATH : public METARECORD, ::EMRENDPATH {
05318   public:
05322     EMRENDPATH ( void )
05323     {
05324       emr.iType = EMR_ENDPATH;
05325       emr.nSize = sizeof( ::EMRENDPATH );
05326     }
05331     EMRENDPATH ( DATASTREAM& ds )
05332     {
05333       ds >> emr;
05334     }
05338     bool serialize ( DATASTREAM ds )
05339     {
05340       ds << emr;
05341       return true;
05342     }
05346     int size ( void ) const { return emr.nSize; }
05352     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05353     {
05354       EndPath( dc );
05355     }
05356 #ifdef ENABLE_EDITING
05357 
05360     void edit ( void ) const
05361     {
05362       printf( "*ENDPATH*\n" );
05363     }
05364 #endif /* ENABLE_EDITING */
05365   };
05367 
05370   class EMRCLOSEFIGURE : public METARECORD, ::EMRCLOSEFIGURE {
05371   public:
05375     EMRCLOSEFIGURE ( void )
05376     {
05377       emr.iType = EMR_CLOSEFIGURE;
05378       emr.nSize = sizeof( ::EMRCLOSEFIGURE );
05379     }
05384     EMRCLOSEFIGURE ( DATASTREAM& ds )
05385     {
05386       ds >> emr;
05387     }
05391     bool serialize ( DATASTREAM ds )
05392     {
05393       ds << emr;
05394       return true;
05395     }
05399     int size ( void ) const { return emr.nSize; }
05405     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05406     {
05407       CloseFigure( dc );
05408     }
05409 #ifdef ENABLE_EDITING
05410 
05413     void edit ( void ) const
05414     {
05415       printf( "*CLOSEFIGURE*\n" );
05416     }
05417 #endif /* ENABLE_EDITING */
05418   };
05420 
05424   class EMRSAVEDC : public METARECORD, ::EMRSAVEDC {
05425   public:
05429     EMRSAVEDC ( void )
05430     {
05431       emr.iType = EMR_SAVEDC;
05432       emr.nSize = sizeof( ::EMRSAVEDC );
05433     }
05438     EMRSAVEDC ( DATASTREAM& ds )
05439     {
05440       ds >> emr;
05441     }
05445     bool serialize ( DATASTREAM ds )
05446     {
05447       ds << emr;
05448       return true;
05449     }
05453     int size ( void ) const { return emr.nSize; }
05459     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05460     {
05461       SaveDC( dc );
05462     }
05463 #ifdef ENABLE_EDITING
05464 
05467     void edit ( void ) const
05468     {
05469       printf( "*SAVEDC*\n" );
05470     }
05471 #endif /* ENABLE_EDITING */
05472   };
05474 
05477   class EMRRESTOREDC : public METARECORD, ::EMRRESTOREDC {
05478   public:
05482     EMRRESTOREDC ( INT n )
05483     {
05484       emr.iType = EMR_RESTOREDC;
05485       emr.nSize = sizeof( ::EMRRESTOREDC );
05486       iRelative = n;
05487     }
05492     EMRRESTOREDC ( DATASTREAM& ds )
05493     {
05494       ds >> emr >> iRelative;
05495     }
05499     bool serialize ( DATASTREAM ds )
05500     {
05501       ds << emr << iRelative;
05502       return true;
05503     }
05507     int size ( void ) const { return emr.nSize; }
05513     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05514     {
05515       RestoreDC( dc, iRelative );
05516     }
05517 #ifdef ENABLE_EDITING
05518 
05521     void edit ( void ) const
05522     {
05523 #if defined(__LP64__)
05524       const char* FMT = "\tiRelative: %d\n";
05525 #else
05526       const char* FMT = "\tiRelative: %ld\n";
05527 #endif /* __x86_64__ */
05528       printf( "*RESTOREDC*\n" );
05529       printf( FMT, iRelative );
05530     }
05531 #endif /* ENABLE_EDITING */
05532   };
05534 
05537   class EMRSETMETARGN : public METARECORD, ::EMRSETMETARGN {
05538   public:
05542     EMRSETMETARGN ( void )
05543     {
05544       emr.iType = EMR_SETMETARGN;
05545       emr.nSize = sizeof( ::EMRSETMETARGN );
05546     }
05551     EMRSETMETARGN ( DATASTREAM& ds )
05552     {
05553       ds >> emr;
05554     }
05558     bool serialize ( DATASTREAM ds )
05559     {
05560       ds << emr;
05561       return true;
05562     }
05566     int size ( void ) const { return emr.nSize; }
05572     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05573     {
05574       SetMetaRgn( dc );
05575     }
05576 #ifdef ENABLE_EDITING
05577 
05580     void edit ( void ) const
05581     {
05582       printf( "*SETMETARGN*\n" );
05583     }
05584 #endif /* ENABLE_EDITING */
05585   };
05586 
05588 
05591   class PEN : public GRAPHICSOBJECT, public LOGPEN {
05592   public:
05596     PEN ( const LOGPEN* lpen )
05597     {
05598       lopnStyle = lpen->lopnStyle;
05599       lopnWidth = lpen->lopnWidth;
05600       lopnColor = lpen->lopnColor;
05601     }
05605     OBJECTTYPE getType ( void ) const { return O_PEN; }
05612     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
05613     {
05614       contexts[dc] = emf_handle;
05615       return new EMRCREATEPEN( this, emf_handle );
05616     }
05617   };
05618 
05620 
05623   class EXTPEN : public GRAPHICSOBJECT, public EXTLOGPEN {
05624   public:
05628     EXTPEN ( const EXTLOGPEN* lpen )
05629     {
05630       elpPenStyle = lpen->elpPenStyle;
05631       elpWidth = lpen->elpWidth;
05632       elpBrushStyle = lpen->elpBrushStyle;
05633       elpColor = lpen->elpColor;
05634       elpHatch = lpen->elpHatch;
05635       elpNumEntries = 0;
05636       elpStyleEntry[0] = 0;
05637     }
05641     OBJECTTYPE getType ( void ) const { return O_EXTPEN; }
05648     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
05649     {
05650       contexts[dc] = emf_handle;
05651       return new EMREXTCREATEPEN( this, emf_handle );
05652     }
05653   };
05654 
05656 
05659   class BRUSH : public GRAPHICSOBJECT, public LOGBRUSH {
05660   public:
05664     BRUSH ( const LOGBRUSH* lbrush )
05665     {
05666       lbStyle = lbrush->lbStyle;
05667       lbColor = lbrush->lbColor;
05668       lbHatch = lbrush->lbHatch;
05669     }
05673     OBJECTTYPE getType ( void ) const { return O_BRUSH; }
05680     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
05681     {
05682       contexts[dc] = emf_handle;
05683       return new EMRCREATEBRUSHINDIRECT( this, emf_handle );
05684     }
05685   };
05686 
05688 
05691   class FONT : public GRAPHICSOBJECT, public EXTLOGFONTW {
05692   public:
05696     FONT ( const LOGFONTW* lfont )
05697     {
05698       this->elfLogFont = *lfont;
05699       // There are a lot more entries in the EXTLOGFONTW structure than
05700       // the API has values for, so we invent them here
05701       memset( &elfFullName, 0, sizeof elfFullName );
05702       memset( &elfStyle, 0, sizeof elfStyle );
05703       elfVersion = ELF_VERSION;
05704       elfStyleSize = 0;
05705       elfMatch = 0;
05706       elfReserved = 0;
05707       memset( &elfVendorId, 0, sizeof elfVendorId );
05708       elfCulture = ELF_CULTURE_LATIN;
05709       memset( &elfPanose, 1, sizeof(PANOSE) );
05710     }
05714     OBJECTTYPE getType ( void ) const { return O_FONT; }
05721     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
05722     {
05723       contexts[dc] = emf_handle;
05724       return new EMREXTCREATEFONTINDIRECTW( this, emf_handle );
05725     }
05726   };
05727 
05729 
05732   class PALETTE : public GRAPHICSOBJECT, public LOGPALETTE {
05733   public:
05737     PALETTE ( const LOGPALETTE* lpalette )
05738     {
05739       (void)lpalette;
05740       palVersion = 0;
05741       palNumEntries = 0;
05742       PALETTEENTRY zero_entry = { 0, 0, 0, 0 };
05743       palPalEntry[0] = zero_entry;
05744     }
05748     OBJECTTYPE getType ( void ) const { return O_PALETTE; }
05755     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
05756     {
05757       contexts[dc] = emf_handle;
05758       return new EMRCREATEPALETTE( this, emf_handle );
05759     }
05760   };
05761 
05763 
05766   class EMRSETMITERLIMIT : public METARECORD, ::EMRSETMITERLIMIT {
05767   public:
05771     EMRSETMITERLIMIT ( FLOAT limit )
05772     {
05773       emr.iType = EMR_SETMITERLIMIT;
05774       emr.nSize = sizeof( ::EMRSETMITERLIMIT );
05775       eMiterLimit = limit;
05776     }
05781     EMRSETMITERLIMIT ( DATASTREAM& ds )
05782     {
05783        int miter_limit;
05784        ds >> emr >> miter_limit;
05785        eMiterLimit = float(miter_limit);
05786     }
05790     bool serialize ( DATASTREAM ds )
05791     {
05792        ds << emr << (int)eMiterLimit;
05793        return true;
05794     }
05798     int size ( void ) const { return emr.nSize; }
05804     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
05805     {
05806        SetMiterLimit( dc, eMiterLimit, 0 );
05807     }
05808 #ifdef ENABLE_EDITING
05809 
05812     void edit ( void ) const
05813     {
05814       printf( "*SETMITERLIMIT*\n" );
05815       printf( "\teMiterLimit\t: %f\n", eMiterLimit );
05816     }
05817 #endif /* ENABLE_EDITING */
05818   };
05819 
05821 
05827   class METAFILEDEVICECONTEXT : public OBJECT {
05835     void init ( const RECT* size, LPCWSTR description_w ) {
05836 
05837       // Evidently, metafile handles are numbered from 1, so don't
05838       // ever use 0.
05839 
05840       handles.push_back( true );
05841 
05842       // Keep some of our graphics state in a header record
05843 
05844       header = new ENHMETAHEADER ( description_w );
05845       records.push_back( header );
05846 
05847       // Compute the size and position of the metafile on the "page"
05848 
05849       if ( size ) {
05850         update_frame = false;
05851 
05852         header->rclFrame.left = size->left;
05853         header->rclFrame.top = size->top;
05854         header->rclFrame.right = size->right;
05855         header->rclFrame.bottom = size->bottom;
05856 
05857         header->rclBounds.left =
05858           size->left * header->szlDevice.cx / ( header->szlMillimeters.cx * 100 );
05859         header->rclBounds.top =
05860           size->top * header->szlDevice.cy / ( header->szlMillimeters.cy * 100 );
05861         header->rclBounds.right =
05862           size->right * header->szlDevice.cx / ( header->szlMillimeters.cx * 100 );
05863         header->rclBounds.bottom =
05864           size->bottom * header->szlDevice.cy / ( header->szlMillimeters.cy * 100 );
05865       }
05866       else {
05867         update_frame = true;
05868 
05869         header->rclBounds.left = -10;
05870         header->rclBounds.top = -10;
05871         header->rclBounds.right = 10;
05872         header->rclBounds.bottom = 10;
05873 
05874         header->rclFrame.left = (LONG)floor( (float)header->rclBounds.left *
05875           header->szlMillimeters.cx * 100 / header->szlDevice.cx );
05876         header->rclFrame.top = (LONG)floor( (float)header->rclBounds.top *
05877           header->szlMillimeters.cy * 100 / header->szlDevice.cy );
05878         header->rclFrame.right = (LONG)ceil( (float)header->rclBounds.right *
05879           header->szlMillimeters.cx * 100 / header->szlDevice.cx );
05880         header->rclFrame.bottom = (LONG)ceil( (float)header->rclBounds.bottom *
05881           header->szlMillimeters.cy * 100 / header->szlDevice.cy );
05882       }
05883 
05884       // Some default graphics state (are they really, though?)
05885 
05886       SIZEL default_resolution = { RESOLUTION, RESOLUTION };
05887       resolution = default_resolution;
05888       SIZEL default_viewport_ext = { 1, 1 };
05889       viewport_ext = default_viewport_ext;
05890       POINT default_viewport_org = { 0, 0 };
05891       viewport_org = default_viewport_org;
05892       SIZEL default_window_ext = { 1, 1 };
05893       window_ext = default_window_ext;
05894       POINT default_window_org = { 0, 0 };
05895       window_org = default_window_org;
05896 
05897       min_device_point = viewport_org;
05898       max_device_point = viewport_org;
05899 
05900       pen = (PEN*)globalObjects.find( BLACK_PEN | ENHMETA_STOCK_OBJECT );
05901       brush = (BRUSH*)globalObjects.find( BLACK_BRUSH | ENHMETA_STOCK_OBJECT );
05902       font = (FONT*)globalObjects.find( DEVICE_DEFAULT_FONT | ENHMETA_STOCK_OBJECT);
05903       palette = (PALETTE*)globalObjects.find( DEFAULT_PALETTE|ENHMETA_STOCK_OBJECT);
05904 
05905       text_alignment = TA_BASELINE;
05906       text_color = RGB(0,0,0);
05907       bk_color = RGB(0xff,0xff,0xff);
05908       bk_mode = OPAQUE;
05909       polyfill_mode = ALTERNATE;
05910       map_mode = MM_TEXT;
05911       miter_limit = 10.f;
05912 
05913       handle = globalObjects.add( this );
05914     }
05915 
05916   public:
05920     ::FILE* fp;
05925     DATASTREAM ds;
05929     ENHMETAHEADER* header;
05933     std::vector< EMF::METARECORD* > records;
05934 
05935     // Keep a small set of graphics state information
05936     SIZEL resolution;           
05937     SIZEL viewport_ext;         
05938     POINT viewport_org;         
05939     SIZEL window_ext;           
05940     POINT window_org;           
05941     bool update_frame;          
05942     POINT min_device_point;     
05943     POINT max_device_point;     
05944     POINT point;                
05945     PEN* pen;                   
05946     BRUSH* brush;               
05947     FONT* font;                 
05948     PALETTE* palette;           
05949     UINT text_alignment;        
05950     COLORREF text_color;        
05951     COLORREF bk_color;          
05952     INT bk_mode;                
05953     INT polyfill_mode;          
05954     INT map_mode;               
05955     FLOAT miter_limit;          
05956 
05962     std::vector< bool > handles;
05963 
05969     std::map< HGDIOBJ, HGDIOBJ > emf_handles;
05970 
05981       METAFILEDEVICECONTEXT ( FILE* fp_, const RECT* size,
05982                               LPCWSTR description_w )
05983         : fp(fp_), ds( fp_ )
05984     {
05985           init( size, description_w );
05986     }
05991     virtual ~METAFILEDEVICECONTEXT ( )
05992     {
05993       // Purge all the metarecords (if there are any) {this include the
05994       // header record, too}
05995       if ( records.size() > 0 )
05996         deleteMetafile();
05997     }
06001     OBJECTTYPE getType ( void ) const { return O_METAFILEDEVICECONTEXT; }
06006     DWORD nextHandle ( void )
06007     {
06008       for ( unsigned int i = 1; i < handles.size(); i++ ) {
06009         if ( !handles[i] ) {
06010           handles[i] = true;
06011           return i;
06012         }
06013       }
06014       handles.push_back( true );
06015       // Well, it appears that even StockObject handles count for something.
06016       // Not sure what the right value here is, then.
06017       header->nHandles = handles.size();
06018       return handles.size()-1;
06019     }
06023     void clearHandle ( DWORD handle )
06024     {
06025       handles[handle] = false;
06026     }
06032     void appendRecord ( METARECORD* record )
06033     {
06034       records.push_back( record );
06035 
06036       header->nBytes += record->size();
06037       header->nRecords++;
06038     }
06044     void appendHandle ( METARECORD* record )
06045     {
06046       records.push_back( record );
06047 
06048       header->nBytes += record->size();
06049       header->nRecords++;
06050     }
06055     void deleteMetafile ( void )
06056     {
06057       for ( std::vector<METARECORD*>::const_iterator r = records.begin();
06058             r != records.end();
06059             r++ ) {
06060         delete *r;
06061       }
06062       records.clear();
06063     }
06068     void mergePoint ( const LONG& x, const LONG& y )
06069     {
06070       POINT p;
06071       p.x = x;
06072       p.y = y;
06073       mergePoint( p );
06074     }
06079     void mergePoint( const POINT& p )
06080     {
06081       POINT device_point;
06082 
06083       // *** Note, it's possible for the global transformation matrix to
06084       // affect this too. ***
06085 
06086       device_point.x = (LONG)( (float)( p.x - window_org.x ) / window_ext.cx *
06087         viewport_ext.cx + viewport_org.x );
06088 
06089       device_point.y = (LONG)( (float)( p.y - window_org.y ) / window_ext.cy *
06090         viewport_ext.cy + viewport_org.y );
06091 
06092       // If the user didn't specify a bounding rectangle in the constructor,
06093       // compute one from this data, too.
06094       if ( device_point.x < min_device_point.x ) {
06095         min_device_point.x = device_point.x;
06096         if ( update_frame ) {
06097           header->rclBounds.left = min_device_point.x - 10;
06098           header->rclFrame.left = (LONG)floor( (float)header->rclBounds.left *
06099             header->szlMillimeters.cx * 100 / header->szlDevice.cx );
06100         }
06101       }
06102       else if ( device_point.x > max_device_point.x ) {
06103         max_device_point.x = device_point.x;
06104         if ( update_frame ) {
06105           header->rclBounds.right = max_device_point.x + 10;
06106           header->rclFrame.right = (LONG)ceil( (float)header->rclBounds.right *
06107             header->szlMillimeters.cx * 100 / header->szlDevice.cx );
06108         }
06109       }
06110 
06111       if ( device_point.y < min_device_point.y ) {
06112         min_device_point.y = device_point.y;
06113         if ( update_frame ) {
06114           header->rclBounds.top = min_device_point.y - 10;
06115           header->rclFrame.top = (LONG)floor( (float)header->rclBounds.top *
06116             header->szlMillimeters.cy * 100 / header->szlDevice.cy );
06117         }
06118       }
06119       else if ( device_point.y > max_device_point.y ) {
06120         max_device_point.y = device_point.y;
06121         if ( update_frame ) {
06122           header->rclBounds.bottom = max_device_point.y + 10;
06123           header->rclFrame.bottom = (LONG)ceil( (float)header->rclBounds.bottom *
06124             header->szlMillimeters.cy * 100 / header->szlDevice.cy );
06125         }
06126       }
06127     }
06128   };
06129 
06130 } // close EMF namespace
06131 
06132 #endif /* _LIBEMF_H */