Main Page   Class Hierarchy   Compound List   File List   Compound Members  

libemf.h

00001 /* -*- c++ -*-
00002  * EMF: A library for generating ECMA-234 Enhanced Metafiles
00003  * Copyright (C) 2002 lignum Computing, Inc. <libemf@lignumcomputing.com>
00004  * $Id: libemf.h,v 1.6 2002/01/28 18:06:45 allen Exp $
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 #ifndef _LIBEMF_H
00022 #define _LIBEMF_H 1
00023 
00024 #include <cmath>
00025 #include <vector>
00026 #include <map>
00027 #include <functional>
00028 #include <algorithm>
00029 
00030 #include <config.h>
00031 #include <emf.h>
00032 
00033 #include <wine/w16.h>
00034 
00035 namespace EMF {
00040   const int XMAX_PIXELS = 1024; /*(INT_MAX)*/
00045   const int YMAX_PIXELS = 768; /*(INT_MAX)*/
00051   const int XMAX_MM = 320;
00057   const int YMAX_MM = 240;
00061   const int RESOLUTION = 96;
00065   static inline int ROUND_TO_LONG ( int n ) { return ((n+3)/4)*4; }
00066 
00068 
00073   struct WCHARSTR {
00074     WCHAR *const string_;       
00075     const int length_;          
00076 
00081     WCHARSTR ( WCHAR *const string, const int length )
00082       : string_( string ), length_( length ) {}
00083   };
00084 
00086 
00091   struct CHARSTR {
00092     CHAR *const string_;        
00093     const int length_;          
00094 
00099     CHARSTR ( CHAR *const string, const int length )
00100       : string_( string ), length_( length ) {}
00101   };
00102 
00104 
00108   struct BYTEARRAY {
00109     BYTE *const array_;         
00110     const int n_;               
00111 
00116     BYTEARRAY ( BYTE *const array, const int n )
00117       : array_( array ), n_( n ) {}
00118   };
00119 
00121 
00124   struct POINTLARRAY {
00125     POINTL *const points_;      
00126     const DWORD n_;             
00127 
00132     POINTLARRAY ( POINTL *const points, const DWORD n )
00133       : points_( points ), n_( n ) {}
00134   };
00135 
00137 
00140   struct POINT16ARRAY {
00141     POINT16 *const points_;     
00142     const DWORD n_;             
00143 
00148     POINT16ARRAY ( POINT16 *const points, const DWORD n )
00149       : points_( points ), n_( n ) {}
00150   };
00151 
00153 
00156   struct INTARRAY {
00157     INT *const ints_;           
00158     const DWORD n_;             
00159 
00164     INTARRAY ( INT *const ints, const DWORD n )
00165       : ints_( ints ), n_( n ) {}
00166   };
00167 
00169 
00172   struct DWORDARRAY {
00173     DWORD *const dwords_;       
00174     const DWORD n_;             
00175 
00180     DWORDARRAY ( DWORD *const dwords, const DWORD n )
00181       : dwords_( dwords ), n_( n ) {}
00182   };
00183 
00185 
00188   struct PADDING {
00189     static const char padding_[4]; 
00190     const int size_;            
00191 
00195     PADDING ( const int size ) : size_( size ) {}
00196   };
00197   
00199 
00206   class DATASTREAM {
00207     bool swap_;
00208     ::FILE* fp_;
00209 
00210     static bool bigEndian ( void );
00211   public:
00217     DATASTREAM ( ::FILE* fp = 0 ) : swap_( bigEndian() ), fp_( fp ) {}
00222     void setStream ( ::FILE* fp ) { fp_ = fp; }
00227     DATASTREAM& operator<< ( const BYTE& byte )
00228     {
00229       fwrite( &byte, sizeof(BYTE), 1, fp_ );
00230       return *this;
00231     }
00236     DATASTREAM& operator>> ( BYTE& byte )
00237     {
00238       fread( &byte, sizeof(BYTE), 1, fp_ );
00239       return *this;
00240     }
00245     DATASTREAM& operator<< ( const WORD& word )
00246     {
00247       if ( swap_ ) {
00248         unsigned char const * p = (unsigned char const*)&word;
00249         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00250         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00251       }
00252       else
00253         fwrite( &word, sizeof(WORD), 1, fp_ );
00254       return *this;
00255     }
00260     DATASTREAM& operator>> ( WORD& word )
00261     {
00262       if ( swap_ ) {
00263         unsigned char* p = (unsigned char*)&word;
00264         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00265         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00266       }
00267       else
00268         fread( &word, sizeof(WORD), 1, fp_ );
00269       return *this;
00270     }
00275     DATASTREAM& operator<< ( const INT16& word )
00276     {
00277       if ( swap_ ) {
00278         unsigned char const * p = (unsigned char const*)&word;
00279         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00280         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00281       }
00282       else
00283         fwrite( &word, sizeof(INT16), 1, fp_ );
00284       return *this;
00285     }
00290     DATASTREAM& operator>> ( INT16& word )
00291     {
00292       if ( swap_ ) {
00293         unsigned char* p = (unsigned char*)&word;
00294         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00295         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00296       }
00297       else
00298         fread( &word, sizeof(INT16), 1, fp_ );
00299       return *this;
00300     }
00305     DATASTREAM& operator<< ( const DWORD& dword )
00306     {
00307       if ( swap_ ) {
00308         unsigned char const* p = (unsigned char const*)&dword;
00309         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00310         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00311         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00312         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00313       }
00314       else
00315         fwrite( &dword, sizeof(DWORD), 1, fp_ );
00316       return *this;
00317     }
00322     DATASTREAM& operator>> ( DWORD& dword )
00323     {
00324       if ( swap_ ) {
00325         unsigned char* p = (unsigned char*)&dword;
00326         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00327         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00328         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00329         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00330       }
00331       else
00332         fread( &dword, sizeof(DWORD), 1, fp_ );
00333       return *this;
00334     }
00339     DATASTREAM& operator<< ( const LONG& long_ )
00340     {
00341       if ( swap_ ) {
00342         unsigned char const* p = (unsigned char const*)&long_;
00343         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00344         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00345         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00346         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00347       }
00348       else
00349         fwrite( &long_, sizeof(LONG), 1, fp_ );
00350       return *this;
00351     }
00356     DATASTREAM& operator>> ( LONG& long_ )
00357     {
00358       if ( swap_ ) {
00359         unsigned char* p = (unsigned char*)&long_;
00360         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00361         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00362         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00363         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00364       }
00365       else
00366         fread( &long_, sizeof(LONG), 1, fp_ );
00367       return *this;
00368     }
00373     DATASTREAM& operator<< ( const INT& int_ )
00374     {
00375       if ( swap_ ) {
00376         unsigned char const* p = (unsigned char const*)&int_;
00377         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00378         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00379         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00380         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00381       }
00382       else
00383         fwrite( &int_, sizeof(INT), 1, fp_ );
00384       return *this;
00385     }
00390     DATASTREAM& operator>> ( INT& int_ )
00391     {
00392       if ( swap_ ) {
00393         unsigned char* p = (unsigned char*)&int_;
00394         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00395         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00396         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00397         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00398       }
00399       else
00400         fread( &int_, sizeof(INT), 1, fp_ );
00401       return *this;
00402     }
00407     DATASTREAM& operator<< ( const UINT& uint )
00408     {
00409       if ( swap_ ) {
00410         unsigned char const* p = (unsigned char const*)&uint;
00411         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00412         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00413         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00414         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00415       }
00416       else
00417         fwrite( &uint, sizeof(UINT), 1, fp_ );
00418       return *this;
00419     }
00424     DATASTREAM& operator>> ( UINT& uint )
00425     {
00426       if ( swap_ ) {
00427         unsigned char* p = (unsigned char*)&uint;
00428         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00429         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00430         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00431         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00432       }
00433       else
00434         fread( &uint, sizeof(UINT), 1, fp_ );
00435       return *this;
00436     }
00441     DATASTREAM& operator<< ( const FLOAT& float_ )
00442     {
00443       if ( swap_ ) {
00444         unsigned char const* p = (unsigned char const*)&float_;
00445         fwrite( &p[3], sizeof(unsigned char), 1, fp_ );
00446         fwrite( &p[2], sizeof(unsigned char), 1, fp_ );
00447         fwrite( &p[1], sizeof(unsigned char), 1, fp_ );
00448         fwrite( &p[0], sizeof(unsigned char), 1, fp_ );
00449       }
00450       else
00451         fwrite( &float_, sizeof(FLOAT), 1, fp_ );
00452       return *this;
00453     }
00458     DATASTREAM& operator>> ( FLOAT& float_ )
00459     {
00460       if ( swap_ ) {
00461         unsigned char* p = (unsigned char*)&float_;
00462         fread( &p[3], sizeof(unsigned char), 1, fp_ );
00463         fread( &p[2], sizeof(unsigned char), 1, fp_ );
00464         fread( &p[1], sizeof(unsigned char), 1, fp_ );
00465         fread( &p[0], sizeof(unsigned char), 1, fp_ );
00466       }
00467       else
00468         fread( &float_, sizeof(FLOAT), 1, fp_ );
00469       return *this;
00470     }
00475     DATASTREAM& operator<< ( const PADDING& padding )
00476     {
00477       if ( padding.size_ != 0 )
00478         fwrite( &padding.padding_, sizeof(CHAR), padding.size_, fp_ );
00479       return *this;
00480     }
00485     DATASTREAM& operator<< ( const RECTL& rectl )
00486     {
00487       *this << rectl.left << rectl.top << rectl.right << rectl.bottom;
00488       return *this;
00489     }
00494     DATASTREAM& operator>> ( RECTL& rectl )
00495     {
00496       *this >> rectl.left >> rectl.top >> rectl.right >> rectl.bottom;
00497       return *this;
00498     }
00503     DATASTREAM& operator<< ( const SIZEL& sizel )
00504     {
00505       *this << sizel.cx << sizel.cy;
00506       return *this;
00507     }
00512     DATASTREAM& operator>> ( SIZEL& sizel )
00513     {
00514       *this >> sizel.cx >> sizel.cy;
00515       return *this;
00516     }
00521     DATASTREAM& operator<< ( const WCHARSTR& wcharstr )
00522     {
00523       for ( int i = 0; i < wcharstr.length_; i++ )
00524         *this << wcharstr.string_[i];
00525       return *this;
00526     }
00531     DATASTREAM& operator>> ( WCHARSTR& wcharstr )
00532     {
00533       for ( int i = 0; i < wcharstr.length_; i++ )
00534         *this >> wcharstr.string_[i];
00535       return *this;
00536     }
00541     DATASTREAM& operator<< ( const CHARSTR& charstr )
00542     {
00543       fwrite( charstr.string_, sizeof(CHAR), charstr.length_, fp_ );
00544       return *this;
00545     }
00550     DATASTREAM& operator>> ( CHARSTR& charstr )
00551     {
00552       fread( charstr.string_, sizeof(CHAR), charstr.length_, fp_ );
00553       return *this;
00554     }
00559     DATASTREAM& operator<< ( const ::EMR& emr )
00560     {
00561       *this << emr.iType << emr.nSize;
00562       return *this;
00563     }
00568     DATASTREAM& operator>> ( ::EMR& emr )
00569     {
00570       *this >> emr.iType >> emr.nSize;
00571       return *this;
00572     }
00577     DATASTREAM& operator<< ( const POINT& point )
00578     {
00579       *this << point.x << point.y;
00580       return *this;
00581     }
00586     DATASTREAM& operator>> ( POINT& point )
00587     {
00588       *this >> point.x >> point.y;
00589       return *this;
00590     }
00595     DATASTREAM& operator<< ( const POINTL& pointl )
00596     {
00597       *this << pointl.x << pointl.y;
00598       return *this;
00599     }
00604     DATASTREAM& operator>> ( POINTL& pointl )
00605     {
00606       *this >> pointl.x >> pointl.y;
00607       return *this;
00608     }
00613     DATASTREAM& operator<< ( const POINT16& point )
00614     {
00615       *this << point.x << point.y;
00616       return *this;
00617     }
00622     DATASTREAM& operator>> ( POINT16& point )
00623     {
00624       *this >> point.x >> point.y;
00625       return *this;
00626     }
00631     DATASTREAM& operator<< ( const XFORM& xform )
00632     {
00633       *this << xform.eM11 << xform.eM12 << xform.eM21 << xform.eM22
00634             << xform.eDx << xform.eDy;
00635       return *this;
00636     }
00641     DATASTREAM& operator>> ( XFORM& xform )
00642     {
00643       *this >> xform.eM11 >> xform.eM12 >> xform.eM21 >> xform.eM22
00644             >> xform.eDx >> xform.eDy;
00645       return *this;
00646     }
00651     DATASTREAM& operator<< ( const BYTEARRAY& array )
00652     {
00653       fwrite( array.array_, sizeof(BYTE), array.n_, fp_ );
00654       return *this;
00655     }
00660     DATASTREAM& operator>> ( BYTEARRAY& array )
00661     {
00662       fread( array.array_, sizeof(BYTE), array.n_, fp_ );
00663       return *this;
00664     }
00669     DATASTREAM& operator<< ( const POINTLARRAY& array )
00670     {
00671       for ( unsigned int i = 0; i < array.n_; i++ )
00672         *this << array.points_[i];
00673       return *this;
00674     }
00679     DATASTREAM& operator>> ( POINTLARRAY& array )
00680     {
00681       for ( unsigned int i = 0; i < array.n_; i++ )
00682         *this >> array.points_[i];
00683       return *this;
00684     }
00689     DATASTREAM& operator<< ( const POINT16ARRAY& array )
00690     {
00691       for ( unsigned int i = 0; i < array.n_; i++ )
00692         *this << array.points_[i];
00693       return *this;
00694     }
00699     DATASTREAM& operator>> ( POINT16ARRAY& array )
00700     {
00701       for ( unsigned int i = 0; i < array.n_; i++ )
00702         *this >> array.points_[i];
00703       return *this;
00704     }
00709     DATASTREAM& operator<< ( const INTARRAY& array )
00710     {
00711       for ( unsigned int i = 0; i < array.n_; i++ )
00712         *this << array.ints_[i];
00713       return *this;
00714     }
00719     DATASTREAM& operator>> ( INTARRAY& array )
00720     {
00721       for ( unsigned int i = 0; i < array.n_; i++ )
00722         *this >> array.ints_[i];
00723       return *this;
00724     }
00729     DATASTREAM& operator<< ( const DWORDARRAY& array )
00730     {
00731       for ( unsigned int i = 0; i < array.n_; i++ )
00732         *this << array.dwords_[i];
00733       return *this;
00734     }
00739     DATASTREAM& operator>> ( DWORDARRAY& array )
00740     {
00741       for ( unsigned int i = 0; i < array.n_; i++ )
00742         *this >> array.dwords_[i];
00743       return *this;
00744     }
00749     DATASTREAM& operator<< ( const ::EMRTEXT& text )
00750     {
00751       *this << text.ptlReference << text.nChars << text.offString << text.fOptions
00752          << text.rcl << text.offDx;
00753       return *this;
00754     }
00759     DATASTREAM& operator>> ( ::EMRTEXT& text )
00760     {
00761       *this >> text.ptlReference >> text.nChars >> text.offString >> text.fOptions
00762             >> text.rcl >> text.offDx;
00763       return *this;
00764     }
00769     DATASTREAM& operator<< ( const LOGPEN& pen )
00770     {
00771       *this << pen.lopnStyle << pen.lopnWidth << pen.lopnColor;
00772       return *this;
00773     }
00778     DATASTREAM& operator>> ( LOGPEN& pen )
00779     {
00780       *this >> pen.lopnStyle >> pen.lopnWidth >> pen.lopnColor;
00781       return *this;
00782     }
00787     DATASTREAM& operator<< ( const EXTLOGPEN& pen )
00788     {
00789       // *** How big is this structure if there are no style entries? ***
00790       *this << pen.elpPenStyle << pen.elpWidth << pen.elpBrushStyle << pen.elpColor
00791             << pen.elpHatch << pen.elpNumEntries;
00792       return *this;
00793     }
00798     DATASTREAM& operator>> ( EXTLOGPEN& pen )
00799     {
00800       // *** How big is this structure if there are no style entries? ***
00801       *this >> pen.elpPenStyle >> pen.elpWidth >> pen.elpBrushStyle >> pen.elpColor
00802             >> pen.elpHatch >> pen.elpNumEntries;
00803       return *this;
00804     }
00809     DATASTREAM& operator<< ( const LOGBRUSH& brush )
00810     {
00811       *this << brush.lbStyle << brush.lbColor << brush.lbHatch;
00812       return *this;
00813     }
00818     DATASTREAM& operator>> ( LOGBRUSH& brush )
00819     {
00820       *this >> brush.lbStyle >> brush.lbColor >> brush.lbHatch;
00821       return *this;
00822     }
00827     DATASTREAM& operator<< ( const LOGFONTW& font )
00828     {
00829       *this << font.lfHeight << font.lfWidth << font.lfEscapement
00830             << font.lfOrientation << font.lfWeight << font.lfItalic
00831             << font.lfUnderline << font.lfStrikeOut << font.lfCharSet
00832             << font.lfOutPrecision << font.lfClipPrecision << font.lfQuality
00833             << font.lfPitchAndFamily
00834             << WCHARSTR( const_cast<WCHAR*const>(font.lfFaceName), LF_FACESIZE );
00835       return *this;
00836     }
00841     DATASTREAM& operator>> ( LOGFONTW& font )
00842     {
00843       WCHARSTR wFaceName( font.lfFaceName, LF_FACESIZE );
00844 
00845       *this >> font.lfHeight >> font.lfWidth >> font.lfEscapement
00846             >> font.lfOrientation >> font.lfWeight >> font.lfItalic
00847             >> font.lfUnderline >> font.lfStrikeOut >> font.lfCharSet
00848             >> font.lfOutPrecision >> font.lfClipPrecision >> font.lfQuality
00849             >> font.lfPitchAndFamily
00850             >> wFaceName;
00851       return *this;
00852     }
00857     DATASTREAM& operator<< ( const PANOSE& panose )
00858     {
00859       fwrite( &panose, sizeof(PANOSE), 1, fp_ );
00860       return *this;
00861     }
00866     DATASTREAM& operator>> ( PANOSE& panose )
00867     {
00868       fread( &panose, sizeof(PANOSE), 1, fp_ );
00869       return *this;
00870     }
00875     DATASTREAM& operator<< ( const EXTLOGFONTW& font )
00876     {
00877       *this << font.elfLogFont
00878             << WCHARSTR( const_cast<WCHAR*const>(font.elfFullName),
00879                          LF_FULLFACESIZE )
00880             << WCHARSTR( const_cast<WCHAR*const>(font.elfStyle), LF_FACESIZE )
00881             << font.elfVersion << font.elfStyleSize << font.elfMatch
00882             << font.elfReserved
00883             << BYTEARRAY( const_cast<BYTE*const>(font.elfVendorId),
00884                           ELF_VENDOR_SIZE )
00885             << font.elfCulture << font.elfPanose;
00886       return *this;
00887     }
00892     DATASTREAM& operator>> ( EXTLOGFONTW& font )
00893     {
00894       WCHARSTR wFullName( font.elfFullName, LF_FULLFACESIZE );
00895       WCHARSTR wStyle( font.elfStyle, LF_FACESIZE );
00896       BYTEARRAY bVendorId( font.elfVendorId, ELF_VENDOR_SIZE );
00897       *this >> font.elfLogFont
00898             >> wFullName >> wStyle
00899             >> font.elfVersion >> font.elfStyleSize >> font.elfMatch
00900             >> font.elfReserved >> bVendorId
00901             >> font.elfCulture >> font.elfPanose;
00902       return *this;
00903     }
00908     DATASTREAM& operator<< ( const LOGPALETTE& palette )
00909     {
00910       // *** How big is this structure if the palette is empty? ***
00911       *this << palette.palVersion << palette.palNumEntries;
00912       return *this;
00913     }
00918     DATASTREAM& operator>> ( LOGPALETTE& palette )
00919     {
00920       // *** How big is this structure if the palette is empty? ***
00921       *this >> palette.palVersion >> palette.palNumEntries;
00922       return *this;
00923     }
00924   };
00925 
00926   class METAFILEDEVICECONTEXT;
00927 
00929 
00935   class METARECORD {
00936   public:
00943     virtual void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const = 0;
00950     virtual bool serialize ( DATASTREAM ds ) = 0;
00956     virtual int size ( void ) const = 0;
00962     virtual ~METARECORD( ) { }
00963 #ifdef ENABLE_EDITING
00964 
00968     virtual void edit ( void ) const {}
00969 #endif
00970   };
00971 
00972 #ifdef ENABLE_EDITING
00973   /* Miscellaneous editing routines */
00974   inline void edit_rectl ( const char* tag, const RECTL& rectl )
00975   {
00976     printf( "\t%s\t: (%ld, %ld) - (%ld, %ld)\n", tag, rectl.left, rectl.top,
00977             rectl.right, rectl.bottom );
00978   }
00979 
00980   inline void edit_xform ( const char* tag, const XFORM& xform )
00981   {
00982     printf( "\t%s.eM11\t: %f\n", tag, xform.eM11 );
00983     printf( "\t%s.eM12\t: %f\n", tag, xform.eM12 );
00984     printf( "\t%s.eM21\t: %f\n", tag, xform.eM21 );
00985     printf( "\t%s.eM22\t: %f\n", tag, xform.eM22 );
00986     printf( "\t%s.eDx\t: %f\n", tag, xform.eDx );
00987     printf( "\t%s.eDy\t: %f\n", tag, xform.eDy );
00988   }
00989 
00990   inline void edit_color ( const char* tag, const COLORREF& color )
00991   {
00992     printf( "\t%s\t: R(0x%02lx) G(0x%02lx) B(0x%02lx)\n", tag,
00993             GetRValue( color ), GetGValue( color ), GetBValue( color ) );
00994   }
00995 
00996   inline void edit_sizel ( const char* tag, const SIZEL& size )
00997   {
00998     printf( "\t%s\t: (%ld, %ld)\n", tag, size.cx, size.cy );
00999   }
01000 
01001   inline void edit_pointl ( const char* tag, const POINTL& point )
01002   {
01003     printf( "\t%s\t: (%ld, %ld)\n", tag, point.x, point.y );
01004   }
01005 
01006   inline void edit_pointlarray ( const char* tag, const DWORD cptl,
01007                                   const POINTL* points )
01008   {
01009     printf( "\tcptl%s\t: %ld\n", tag, cptl );
01010     printf( "\taptl%s\t: ", tag );
01011     if ( cptl > 0 )
01012       printf( "%ld, %ld\n", points[0].x, points[0].y );
01013     else
01014       puts( "" );
01015     for ( DWORD i = 1; i < cptl; i++ )
01016       printf( "\t\t%s  %ld, %ld\n", tag, points[i].x, points[i].y );
01017   }
01018 
01019   inline void edit_point16array ( const char* tag, const unsigned int cpts,
01020                                   const POINT16* points )
01021   {
01022     printf( "\tcpts%s\t: %d\n", tag, cpts );
01023     printf( "\tapts%s\t: ", tag );
01024     if ( cpts > 0 )
01025       printf( "%d, %d\n", points[0].x, points[0].y );
01026     else
01027       puts( "" );
01028     for ( unsigned int i = 1; i < cpts; i++ )
01029       printf( "\t\t%s  %d, %d\n", tag, points[i].x, points[i].y );
01030   }
01031 
01032   inline void edit_pen_style ( const char* tag, DWORD style )
01033   {
01034     printf( "\t%s\t: ", tag );
01035     switch ( style & PS_STYLE_MASK ) {
01036     case PS_SOLID: printf( "PS_SOLID" ); break;
01037     case PS_DASH: printf( "PS_DASH" ); break;
01038     case PS_DOT: printf( "PS_DOT" ); break;
01039     case PS_DASHDOT: printf( "PS_DASHDOT" ); break;
01040     case PS_DASHDOTDOT: printf( "PS_DASHDOTDOT" ); break;
01041     case PS_NULL: printf( "PS_NULL" ); break;
01042     case PS_INSIDEFRAME: printf( "PS_INSIDEFRAME" ); break;
01043     case PS_USERSTYLE: printf( "PS_USERSTYLE" ); break;
01044     case PS_ALTERNATE: printf( "PS_ALTERNATE" ); break;
01045     }
01046     switch ( style & PS_ENDCAP_MASK ) {
01047     case PS_ENDCAP_ROUND: printf( " | PS_ENDCAP_ROUND" ); break;
01048     case PS_ENDCAP_SQUARE: printf( " | PS_ENDCAP_SQUARE" ); break;
01049     case PS_ENDCAP_FLAT: printf( " | PS_ENDCAP_FLAT" ); break;
01050     }
01051     switch ( style & PS_JOIN_MASK ) {
01052     case PS_JOIN_ROUND: printf( " | PS_JOIN_ROUND" ); break;
01053     case PS_JOIN_BEVEL: printf( " | PS_JOIN_BEVEL" ); break;
01054     case PS_JOIN_MITER: printf( " | PS_JOIN_MITER" ); break;
01055     }
01056     switch ( style & PS_TYPE_MASK ) {
01057     case PS_COSMETIC: printf( " | PS_COSMETIC" ); break;
01058     case PS_GEOMETRIC: printf( " | PS_GEOMETRIC" ); break;
01059     }
01060     printf( "\n" );
01061   }
01062 
01063   inline void edit_brush_style ( const char* tag, DWORD style )
01064   {
01065     printf( "\t%s\t: ", tag );
01066     switch ( style ) {
01067     case BS_SOLID: printf( "BS_SOLID" ); break;
01068     case BS_NULL: printf( "BS_NULL" ); break;
01069     case BS_HATCHED: printf( "BS_HATCHED" ); break;
01070     case BS_PATTERN: printf( "BS_PATTERN" ); break;
01071     case BS_INDEXED: printf( "BS_INDEXED" ); break;
01072     case BS_DIBPATTERN: printf( "BS_DIBPATTERN" ); break;
01073     case BS_DIBPATTERNPT: printf( "BS_DIBPATTERNPT" ); break;
01074     case BS_PATTERN8X8: printf( "BS_PATTERN8X8" ); break;
01075     case BS_DIBPATTERN8X8: printf( "BS_DIBPATTERN8X8" ); break;
01076     case BS_MONOPATTERN: printf( "BS_DIBPATTERN8X8" ); break;
01077     default: printf( "unknown(%ld)", style );
01078     }
01079     printf( "\n" );
01080   }
01081 
01082   inline void edit_brush_hatch ( const char* tag, DWORD hatch )
01083   {
01084     printf( "\t%s\t: ", tag );
01085     switch ( hatch ) {
01086     case HS_HORIZONTAL: printf( "HS_HORIZONTAL" ); break;
01087     case HS_VERTICAL: printf( "HS_VERTICAL" ); break;
01088     case HS_FDIAGONAL: printf( "HS_FDIAGONAL" ); break;
01089     case HS_BDIAGONAL: printf( "HS_BDIAGONAL" ); break;
01090     case HS_CROSS: printf( "HS_CROSS" ); break;
01091     case HS_DIAGCROSS: printf( "HS_DIAGCROSS" ); break;
01092     default: printf( "unknown(%ld)", hatch );
01093     }
01094     printf( "\n" );
01095   }
01096 #endif
01097 
01104   enum OBJECTTYPE { O_METAFILEDEVICECONTEXT     = OBJ_METADC,
01105                     O_FONT                      = OBJ_FONT,
01106                     O_PEN                       = OBJ_PEN,
01107                     O_EXTPEN                    = OBJ_EXTPEN,
01108                     O_BRUSH                     = OBJ_BRUSH,
01109                     O_PALETTE                   = OBJ_PAL };
01110 #if 0
01111 
01114   static char* typStr ( OBJECTTYPE type )
01115   {
01116     switch (type) {
01117     case O_METAFILEDEVICECONTEXT:
01118       return "metafile device context";
01119     case O_FONT:
01120       return "font";
01121     case O_PEN:
01122       return "pen";
01123     case O_EXTPEN:
01124       return "extended pen";
01125     case O_BRUSH:
01126       return "brush";
01127     case O_PALETTE:
01128       return "palette";
01129     }
01130     return "unknown object";
01131   }
01132 #endif
01133 
01134 
01139   class OBJECT {
01140   public:
01141     HGDIOBJ handle;             
01142 
01143     virtual ~OBJECT () {}
01148     OBJECT ( void ) : handle( 0 ) {}
01152     virtual OBJECTTYPE getType ( void ) const = 0;
01153   };
01154 
01156 
01161   class GRAPHICSOBJECT : public OBJECT {
01162   public:
01164     virtual ~GRAPHICSOBJECT () {}
01169     std::map< HDC, HGDIOBJ > contexts;
01175     virtual METARECORD* newEMR ( HDC dc, HGDIOBJ handle ) = 0;
01176   };
01177 
01178   typedef METARECORD*(*METARECORDCTOR)(DATASTREAM&);
01179 
01180   class GLOBALOBJECTS {
01184     std::vector<OBJECT*> objects;
01185 
01192     std::map< DWORD, METARECORDCTOR > new_records;
01193 
01194   public:
01195     GLOBALOBJECTS ( void );
01196     ~GLOBALOBJECTS ( void );
01197     HGDIOBJ add ( OBJECT* object );
01198     OBJECT* find ( const HGDIOBJ handle );
01199     void remove ( const OBJECT* object );
01200 
01201     std::vector<EMF::OBJECT*>::const_iterator begin ( void ) const
01202     { return objects.begin(); }
01203     std::vector<EMF::OBJECT*>::const_iterator end ( void ) const
01204     { return objects.end(); }
01205 
01206     METARECORDCTOR newRecord ( DWORD iType ) const;
01207 
01208     static EMF::METARECORD* new_eof ( DATASTREAM& ds );
01209     static EMF::METARECORD* new_setviewportorgex ( DATASTREAM& ds );
01210     static EMF::METARECORD* new_setwindoworgex ( DATASTREAM& ds );
01211     static EMF::METARECORD* new_setviewportextex ( DATASTREAM& ds );
01212     static EMF::METARECORD* new_setwindowextex ( DATASTREAM& ds );
01213     static EMF::METARECORD* new_scaleviewportextex ( DATASTREAM& ds );
01214     static EMF::METARECORD* new_scalewindowextex ( DATASTREAM& ds );
01215     static EMF::METARECORD* new_modifyworldtransform ( DATASTREAM& ds );
01216     static EMF::METARECORD* new_setworldtransform ( DATASTREAM& ds );
01217     static EMF::METARECORD* new_settextalign ( DATASTREAM& ds );
01218     static EMF::METARECORD* new_settextcolor ( DATASTREAM& ds );
01219     static EMF::METARECORD* new_setbkcolor ( DATASTREAM& ds );
01220     static EMF::METARECORD* new_setbkmode ( DATASTREAM& ds );
01221     static EMF::METARECORD* new_setpolyfillmode ( DATASTREAM& ds );
01222     static EMF::METARECORD* new_setmapmode ( DATASTREAM& ds );
01223     static EMF::METARECORD* new_selectobject ( DATASTREAM& ds );
01224     static EMF::METARECORD* new_deleteobject ( DATASTREAM& ds );
01225     static EMF::METARECORD* new_movetoex ( DATASTREAM& ds );
01226     static EMF::METARECORD* new_lineto ( DATASTREAM& ds );
01227     static EMF::METARECORD* new_arc ( DATASTREAM& ds );
01228     static EMF::METARECORD* new_arcto ( DATASTREAM& ds );
01229     static EMF::METARECORD* new_rectangle ( DATASTREAM& ds );
01230     static EMF::METARECORD* new_ellipse ( DATASTREAM& ds );
01231     static EMF::METARECORD* new_polyline ( DATASTREAM& ds );
01232     static EMF::METARECORD* new_polyline16 ( DATASTREAM& ds );
01233     static EMF::METARECORD* new_polygon ( DATASTREAM& ds );
01234     static EMF::METARECORD* new_polygon16 ( DATASTREAM& ds );
01235     static EMF::METARECORD* new_polypolygon ( DATASTREAM& ds );
01236     static EMF::METARECORD* new_polypolygon16 ( DATASTREAM& ds );
01237     static EMF::METARECORD* new_polybezier ( DATASTREAM& ds );
01238     static EMF::METARECORD* new_polybezier16 ( DATASTREAM& ds );
01239     static EMF::METARECORD* new_polybezierto ( DATASTREAM& ds );
01240     static EMF::METARECORD* new_polybezierto16 ( DATASTREAM& ds );
01241     static EMF::METARECORD* new_polylineto ( DATASTREAM& ds );
01242     static EMF::METARECORD* new_polylineto16 ( DATASTREAM& ds );
01243     static EMF::METARECORD* new_exttextouta ( DATASTREAM& ds );
01244     static EMF::METARECORD* new_setpixelv ( DATASTREAM& ds );
01245     static EMF::METARECORD* new_createpen ( DATASTREAM& ds );
01246     static EMF::METARECORD* new_extcreatepen ( DATASTREAM& ds );
01247     static EMF::METARECORD* new_createbrushindirect ( DATASTREAM& ds );
01248     static EMF::METARECORD* new_extcreatefontindirectw ( DATASTREAM& ds );
01249     static EMF::METARECORD* new_fillpath ( DATASTREAM& ds );
01250     static EMF::METARECORD* new_strokepath ( DATASTREAM& ds );
01251     static EMF::METARECORD* new_beginpath ( DATASTREAM& ds );
01252     static EMF::METARECORD* new_endpath ( DATASTREAM& ds );
01253     static EMF::METARECORD* new_closefigure ( DATASTREAM& ds );
01254     static EMF::METARECORD* new_savedc ( DATASTREAM& ds );
01255     static EMF::METARECORD* new_restoredc ( DATASTREAM& ds );
01256     static EMF::METARECORD* new_setmetargn ( DATASTREAM& ds );
01257   };
01258 
01259   extern GLOBALOBJECTS globalObjects;
01260 
01262 
01268   class ENHMETAHEADER : public METARECORD, public ::ENHMETAHEADER {
01269 
01270     LPWSTR description_w;
01271     int description_size;
01272 
01273   public:
01280     ENHMETAHEADER ( LPCWSTR description = 0 )
01281       : description_w( 0 ), description_size( 0 )
01282     {
01283       iType = EMR_HEADER;
01284       nSize = sizeof( ::ENHMETAHEADER );
01285 
01286       // Compute the bounds
01287       RECTL default_bounds = { 0, 0, 0, 0 };
01288       rclBounds = default_bounds;
01289       RECTL default_frame = { 0, 0, 0, 0 };
01290       rclFrame = default_frame;
01291       dSignature = ENHMETA_SIGNATURE;
01292       nVersion = 0x10000;
01293       nBytes = nSize;
01294       nRecords = 1;
01295       nHandles = 0;
01296       sReserved = 0;
01297       nDescription = 0;
01298       offDescription = 0;
01299       nPalEntries = 0;
01300       szlDevice.cx = XMAX_PIXELS;
01301       szlDevice.cy = YMAX_PIXELS;
01302       szlMillimeters.cx = XMAX_MM;
01303       szlMillimeters.cy = YMAX_MM;
01304       //
01305       cbPixelFormat = 0;
01306       offPixelFormat = 0;
01307       bOpenGL = FALSE;
01308       //
01309       szlMicrometers.cx = 1000 * szlMillimeters.cx;
01310       szlMicrometers.cy = 1000 * szlMillimeters.cy;
01311 
01312       if ( description ) {
01313         // Count the number of characters in the description
01314         int description_count = 0, nulls = 0;
01315         LPCWSTR description_p = description;
01316         while ( nulls < 3 ) {
01317           description_count++;
01318           if ( (*description_p++) == 0 ) nulls++;
01319         }
01320 
01321         // Make sure that the TOTAL record length will be a multiple of 4
01322 
01323         int record_size = ROUND_TO_LONG( sizeof( ::ENHMETAHEADER ) +
01324                                          sizeof( WCHAR ) * description_count );
01325         description_size =
01326           (record_size - sizeof( ::ENHMETAHEADER )) / sizeof( WCHAR );
01327 
01328         description_w = new WCHAR[ description_size ];
01329 
01330         memset( description_w, 0, sizeof(WCHAR) * description_size );
01331 
01332         for ( int i=0; i<description_count; i++ )
01333           description_w[i] = *description++;
01334 
01335         nSize = nBytes = record_size;
01336         nDescription = description_count;
01337         offDescription = sizeof( ::ENHMETAHEADER );
01338       }
01339     }
01340     
01344     ~ENHMETAHEADER ( )
01345     {
01346       if ( description_w ) delete[] description_w;
01347     }
01352     bool serialize ( DATASTREAM ds )
01353     {
01354       ds << iType << nSize
01355          << rclBounds << rclFrame
01356          << dSignature << nVersion << nBytes << nRecords << nHandles << sReserved
01357          << nDescription << offDescription << nPalEntries
01358          << szlDevice << szlMillimeters
01359          << cbPixelFormat << offPixelFormat << bOpenGL
01360          << szlMicrometers
01361          << WCHARSTR( description_w, description_size );
01362       return true;
01363     }
01367     bool unserialize ( DATASTREAM ds )
01368     {
01369       ds >> iType >> nSize
01370          >> rclBounds >> rclFrame
01371          >> dSignature >> nVersion >> nBytes >> nRecords >> nHandles >> sReserved
01372          >> nDescription >> offDescription >> nPalEntries
01373          >> szlDevice >> szlMillimeters;
01374 
01375       // Some elements of the metafile header were added at later dates
01376 
01377 #define OffsetOf( a, b ) ((unsigned int)(((char*)&(((::ENHMETAHEADER*)a)->b)) - \
01378 (char*)((::ENHMETAHEADER*)a)))
01379 
01380       if ( OffsetOf( this, szlMicrometers ) <= offDescription )
01381         ds >> cbPixelFormat >> offPixelFormat >> bOpenGL;
01382 
01383 #undef OffsetOf
01384 
01385       if ( sizeof(::ENHMETAHEADER) <= offDescription )
01386         ds >> szlMicrometers;
01387 
01388       // Should now probably check that the offset is correct...
01389 
01390       description_size = ( nSize - offDescription ) / sizeof(WCHAR);
01391       description_w = new WCHAR[ description_size ];
01392 
01393       WCHARSTR description( description_w, description_size );
01394 
01395       ds >> description;
01396 
01397       return true;
01398     }
01402     int size ( void ) const { return nSize; }
01408     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC /*dc*/ ) const
01409     {
01410       // Actually handled by the destination device context.
01411     }
01412 #ifdef ENABLE_EDITING
01413 
01416     void edit ( void ) const
01417     {
01418       printf( "*HEADER*\n" );
01419       printf( "\tiType\t\t\t: %ld\n", iType );
01420       printf( "\tnSize\t\t\t: %ld\n", nSize );
01421       edit_rectl( "rclBounds\t", rclBounds );
01422       edit_rectl( "rclFrame\t", rclFrame );
01423       printf( "\tdSignature\t\t: %.4s\n", (const char*)&dSignature );
01424       printf( "\tnVersion\t\t: 0x%x\n", (unsigned int)nVersion );
01425       printf( "\tnBytes\t\t\t: %ld\n", nBytes );
01426       printf( "\tnRecords\t\t: %ld\n", nRecords );
01427       printf( "\tnHandles\t\t: %d\n", nHandles );
01428       printf( "\tnDescription\t\t: %ld\n", nDescription );
01429       printf( "\toffDescription\t\t: %ld\n", offDescription );
01430       printf( "\tnPalEntries\t\t: %ld\n", nPalEntries );
01431       edit_sizel( "szlDevice\t", szlDevice );
01432       edit_sizel( "szlMillimeters\t", szlMillimeters );
01433 
01434       /* Make a crude guess as to the age of this file */
01435 #define OffsetOf( a, b ) ((unsigned int)(((const char*)&(((const ::ENHMETAHEADER*)a)->b)) - \
01436 (const char*)((const ::ENHMETAHEADER*)a)))
01437 
01438       if ( OffsetOf( this, cbPixelFormat ) <= offDescription ) {
01439         printf( "\tcbPixelFormat\t\t: %ld\n", cbPixelFormat );
01440         printf( "\toffPixelFormat\t\t: %ld\n", offPixelFormat );
01441         printf( "\tbOpenGL\t\t\t: %ld\n", bOpenGL );
01442 
01443         if ( sizeof(::ENHMETAHEADER) <= offDescription ) {
01444           edit_sizel( "szlMicrometers\t", szlMicrometers );
01445         }
01446       }
01447 
01448 #undef OffsetOf
01449 
01450       if ( nDescription != 0 ) {
01451 
01452         wchar_t last_w = 0;
01453         WCHAR* description = description_w;
01454 
01455         printf( "\tDescription:" );
01456 
01457         for ( DWORD i = 0; i < nDescription; i++ ) {
01458 
01459           wchar_t w = *description++; /* This is not true, really. UNICODE is not
01460                                        * glibc's wide character representation */
01461 
01462           if ( w != 0 ) {
01463             if ( last_w == 0 ) printf( "\n\t\t" );
01464             putchar( w );
01465           }
01466           
01467           last_w = w;
01468         }
01469         printf( "\n" );
01470       }
01471     }
01472 #endif /* ENABLE_EDITING */
01473   };
01474 
01476 
01481   class EMREOF : public METARECORD, ::EMREOF {
01482   public:
01486     EMREOF ( void )
01487     {
01488       emr.iType = EMR_EOF;
01489       emr.nSize = sizeof( ::EMREOF );
01490       nPalEntries = 0;
01491       offPalEntries = 0;
01492       nSizeLast = 0;
01493     }
01494 
01499     EMREOF ( DATASTREAM& ds )
01500     {
01501       ds >> emr >> nPalEntries >> offPalEntries >> nSizeLast;
01502     }
01503 
01507     bool serialize ( DATASTREAM ds )
01508     {
01509       ds << emr << nPalEntries << offPalEntries << nSizeLast;
01510       return true;
01511     }
01515     int size ( void ) const { return emr.nSize; }
01521     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC /*dc*/ ) const
01522     {
01523       // Actually handled by the destination device context.
01524     }
01525 #ifdef ENABLE_EDITING
01526 
01529     void edit ( void ) const
01530     {
01531       printf( "*EOF*\n" );
01532     }
01533 #endif /* ENABLE_EDITING */
01534   };
01535 
01537 
01542   class EMRSETVIEWPORTORGEX : public METARECORD, ::EMRSETVIEWPORTORGEX {
01543   public:
01548     EMRSETVIEWPORTORGEX ( INT x, INT y )
01549     {
01550       emr.iType = EMR_SETVIEWPORTORGEX;
01551       emr.nSize = sizeof( ::EMRSETVIEWPORTORGEX );
01552       ptlOrigin.x = x;
01553       ptlOrigin.y = y;
01554     }
01559     EMRSETVIEWPORTORGEX ( DATASTREAM& ds )
01560     {
01561       ds >> emr >> ptlOrigin;
01562     }
01566     bool serialize ( DATASTREAM ds )
01567     {
01568       ds << emr << ptlOrigin;
01569       return true;
01570     }
01574     int size ( void ) const { return emr.nSize; }
01580     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01581     {
01582       SetViewportOrgEx( dc, ptlOrigin.x, ptlOrigin.y, 0 );
01583     }
01584 #ifdef ENABLE_EDITING
01585 
01588     void edit ( void ) const
01589     {
01590       printf( "*SETVIEWPORTORGEX*\n" );
01591       edit_pointl( "ptlOrigin", ptlOrigin );
01592     }
01593 #endif /* ENABLE_EDITING */
01594   };
01595 
01597 
01604   class EMRSETWINDOWORGEX : public METARECORD, ::EMRSETWINDOWORGEX {
01605   public:
01610     EMRSETWINDOWORGEX ( INT x, INT y )
01611     {
01612       emr.iType = EMR_SETWINDOWORGEX;
01613       emr.nSize = sizeof( ::EMRSETWINDOWORGEX );
01614       ptlOrigin.x = x;
01615       ptlOrigin.y = y;
01616     }
01621     EMRSETWINDOWORGEX ( DATASTREAM& ds )
01622     {
01623       ds >> emr >> ptlOrigin;
01624     }
01628     bool serialize ( DATASTREAM ds )
01629     {
01630       ds << emr << ptlOrigin;
01631       return true;
01632     }
01636     int size ( void ) const { return emr.nSize; }
01642     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01643     {
01644       SetWindowOrgEx( dc, ptlOrigin.x, ptlOrigin.y, 0 );
01645     }
01646 #ifdef ENABLE_EDITING
01647 
01650     void edit ( void ) const
01651     {
01652       printf( "*SETWINDOWORGEX*\n" );
01653       edit_pointl( "ptlOrigin", ptlOrigin );
01654     }
01655 #endif /* ENABLE_EDITING */
01656   };
01657 
01659 
01664   class EMRSETVIEWPORTEXTEX : public METARECORD, ::EMRSETVIEWPORTEXTEX {
01665   public:
01670     EMRSETVIEWPORTEXTEX ( INT cx, INT cy )
01671     {
01672       emr.iType = EMR_SETVIEWPORTEXTEX;
01673       emr.nSize = sizeof( ::EMRSETVIEWPORTEXTEX );
01674       szlExtent.cx = cx;
01675       szlExtent.cy = cy;
01676     }
01681     EMRSETVIEWPORTEXTEX ( DATASTREAM& ds )
01682     {
01683       ds >> emr >> szlExtent;
01684     }
01688     bool serialize ( DATASTREAM ds )
01689     {
01690       ds << emr << szlExtent;
01691       return true;
01692     }
01696     int size ( void ) const { return emr.nSize; }
01702     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01703     {
01704       SetViewportExtEx( dc, szlExtent.cx, szlExtent.cy, 0 );
01705     }
01706 #ifdef ENABLE_EDITING
01707 
01710     void edit ( void ) const
01711     {
01712       printf( "*SETVIEWPORTEXTEX*\n" );
01713       edit_sizel( "szlExtent", szlExtent );
01714     }
01715 #endif /* ENABLE_EDITING */
01716   };
01717 
01719 
01724   class EMRSCALEVIEWPORTEXTEX : public METARECORD, ::EMRSCALEVIEWPORTEXTEX {
01725   public:
01732     EMRSCALEVIEWPORTEXTEX ( LONG x_num, LONG x_den, LONG y_num, LONG y_den )
01733     {
01734       emr.iType = EMR_SCALEVIEWPORTEXTEX;
01735       emr.nSize = sizeof( ::EMRSCALEVIEWPORTEXTEX );
01736       xNum = x_num;
01737       xDenom = x_den;
01738       yNum = y_num;
01739       yDenom = y_den;
01740     }
01745     EMRSCALEVIEWPORTEXTEX ( DATASTREAM& ds )
01746     {
01747       ds >> emr >> xNum >> xDenom >> yNum >> yDenom;
01748     }
01752     bool serialize ( DATASTREAM ds )
01753     {
01754       ds << emr << xNum << xDenom << yNum << yDenom;
01755       return true;
01756     }
01760     int size ( void ) const { return emr.nSize; }
01766     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01767     {
01768       ScaleViewportExtEx( dc, xNum, xDenom, yNum, yDenom, 0 );
01769     }
01770 #ifdef ENABLE_EDITING
01771 
01774     void edit ( void ) const
01775     {
01776       printf( "*SCALEVIEWPORTEXTEX*\n" );
01777       printf( "\txNum\t: %ld\n", xNum );
01778       printf( "\txDenom\t: %ld\n", xDenom );
01779       printf( "\tyNum\t: %ld\n", yNum );
01780       printf( "\tyDenom\t: %ld\n", yDenom );
01781     }
01782 #endif /* ENABLE_EDITING */
01783   };
01784 
01786 
01791   class EMRSETWINDOWEXTEX : public METARECORD, ::EMRSETWINDOWEXTEX {
01792   public:
01797     EMRSETWINDOWEXTEX ( INT cx, INT cy )
01798     {
01799       emr.iType = EMR_SETWINDOWEXTEX;
01800       emr.nSize = sizeof( ::EMRSETWINDOWEXTEX );
01801       szlExtent.cx = cx;
01802       szlExtent.cy = cy;
01803     }
01808     EMRSETWINDOWEXTEX ( DATASTREAM& ds )
01809     {
01810       ds >> emr >> szlExtent;
01811     }
01815     bool serialize ( DATASTREAM ds )
01816     {
01817       ds << emr << szlExtent;
01818       return true;
01819     }
01823     int size ( void ) const { return emr.nSize; }
01829     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01830     {
01831       SetWindowExtEx( dc, szlExtent.cx, szlExtent.cy, 0 );
01832     }
01833 #ifdef ENABLE_EDITING
01834 
01837     void edit ( void ) const
01838     {
01839       printf( "*SETWINDOWEXTEX*\n" );
01840       edit_sizel( "szlExtent", szlExtent );
01841     }
01842 #endif /* ENABLE_EDITING */
01843   };
01844 
01846 
01851   class EMRSCALEWINDOWEXTEX : public METARECORD, ::EMRSCALEWINDOWEXTEX {
01852   public:
01859     EMRSCALEWINDOWEXTEX ( LONG x_num, LONG x_den, LONG y_num, LONG y_den )
01860     {
01861       emr.iType = EMR_SCALEWINDOWEXTEX;
01862       emr.nSize = sizeof( ::EMRSCALEWINDOWEXTEX );
01863       xNum = x_num;
01864       xDenom = x_den;
01865       yNum = y_num;
01866       yDenom = y_den;
01867     }
01872     EMRSCALEWINDOWEXTEX ( DATASTREAM& ds )
01873     {
01874       ds >> emr >> xNum >> xDenom >> yNum >> yDenom;
01875     }
01879     bool serialize ( DATASTREAM ds )
01880     {
01881       ds << emr << xNum << xDenom << yNum << yDenom;
01882       return true;
01883     }
01887     int size ( void ) const { return emr.nSize; }
01893     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01894     {
01895       ScaleWindowExtEx( dc, xNum, xDenom, yNum, yDenom, 0 );
01896     }
01897 #ifdef ENABLE_EDITING
01898 
01901     void edit ( void ) const
01902     {
01903       printf( "*SCALEWINDOWEXTEX*\n" );
01904       printf( "\txNum\t: %ld\n", xNum );
01905       printf( "\txDenom\t: %ld\n", xDenom );
01906       printf( "\tyNum\t: %ld\n", yNum );
01907       printf( "\tyDenom\t: %ld\n", yDenom );
01908     }
01909 #endif /* ENABLE_EDITING */
01910   };
01911 
01913 
01919   class EMRMODIFYWORLDTRANSFORM : public METARECORD, ::EMRMODIFYWORLDTRANSFORM {
01920   public:
01926     EMRMODIFYWORLDTRANSFORM ( const XFORM* transform, DWORD mode )
01927     {
01928       emr.iType = EMR_MODIFYWORLDTRANSFORM;
01929       emr.nSize = sizeof( ::EMRMODIFYWORLDTRANSFORM );
01930       xform = *transform;
01931       iMode = mode;
01932     }
01937     EMRMODIFYWORLDTRANSFORM ( DATASTREAM& ds )
01938     {
01939       ds >> emr >> xform >> iMode;
01940     }
01944     bool serialize ( DATASTREAM ds )
01945     {
01946       ds << emr << xform << iMode;
01947       return true;
01948     }
01952     int size ( void ) const { return emr.nSize; }
01958     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
01959     {
01960       ModifyWorldTransform( dc, &xform, iMode );
01961     }
01962 #ifdef ENABLE_EDITING
01963 
01966     void edit ( void ) const
01967     {
01968       printf( "*MODIFYWORLDTRANSFORM*\n" );
01969       edit_xform( "xform", xform );
01970       printf( "\tiMode\t\t: " );
01971       switch ( iMode ) {
01972       case MWT_IDENTITY: printf( "MWT_IDENTITY\n" ); break;
01973       case MWT_LEFTMULTIPLY: printf( "MWT_LEFTMULTIPLY\n" ); break;
01974       case MWT_RIGHTMULTIPLY: printf( "MWT_RIGHTMULTIPLY\n" ); break;
01975       default: printf( "unknown(%ld)\n", iMode );
01976       }
01977     }
01978 #endif /* ENABLE_EDITING */
01979   };
01980 
01982 
01988   class EMRSETWORLDTRANSFORM : public METARECORD, ::EMRSETWORLDTRANSFORM {
01989   public:
01993     EMRSETWORLDTRANSFORM ( const XFORM* transform )
01994     {
01995       emr.iType = EMR_SETWORLDTRANSFORM;
01996       emr.nSize = sizeof( ::EMRSETWORLDTRANSFORM );
01997       xform = *transform;
01998     }
02003     EMRSETWORLDTRANSFORM ( DATASTREAM& ds )
02004     {
02005       ds >> emr >> xform;
02006     }
02010     bool serialize ( DATASTREAM ds )
02011     {
02012       ds << emr << xform;
02013       return true;
02014     }
02018     int size ( void ) const { return emr.nSize; }
02024     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02025     {
02026       SetWorldTransform( dc, &xform );
02027     }
02028 #ifdef ENABLE_EDITING
02029 
02032     void edit ( void ) const
02033     {
02034       printf( "*SETWORLDTRANSFORM*\n" );
02035       edit_xform( "xform", xform );
02036     }
02037 #endif /* ENABLE_EDITING */
02038   };
02039 
02041 
02044   class EMRSETTEXTALIGN : public METARECORD, ::EMRSETTEXTALIGN {
02045   public:
02049     EMRSETTEXTALIGN ( UINT mode )
02050     {
02051       emr.iType = EMR_SETTEXTALIGN;
02052       emr.nSize = sizeof( ::EMRSETTEXTALIGN );
02053       iMode = mode;
02054     }
02059     EMRSETTEXTALIGN ( DATASTREAM& ds )
02060     {
02061       ds >> emr >> iMode;
02062     }
02066     bool serialize ( DATASTREAM ds )
02067     {
02068       ds << emr << iMode;
02069       return true;
02070     }
02074     int size ( void ) const { return emr.nSize; }
02080     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02081     {
02082       SetTextAlign( dc, iMode );
02083     }
02084 #ifdef ENABLE_EDITING
02085 
02088     void edit ( void ) const
02089     {
02090       unsigned int known_bits = TA_BASELINE+TA_CENTER+TA_UPDATECP+TA_RTLREADING;
02091       unsigned int unknown_bits = ~known_bits;
02092 
02093       printf( "*SETTEXTALIGN*\n" );
02094       printf( "\tiMode\t: " );
02095       if ( iMode & TA_UPDATECP )
02096         printf( "TA_UPDATECP" );
02097       else
02098         printf( "TA_NOUPDATECP" );
02099       if ( iMode & TA_CENTER )
02100         printf( " | TA_CENTER" );
02101       else if ( iMode & TA_RIGHT )
02102         printf( " | TA_RIGHT" );
02103       else
02104         printf( " | TA_LEFT" );
02105       if ( iMode & TA_BASELINE )
02106         printf( " | TA_BASELINE" );
02107       else if ( iMode & TA_BOTTOM )
02108         printf( " | TA_BOTTOM" );
02109       else
02110         printf( " | TA_TOP" );
02111       if ( iMode & TA_RTLREADING )
02112         printf( " | TA_RTLREADING" );
02113       if ( iMode & unknown_bits )
02114         printf( " | unknown bits(0x%lx)", iMode & unknown_bits );
02115       printf( "\n" );
02116     }
02117 #endif /* ENABLE_EDITING */
02118   };
02119 
02121 
02124   class EMRSETTEXTCOLOR : public METARECORD, ::EMRSETTEXTCOLOR {
02125   public:
02129     EMRSETTEXTCOLOR ( COLORREF color )
02130     {
02131       emr.iType = EMR_SETTEXTCOLOR;
02132       emr.nSize = sizeof( ::EMRSETTEXTCOLOR );
02133       crColor = color;
02134     }
02139     EMRSETTEXTCOLOR ( DATASTREAM& ds )
02140     {
02141       ds >> emr >> crColor;
02142     }
02146     bool serialize ( DATASTREAM ds )
02147     {
02148       ds << emr << crColor;
02149       return true;
02150     }
02154     int size ( void ) const { return emr.nSize; }
02160     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
02161     {
02162       SetTextColor( dc, crColor );
02163     }
02164 #ifdef ENABLE_EDITING
02165 
02168     void