libemf.h Source File

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 edit ( void ) const
    02169     {
    02170       printf( "*SETTEXTCOLOR*\n" );
    02171       edit_color( "crColor", crColor );
    02172     }
    02173 #endif /* ENABLE_EDITING */
    02174   };
    02175
    02177
    02180   class EMRSETBKCOLOR : public METARECORD, ::EMRSETBKCOLOR {
    02181   public:
    02185     EMRSETBKCOLOR ( COLORREF color )
    02186     {
    02187       emr.iType = EMR_SETBKCOLOR;
    02188       emr.nSize = sizeof( ::EMRSETBKCOLOR );
    02189       crColor = color;
    02190     }
    02195     EMRSETBKCOLOR ( DATASTREAM& ds )
    02196     {
    02197       ds >> emr >> crColor;
    02198     }
    02202     bool serialize ( DATASTREAM ds )
    02203     {
    02204       ds << emr << crColor;
    02205       return true;
    02206     }
    02210     int size ( void ) const { return emr.nSize; }
    02216     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    02217     {
    02218       SetBkColor( dc, crColor );
    02219     }
    02220 #ifdef ENABLE_EDITING
    02221
    02224     void edit ( void ) const
    02225     {
    02226       printf( "*SETBKCOLOR*\n" );
    02227       edit_color( "crColor", crColor );
    02228     }
    02229 #endif /* ENABLE_EDITING */
    02230   };
    02231
    02233
    02237   class EMRSETBKMODE : public METARECORD, ::EMRSETBKMODE {
    02238   public:
    02242     EMRSETBKMODE ( DWORD mode )
    02243     {
    02244       emr.iType = EMR_SETBKMODE;
    02245       emr.nSize = sizeof( ::EMRSETBKMODE );
    02246       iMode = mode;
    02247     }
    02252     EMRSETBKMODE ( DATASTREAM& ds )
    02253     {
    02254       ds >> emr >> iMode;
    02255     }
    02259     bool serialize ( DATASTREAM ds )
    02260     {
    02261       ds << emr << iMode;
    02262       return true;
    02263     }
    02267     int size ( void ) const { return emr.nSize; }
    02273     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    02274     {
    02275       SetBkMode( dc, iMode );
    02276     }
    02277 #ifdef ENABLE_EDITING
    02278
    02281     void edit ( void ) const
    02282     {
    02283       printf( "*SETBKMODE*\n" );
    02284       printf( "\tiMode\t: " );
    02285       switch ( iMode ) {
    02286       case TRANSPARENT: printf( "TRANSPARENT\n" ); break;
    02287       case OPAQUE: printf( "OPAQUE\n" ); break;
    02288       default: printf( "unknown(%ld)\n", iMode );
    02289       }
    02290     }
    02291 #endif /* ENABLE_EDITING */
    02292   };
    02293
    02295
    02298   class EMRSETPOLYFILLMODE : public METARECORD, ::EMRSETPOLYFILLMODE {
    02299   public:
    02303     EMRSETPOLYFILLMODE ( DWORD mode )
    02304     {
    02305       emr.iType = EMR_SETPOLYFILLMODE;
    02306       emr.nSize = sizeof( ::EMRSETPOLYFILLMODE );
    02307       iMode = mode;
    02308     }
    02313     EMRSETPOLYFILLMODE ( DATASTREAM& ds )
    02314     {
    02315       ds >> emr >> iMode;
    02316     }
    02320     bool serialize ( DATASTREAM ds )
    02321     {
    02322       ds << emr << iMode;
    02323       return true;
    02324     }
    02328     int size ( void ) const { return emr.nSize; }
    02334     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    02335     {
    02336       SetPolyFillMode( dc, iMode );
    02337     }
    02338 #ifdef ENABLE_EDITING
    02339
    02342     void edit ( void ) const
    02343     {
    02344       printf( "*SETPOLYFILLMODE*\n" );
    02345       printf( "\tiMode: " );
    02346       switch ( iMode ) {
    02347       case ALTERNATE: printf( "ALTERNATE\n" ); break;
    02348       case WINDING: printf( "WINDING\n" ); break;
    02349       default: printf( "unknown(%ld)\n", iMode );
    02350       }
    02351     }
    02352 #endif /* ENABLE_EDITING */
    02353   };
    02354
    02356
    02360   class EMRSETMAPMODE : public METARECORD, ::EMRSETMAPMODE {
    02361   public:
    02365     EMRSETMAPMODE ( DWORD mode )
    02366     {
    02367       emr.iType = EMR_SETMAPMODE;
    02368       emr.nSize = sizeof( ::EMRSETMAPMODE );
    02369       iMode = mode;
    02370     }
    02375     EMRSETMAPMODE ( DATASTREAM& ds )
    02376     {
    02377       ds >> emr >> iMode;
    02378     }
    02382     bool serialize ( DATASTREAM ds )
    02383     {
    02384       ds << emr << iMode;
    02385       return true;
    02386     }
    02390     int size ( void ) const { return emr.nSize; }
    02396     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    02397     {
    02398       SetMapMode( dc, iMode );
    02399     }
    02400 #ifdef ENABLE_EDITING
    02401
    02404     void edit ( void ) const
    02405     {
    02406       printf( "*SETMAPMODE*\n" );
    02407       printf( "\tiMode\t: " );
    02408       switch ( iMode ) {
    02409       case MM_TEXT: printf( "MM_TEXT\n" ); break;
    02410       case MM_LOMETRIC: printf( "MM_LOMETRIC\n" ); break;
    02411       case MM_HIMETRIC: printf( "MM_HIMETRIC\n" ); break;
    02412       case MM_LOENGLISH: printf( "MM_LOENGLISH\n" ); break;
    02413       case MM_HIENGLISH: printf( "MM_HIENGLISH\n" ); break;
    02414       case MM_TWIPS: printf( "MM_TWIPS\n" ); break;
    02415       case MM_ISOTROPIC: printf( "MM_ISOTROPIC\n" ); break;
    02416       case MM_ANISOTROPIC: printf( "MM_ANISOTROPIC\n" ); break;
    02417       default: printf( "unknown(%ld)\n", iMode );
    02418       }
    02419     }
    02420 #endif /* ENABLE_EDITING */
    02421   };
    02422
    02424
    02427   class EMRSELECTOBJECT : public METARECORD, ::EMRSELECTOBJECT {
    02428   public:
    02432     EMRSELECTOBJECT ( HGDIOBJ object )
    02433     {
    02434       emr.iType = EMR_SELECTOBJECT;
    02435       emr.nSize = sizeof( ::EMRSELECTOBJECT );
    02436       ihObject = object;
    02437     }
    02442     EMRSELECTOBJECT ( DATASTREAM& ds )
    02443     {
    02444       ds >> emr >> ihObject;
    02445     }
    02449     bool serialize ( DATASTREAM ds )
    02450     {
    02451       ds << emr << ihObject;
    02452       return true;
    02453     }
    02457     int size ( void ) const { return emr.nSize; }
    02463     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
    02464 #ifdef ENABLE_EDITING
    02465
    02468     void edit ( void ) const
    02469     {
    02470       printf( "*SELECTOBJECT*\n" );
    02471       printf( "\tihObject\t: 0x%lx\n", ihObject );
    02472     }
    02473 #endif /* ENABLE_EDITING */
    02474   };
    02475
    02477
    02480   class EMRDELETEOBJECT : public METARECORD, ::EMRDELETEOBJECT {
    02481   public:
    02485     EMRDELETEOBJECT ( HGDIOBJ object )
    02486     {
    02487       emr.iType = EMR_DELETEOBJECT;
    02488       emr.nSize = sizeof( ::EMRDELETEOBJECT );
    02489       ihObject = object;
    02490     }
    02495     EMRDELETEOBJECT ( DATASTREAM& ds )
    02496     {
    02497       ds >> emr >> ihObject;
    02498     }
    02502     bool serialize ( DATASTREAM ds )
    02503     {
    02504       ds << emr << ihObject;
    02505       return true;
    02506     }
    02510     int size ( void ) const { return emr.nSize; }
    02516     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
    02517 #ifdef ENABLE_EDITING
    02518
    02521     void edit ( void ) const
    02522     {
    02523       printf( "*DELETEOBJECT*\n" );
    02524       printf( "\tihObject\t: 0x%lx\n", ihObject );
    02525     }
    02526 #endif /* ENABLE_EDITING */
    02527   };
    02528
    02530
    02533   class EMRMOVETOEX : public METARECORD, ::EMRMOVETOEX {
    02534   public:
    02539     EMRMOVETOEX ( INT x, INT y )
    02540     {
    02541       emr.iType = EMR_MOVETOEX;
    02542       emr.nSize = sizeof( ::EMRMOVETOEX );
    02543       ptl.x = x;
    02544       ptl.y = y;
    02545     }
    02550     EMRMOVETOEX ( DATASTREAM& ds )
    02551     {
    02552       ds >> emr >> ptl;
    02553     }
    02557     bool serialize ( DATASTREAM ds )
    02558     {
    02559       ds << emr << ptl;
    02560       return true;
    02561     }
    02565     int size ( void ) const { return emr.nSize; }
    02571     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    02572     {
    02573       MoveToEx( dc,  ptl.x, ptl.y, 0 );
    02574     }
    02575 #ifdef ENABLE_EDITING
    02576
    02579     void edit ( void ) const
    02580     {
    02581       printf( "*MOVETOEX*\n" );
    02582       edit_pointl( "ptl", ptl );
    02583     }
    02584 #endif /* ENABLE_EDITING */
    02585   };
    02586
    02588
    02591   class EMRLINETO : public METARECORD, ::EMRLINETO {
    02592   public:
    02597     EMRLINETO ( INT x, INT y )
    02598     {
    02599       emr.iType = EMR_LINETO;
    02600       emr.nSize = sizeof( ::EMRLINETO );
    02601       ptl.x = x;
    02602       ptl.y = y;
    02603     }
    02608     EMRLINETO ( DATASTREAM& ds )
    02609     {
    02610       ds >> emr >> ptl;
    02611     }
    02615     bool serialize ( DATASTREAM ds )
    02616     {
    02617       ds << emr << ptl;
    02618       return true;
    02619     }
    02623     int size ( void ) const { return emr.nSize; }
    02629     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    02630     {
    02631       LineTo( dc,  ptl.x, ptl.y );
    02632     }
    02633 #ifdef ENABLE_EDITING
    02634
    02637     void edit ( void ) const
    02638     {
    02639       printf( "*LINETO*\n" );
    02640       edit_pointl( "ptl", ptl );
    02641     }
    02642 #endif /* ENABLE_EDITING */
    02643   };
    02644
    02646
    02649   class EMRARC : public METARECORD, ::EMRARC {
    02650   public:
    02662     EMRARC ( INT left, INT top, INT right, INT bottom, INT xstart,
    02663              INT ystart, INT xend, INT yend )
    02664     {
    02665       emr.iType = EMR_ARC;
    02666       emr.nSize = sizeof( ::EMRARC );
    02667       rclBox.left = left;
    02668       rclBox.right = right;
    02669       rclBox.bottom = bottom;
    02670       rclBox.top = top;
    02671       ptlStart.x = xstart;
    02672       ptlStart.y = ystart;
    02673       ptlEnd.x = xend;
    02674       ptlEnd.y = yend;
    02675     }
    02680     EMRARC ( DATASTREAM& ds )
    02681     {
    02682       ds >> emr >> rclBox >> ptlStart >> ptlEnd;
    02683     }
    02687     bool serialize ( DATASTREAM ds )
    02688     {
    02689       ds << emr << rclBox << ptlStart << ptlEnd;
    02690       return true;
    02691     }
    02695     int size ( void ) const { return emr.nSize; }
    02701     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    02702     {
    02703       Arc( dc, rclBox.left, rclBox.top, rclBox.right, rclBox.bottom,
    02704            ptlStart.x, ptlStart.y, ptlEnd.x, ptlEnd.y );
    02705     }
    02706 #ifdef ENABLE_EDITING
    02707
    02710     void edit ( void ) const
    02711     {
    02712       printf( "*ARC*\n" );
    02713       edit_rectl( "rclBox\t", rclBox );
    02714       edit_pointl( "ptlStart", ptlStart );
    02715       edit_pointl( "ptlEnd\t", ptlEnd );
    02716     }
    02717 #endif /* ENABLE_EDITING */
    02718   };
    02719
    02721
    02724   class EMRARCTO : public METARECORD, ::EMRARCTO {
    02725   public:
    02737     EMRARCTO ( INT left, INT top, INT right, INT bottom, INT xstart,
    02738              INT ystart, INT xend, INT yend )
    02739     {
    02740       emr.iType = EMR_ARCTO;
    02741       emr.nSize = sizeof( ::EMRARCTO );
    02742       rclBox.left = left;
    02743       rclBox.right = right;
    02744       rclBox.bottom = bottom;
    02745       rclBox.top = top;
    02746       ptlStart.x = xstart;
    02747       ptlStart.y = ystart;
    02748       ptlEnd.x = xend;
    02749       ptlEnd.y = yend;
    02750     }
    02755     EMRARCTO ( DATASTREAM& ds )
    02756     {
    02757       ds >> emr >> rclBox >> ptlStart >> ptlEnd;
    02758     }
    02762     bool serialize ( DATASTREAM ds )
    02763     {
    02764       ds << emr << rclBox << ptlStart << ptlEnd;
    02765       return true;
    02766     }
    02770     int size ( void ) const { return emr.nSize; }
    02776     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    02777     {
    02778       ArcTo( dc, rclBox.left, rclBox.top, rclBox.right, rclBox.bottom,
    02779              ptlStart.x, ptlStart.y, ptlEnd.x, ptlEnd.y );
    02780     }
    02781 #ifdef ENABLE_EDITING
    02782
    02785     void edit ( void ) const
    02786     {
    02787       printf( "*ARCTO*\n" );
    02788       edit_rectl( "rclBox\t", rclBox );
    02789       edit_pointl( "ptlStart", ptlStart );
    02790       edit_pointl( "ptlEnd\t", ptlEnd );
    02791     }
    02792 #endif /* ENABLE_EDITING */
    02793   };
    02794
    02796
    02799   class EMRRECTANGLE : public METARECORD, ::EMRRECTANGLE {
    02800   public:
    02807     EMRRECTANGLE ( INT left, INT top, INT right, INT bottom )
    02808     {
    02809       emr.iType = EMR_RECTANGLE;
    02810       emr.nSize = sizeof( ::EMRRECTANGLE );
    02811       rclBox.left = left;
    02812       rclBox.right = right;
    02813       rclBox.bottom = bottom;
    02814       rclBox.top = top;
    02815     }
    02820     EMRRECTANGLE ( DATASTREAM& ds )
    02821     {
    02822       ds >> emr >> rclBox;
    02823     }
    02827     bool serialize ( DATASTREAM ds )
    02828     {
    02829       ds << emr << rclBox;
    02830       return true;
    02831     }
    02835     int size ( void ) const { return emr.nSize; }
    02841     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    02842     {
    02843       Rectangle( dc, rclBox.left, rclBox.top, rclBox.right, rclBox.bottom );
    02844     }
    02845 #ifdef ENABLE_EDITING
    02846
    02849     void edit ( void ) const
    02850     {
    02851       printf( "*RECTANGLE*\n" );
    02852       edit_rectl( "rclBox", rclBox );
    02853     }
    02854 #endif /* ENABLE_EDITING */
    02855   };
    02856
    02858
    02861   class EMRELLIPSE : public METARECORD, ::EMRELLIPSE {
    02862   public:
    02870     EMRELLIPSE ( INT left, INT top, INT right, INT bottom )
    02871     {
    02872       emr.iType = EMR_ELLIPSE;
    02873       emr.nSize = sizeof( ::EMRELLIPSE );
    02874       rclBox.left = left;
    02875       rclBox.right = right;
    02876       rclBox.bottom = bottom;
    02877       rclBox.top = top;
    02878     }
    02883     EMRELLIPSE ( DATASTREAM& ds )
    02884     {
    02885       ds >> emr >> rclBox;
    02886     }
    02890     bool serialize ( DATASTREAM ds )
    02891     {
    02892       ds << emr << rclBox;
    02893       return true;
    02894     }
    02898     int size ( void ) const { return emr.nSize; }
    02904     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    02905     {
    02906       Ellipse( dc, rclBox.left, rclBox.top, rclBox.right, rclBox.bottom );
    02907     }
    02908 #ifdef ENABLE_EDITING
    02909
    02912     void edit ( void ) const
    02913     {
    02914       printf( "*ELLIPSE*\n" );
    02915       edit_rectl( "rclBox", rclBox );
    02916     }
    02917 #endif /* ENABLE_EDITING */
    02918   };
    02919
    02921
    02924   class EMRPOLYLINE : public METARECORD, ::EMRPOLYLINE {
    02925     POINTL* lpoints;
    02926   public:
    02932     EMRPOLYLINE ( const RECTL* bounds, const POINT* points, INT n )
    02933     {
    02934       cptl = n;
    02935       aptl[0].x = 0;            // Really unused
    02936       aptl[0].y = 0;
    02937
    02938       emr.iType = EMR_POLYLINE;
    02939       // The (cptl - 1) below is to account for aptl, which isn't written out
    02940       emr.nSize = sizeof( ::EMRPOLYLINE ) + sizeof( POINTL ) * ( cptl - 1);
    02941
    02942       lpoints = new POINTL[cptl];
    02943
    02944       for (int i=0; i<n; i++) {
    02945         lpoints[i].x = points[i].x;
    02946         lpoints[i].y = points[i].y;
    02947       }
    02948
    02949       rclBounds = *bounds;
    02950     }
    02954     ~EMRPOLYLINE ( )
    02955     {
    02956       if ( lpoints ) delete[] lpoints;
    02957     }
    02962     EMRPOLYLINE ( DATASTREAM& ds )
    02963     {
    02964       ds >> emr >> rclBounds >> cptl;
    02965
    02966       lpoints = new POINTL[cptl];
    02967
    02968       POINTLARRAY points( lpoints, cptl );
    02969
    02970       ds >> points;
    02971     }
    02975     bool serialize ( DATASTREAM ds )
    02976     {
    02977       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
    02978       return true;
    02979     }
    02983     int size ( void ) const { return emr.nSize; }
    02989     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    02990     {
    02991       // According to the wine windef.h header, POINT and POINTL are equivalent
    02992       Polyline( dc, (POINT*)lpoints, cptl );
    02993     }
    02994 #ifdef ENABLE_EDITING
    02995
    02998     void edit ( void ) const
    02999     {
    03000       printf( "*POLYLINE*\n" );
    03001       edit_rectl( "rclBounds", rclBounds );
    03002 #if 0
    03003       printf( "\tcptl              : %ld\n", cptl );
    03004       printf( "\taptl->\n" );
    03005       for ( unsigned int i = 0; i < cptl; i++ )
    03006         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
    03007 #else
    03008       edit_pointlarray( "\t", cptl, lpoints );
    03009 #endif
    03010     }
    03011 #endif /* ENABLE_EDITING */
    03012   };
    03013
    03015
    03018   class EMRPOLYLINE16 : public METARECORD, ::EMRPOLYLINE16 {
    03019     POINT16* lpoints;
    03020   public:
    03026     EMRPOLYLINE16 ( const RECTL* bounds, const POINT16* points, INT n )
    03027     {
    03028       cpts = n;
    03029       apts[0].x = 0;            // Really unused
    03030       apts[0].y = 0;
    03031
    03032       emr.iType = EMR_POLYLINE16;
    03033       // The (cptl - 1) below is to account for aptl, which isn't written out
    03034       emr.nSize = sizeof( ::EMRPOLYLINE16 ) + sizeof( POINT16 ) * ( cpts - 1);
    03035
    03036       lpoints = new POINT16[cpts];
    03037
    03038       for (int i=0; i<n; i++) {
    03039         lpoints[i].x = points[i].x;
    03040         lpoints[i].y = points[i].y;
    03041       }
    03042
    03043       rclBounds = *bounds;
    03044     }
    03051     EMRPOLYLINE16 ( const RECTL* bounds, const POINT* points, INT n )
    03052     {
    03053       cpts = n;
    03054       apts[0].x = 0;            // Really unused
    03055       apts[0].y = 0;
    03056
    03057       emr.iType = EMR_POLYLINE16;
    03058       // The (cptl - 1) below is to account for aptl, which isn't written out
    03059       emr.nSize = sizeof( ::EMRPOLYLINE16 ) + sizeof( POINT16 ) * ( cpts - 1);
    03060
    03061       lpoints = new POINT16[cpts];
    03062
    03063       for (int i=0; i<n; i++) {
    03064         lpoints[i].x = points[i].x;
    03065         lpoints[i].y = points[i].y;
    03066       }
    03067
    03068       rclBounds = *bounds;
    03069     }
    03073     ~EMRPOLYLINE16 ( )
    03074     {
    03075       if ( lpoints ) delete[] lpoints;
    03076     }
    03081     EMRPOLYLINE16 ( DATASTREAM& ds )
    03082     {
    03083       ds >> emr >> rclBounds >> cpts;
    03084
    03085       lpoints = new POINT16[cpts];
    03086
    03087       POINT16ARRAY points( lpoints, cpts );
    03088
    03089       ds >> points;
    03090     }
    03094     bool serialize ( DATASTREAM ds )
    03095     {
    03096       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
    03097       return true;
    03098     }
    03102     int size ( void ) const { return emr.nSize; }
    03108     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    03109     {
    03110       // According to the wine windef.h header, POINT and POINTL are equivalent
    03111       Polyline16( dc, lpoints, cpts );
    03112     }
    03113 #ifdef ENABLE_EDITING
    03114
    03117     void edit ( void ) const
    03118     {
    03119       printf( "*POLYLINE16*\n" );
    03120       edit_rectl( "rclBounds", rclBounds );
    03121       edit_point16array( "\t", cpts, lpoints );
    03122     }
    03123 #endif /* ENABLE_EDITING */
    03124   };
    03125
    03127
    03130   class EMRPOLYGON : public METARECORD, ::EMRPOLYGON {
    03131     POINTL* lpoints;
    03132   public:
    03138     EMRPOLYGON ( const RECTL* bounds, const POINT* points, INT n )
    03139     {
    03140       cptl = n;
    03141       aptl[0].x = 0;            // Really unused
    03142       aptl[0].y = 0;
    03143
    03144       emr.iType = EMR_POLYGON;
    03145       // The (cptl-1) below is to account for aptl, which isn't written out
    03146       emr.nSize = sizeof( ::EMRPOLYGON ) + sizeof( POINTL ) * (cptl-1);
    03147
    03148       lpoints = new POINTL[cptl];
    03149
    03150       for (int i=0; i<n; i++) {
    03151         lpoints[i].x = points[i].x;
    03152         lpoints[i].y = points[i].y;
    03153       }
    03154
    03155       rclBounds = *bounds;
    03156     }
    03161     EMRPOLYGON ( DATASTREAM& ds )
    03162     {
    03163       ds >> emr >> rclBounds >> cptl;
    03164
    03165       lpoints = new POINTL[cptl];
    03166
    03167       POINTLARRAY points( lpoints, cptl );
    03168
    03169       ds >> points;
    03170     }
    03174     ~EMRPOLYGON ( )
    03175     {
    03176       if ( lpoints ) delete[] lpoints;
    03177     }
    03181     bool serialize ( DATASTREAM ds )
    03182     {
    03183       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
    03184       return true;
    03185     }
    03189     int size ( void ) const { return emr.nSize; }
    03195     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    03196     {
    03197       // According to the wine windef.h header, POINT and POINTL are equivalent
    03198       Polygon( dc, (POINT*)lpoints, cptl );
    03199     }
    03200 #ifdef ENABLE_EDITING
    03201
    03204     void edit ( void ) const
    03205     {
    03206       printf( "*POLYGON*\n" );
    03207       edit_rectl( "rclBounds", rclBounds );
    03208 #if 0
    03209       printf( "\tcptl              : %ld\n", cptl );
    03210       printf( "\taptl->\n" );
    03211       for ( unsigned int i = 0; i < cptl; i++ )
    03212         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
    03213 #else
    03214       edit_pointlarray( "\t", cptl, lpoints );
    03215 #endif
    03216     }
    03217 #endif /* ENABLE_EDITING */
    03218   };
    03219
    03221
    03224   class EMRPOLYGON16 : public METARECORD, ::EMRPOLYGON16 {
    03225     POINT16* lpoints;
    03226   public:
    03232     EMRPOLYGON16 ( const RECTL* bounds, const POINT* points, INT16 n )
    03233     {
    03234       cpts = n;
    03235       apts[0].x = 0;            // Really unused
    03236       apts[0].y = 0;
    03237
    03238       emr.iType = EMR_POLYGON16;
    03239       // The (cptl-1) below is to account for aptl, which isn't written out
    03240       emr.nSize = sizeof( ::EMRPOLYGON16 ) + sizeof( POINT16 ) * (cpts-1);
    03241
    03242       lpoints = new POINT16[cpts];
    03243
    03244       for (int i=0; i<n; i++) {
    03245         lpoints[i].x = points[i].x;
    03246         lpoints[i].y = points[i].y;
    03247       }
    03248
    03249       rclBounds = *bounds;
    03250     }
    03257     EMRPOLYGON16 ( const RECTL* bounds, const POINT16* points, INT16 n )
    03258     {
    03259       cpts = n;
    03260       apts[0].x = 0;            // Really unused
    03261       apts[0].y = 0;
    03262
    03263       emr.iType = EMR_POLYGON16;
    03264       // The (cptl-1) below is to account for aptl, which isn't written out
    03265       emr.nSize = sizeof( ::EMRPOLYGON16 ) + sizeof( POINT16 ) * (cpts-1);
    03266
    03267       lpoints = new POINT16[cpts];
    03268
    03269       for (int i=0; i<n; i++) {
    03270         lpoints[i].x = points[i].x;
    03271         lpoints[i].y = points[i].y;
    03272       }
    03273
    03274       rclBounds = *bounds;
    03275     }
    03280     EMRPOLYGON16 ( DATASTREAM& ds )
    03281     {
    03282       ds >> emr >> rclBounds >> cpts;
    03283
    03284       lpoints = new POINT16[cpts];
    03285
    03286       POINT16ARRAY points( lpoints, cpts );
    03287
    03288       ds >> points;
    03289     }
    03293     ~EMRPOLYGON16 ( )
    03294     {
    03295       if ( lpoints ) delete[] lpoints;
    03296     }
    03300     bool serialize ( DATASTREAM ds )
    03301     {
    03302       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
    03303       return true;
    03304     }
    03308     int size ( void ) const { return emr.nSize; }
    03314     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    03315     {
    03316       // According to the wine windef.h header, POINT and POINTL are equivalent
    03317       Polygon16( dc, lpoints, cpts );
    03318     }
    03319 #ifdef ENABLE_EDITING
    03320
    03323     void edit ( void ) const
    03324     {
    03325       printf( "*POLYGON16*\n" );
    03326       edit_rectl( "rclBounds", rclBounds );
    03327       edit_point16array( "\t", cpts, lpoints );
    03328     }
    03329 #endif /* ENABLE_EDITING */
    03330   };
    03331
    03333
    03336   class EMRPOLYPOLYGON : public METARECORD, ::EMRPOLYPOLYGON {
    03337     DWORD* lcounts;
    03338     POINTL* lpoints;
    03339   public:
    03346     EMRPOLYPOLYGON ( const RECTL* bounds, const POINT* points, const INT* counts,
    03347                      UINT polygons )
    03348     {
    03349       nPolys = polygons;
    03350       // Count the number of points in points
    03351       int n = 0;
    03352       for ( unsigned int i = 0; i < nPolys; i++ )
    03353         n += counts[i];
    03354
    03355       cptl = n;
    03356       aPolyCounts[0] = 0;       // Really unused
    03357       aptl[0].x = 0;
    03358       aptl[0].y = 0;
    03359
    03360       emr.iType = EMR_POLYPOLYGON;
    03361       // The (#-1)'s below are to account for aPolyCounts[0] and aptl[0], which
    03362       // aren't directly written out
    03363       emr.nSize = sizeof( ::EMRPOLYPOLYGON ) + sizeof( POINTL ) * (cptl-1)
    03364         + sizeof( DWORD ) * (nPolys-1);
    03365
    03366       lcounts = new DWORD[nPolys];
    03367
    03368       for ( unsigned int i = 0; i < nPolys; i++ )
    03369         lcounts[i] = counts[i];
    03370
    03371       lpoints = new POINTL[cptl];
    03372
    03373       for (int i=0; i<n; i++) {
    03374         lpoints[i].x = points[i].x;
    03375         lpoints[i].y = points[i].y;
    03376       }
    03377
    03378       rclBounds = *bounds;
    03379     }
    03383     ~EMRPOLYPOLYGON ( )
    03384     {
    03385       if ( lcounts ) delete[] lcounts;
    03386       if ( lpoints ) delete[] lpoints;
    03387     }
    03392     EMRPOLYPOLYGON ( DATASTREAM& ds )
    03393     {
    03394       ds >> emr >> rclBounds >> nPolys >> cptl;
    03395
    03396       lcounts = new DWORD[nPolys];
    03397
    03398       DWORDARRAY counts( lcounts, nPolys );
    03399
    03400       ds >> counts;
    03401
    03402       lpoints = new POINTL[cptl];
    03403
    03404       POINTLARRAY points( lpoints, cptl );
    03405
    03406       ds >> points;
    03407     }
    03411     bool serialize ( DATASTREAM ds )
    03412     {
    03413       ds << emr << rclBounds << nPolys << cptl << DWORDARRAY( lcounts, nPolys )
    03414          << POINTLARRAY( lpoints, cptl );
    03415       return true;
    03416     }
    03420     int size ( void ) const { return emr.nSize; }
    03426     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    03427     {
    03428       // According to the wine windef.h header, POINT and POINTL are equivalent
    03429       // (but DWORD and INT are not)
    03430       INT* counts = new INT[nPolys];
    03431       for ( unsigned int i = 0; i < nPolys; i++ )
    03432         counts[i] = lcounts[i];
    03433
    03434       PolyPolygon( dc, (POINT*)lpoints, counts, nPolys );
    03435
    03436       delete[] counts;
    03437     }
    03438 #ifdef ENABLE_EDITING
    03439
    03442     void edit ( void ) const
    03443     {
    03444       printf( "*POLYPOLYGON*\n" );
    03445       edit_rectl( "rclBounds", rclBounds );
    03446       printf( "\tnPolys\t\t: %ld\n", nPolys );
    03447       printf( "\tcptl\t\t: %ld\n", cptl );
    03448       printf( "\taPolyCounts\t: " );
    03449       if ( nPolys > 0 )
    03450         printf( "%ld\n", lcounts[0] );
    03451       else
    03452         puts( "" );
    03453       for ( unsigned int i = 1; i < nPolys; i++ )
    03454         printf( "\t\t\t  %ld\n", lcounts[i] );
    03455       printf( "\tapts\t\t: " );
    03456       if ( cptl > 0 )
    03457         printf( "%ld, %ld\n", lpoints[0].x, lpoints[0].y );
    03458       else
    03459         puts( "" );
    03460       for ( unsigned int i = 1; i < cptl; i++ )
    03461         printf( "\t\t\t  %ld, %ld\n", lpoints[i].x, lpoints[i].y );
    03462     }
    03463 #endif /* ENABLE_EDITING */
    03464   };
    03465
    03467
    03470   class EMRPOLYPOLYGON16 : public METARECORD, ::EMRPOLYPOLYGON16 {
    03471     DWORD* lcounts;
    03472     POINT16* lpoints;
    03473   public:
    03480     EMRPOLYPOLYGON16 ( const RECTL* bounds, const POINT* points,
    03481                        const INT* counts, UINT polygons )
    03482     {
    03483       nPolys = polygons;
    03484       // Count the number of points in points
    03485       int n = 0;
    03486       for ( unsigned int i = 0; i < nPolys; i++ )
    03487         n += counts[i];
    03488
    03489       cpts = n;
    03490       aPolyCounts[0] = 0;       // Really unused
    03491       apts[0].x = 0;
    03492       apts[0].y = 0;
    03493
    03494       emr.iType = EMR_POLYPOLYGON16;
    03495       // The (#-1)'s below are to account for aPolyCounts[0] and aptl[0], which
    03496       // aren't directly written out
    03497       emr.nSize = sizeof( ::EMRPOLYPOLYGON16 ) + sizeof( POINT16 ) * (cpts-1)
    03498         + sizeof( DWORD ) * (nPolys-1);
    03499
    03500       lcounts = new DWORD[nPolys];
    03501
    03502       for ( unsigned int i = 0; i < nPolys; i++ )
    03503         lcounts[i] = counts[i];
    03504
    03505       lpoints = new POINT16[cpts];
    03506
    03507       for (int i=0; i<n; i++) {
    03508         lpoints[i].x = points[i].x;
    03509         lpoints[i].y = points[i].y;
    03510       }
    03511
    03512       rclBounds = *bounds;
    03513     }
    03521     EMRPOLYPOLYGON16 ( const RECTL* bounds, const POINT16* points,
    03522                        const INT* counts, UINT16 polygons )
    03523     {
    03524       nPolys = polygons;
    03525       // Count the number of points in points
    03526       int n = 0;
    03527       for ( unsigned int i = 0; i < nPolys; i++ )
    03528         n += counts[i];
    03529
    03530       cpts = n;
    03531       aPolyCounts[0] = 0;       // Really unused
    03532       apts[0].x = 0;
    03533       apts[0].y = 0;
    03534
    03535       emr.iType = EMR_POLYPOLYGON16;
    03536       // The (#-1)'s below are to account for aPolyCounts[0] and aptl[0], which
    03537       // aren't directly written out
    03538       emr.nSize = sizeof( ::EMRPOLYPOLYGON16 ) + sizeof( POINT16 ) * (cpts-1)
    03539         + sizeof( DWORD ) * (nPolys-1);
    03540
    03541       lcounts = new DWORD[nPolys];
    03542
    03543       for ( unsigned int i = 0; i < nPolys; i++ )
    03544         lcounts[i] = counts[i];
    03545
    03546       lpoints = new POINT16[cpts];
    03547
    03548       for (int i=0; i<n; i++) {
    03549         lpoints[i].x = points[i].x;
    03550         lpoints[i].y = points[i].y;
    03551       }
    03552
    03553       rclBounds = *bounds;
    03554     }
    03558     ~EMRPOLYPOLYGON16 ( )
    03559     {
    03560       if ( lcounts ) delete[] lcounts;
    03561       if ( lpoints ) delete[] lpoints;
    03562     }
    03567     EMRPOLYPOLYGON16 ( DATASTREAM& ds )
    03568     {
    03569       ds >> emr >> rclBounds >> nPolys >> cpts;
    03570
    03571       lcounts = new DWORD[nPolys];
    03572
    03573       DWORDARRAY counts( lcounts, nPolys );
    03574
    03575       ds >> counts;
    03576
    03577       lpoints = new POINT16[cpts];
    03578
    03579       POINT16ARRAY points( lpoints, cpts );
    03580
    03581       ds >> points;
    03582     }
    03586     bool serialize ( DATASTREAM ds )
    03587     {
    03588       ds << emr << rclBounds << nPolys << cpts << DWORDARRAY( lcounts, nPolys )
    03589          << POINT16ARRAY( lpoints, cpts );
    03590       return true;
    03591     }
    03595     int size ( void ) const { return emr.nSize; }
    03601     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    03602     {
    03603       // According to the wine windef.h header, POINT and POINTL are equivalent
    03604       // (but DWORD and INT are not)
    03605       INT* counts = new INT[nPolys];
    03606       for ( unsigned int i = 0; i < nPolys; i++ )
    03607         counts[i] = lcounts[i];
    03608
    03609       PolyPolygon16( dc, lpoints, counts, nPolys );
    03610
    03611       delete[] counts;
    03612     }
    03613 #ifdef ENABLE_EDITING
    03614
    03617     void edit ( void ) const
    03618     {
    03619       printf( "*POLYPOLYGON16*\n" );
    03620       edit_rectl( "rclBounds", rclBounds );
    03621       printf( "\tnPolys\t\t: %ld\n", nPolys );
    03622       printf( "\tcpts\t\t: %ld\n", cpts );
    03623       printf( "\taPolyCounts\t: " );
    03624       if ( nPolys > 0 )
    03625         printf( "%ld\n", lcounts[0] );
    03626       else
    03627         puts( "" );
    03628       for ( unsigned int i = 1; i < nPolys; i++ )
    03629         printf( "\t\t\t  %ld\n", lcounts[i] );
    03630       printf( "\tapts\t\t: " );
    03631       if ( cpts > 0 )
    03632         printf( "%d, %d\n", lpoints[0].x, lpoints[0].y );
    03633       else
    03634         puts( "" );
    03635       for ( unsigned int i = 1; i < cpts; i++ )
    03636         printf( "\t\t\t  %d, %d\n", lpoints[i].x, lpoints[i].y );
    03637     }
    03638 #endif /* ENABLE_EDITING */
    03639   };
    03640
    03642
    03645   class EMRPOLYBEZIER : public METARECORD, ::EMRPOLYBEZIER {
    03646     POINTL* lpoints;
    03647   public:
    03653     EMRPOLYBEZIER ( const RECTL* bounds, const POINT* points, INT n )
    03654     {
    03655       cptl = n;
    03656       aptl[0].x = 0;            // Really unused
    03657       aptl[0].y = 0;
    03658
    03659       emr.iType = EMR_POLYBEZIER;
    03660       // The (cptl-1) below is to account for aptl, which isn't written out
    03661       emr.nSize = sizeof( ::EMRPOLYBEZIER ) + sizeof( POINTL ) * (cptl-1);
    03662
    03663       lpoints = new POINTL[cptl];
    03664
    03665       for (int i=0; i<n; i++) {
    03666         lpoints[i].x = points[i].x;
    03667         lpoints[i].y = points[i].y;
    03668       }
    03669
    03670       rclBounds = *bounds;
    03671     }
    03676     EMRPOLYBEZIER ( DATASTREAM& ds )
    03677     {
    03678       ds >> emr >> rclBounds >> cptl;
    03679
    03680       lpoints = new POINTL[cptl];
    03681
    03682       POINTLARRAY points( lpoints, cptl );
    03683
    03684       ds >> points;
    03685     }
    03689     ~EMRPOLYBEZIER ( )
    03690     {
    03691       if ( lpoints ) delete[] lpoints;
    03692     }
    03696     bool serialize ( DATASTREAM ds )
    03697     {
    03698       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
    03699       return true;
    03700     }
    03704     int size ( void ) const { return emr.nSize; }
    03710     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    03711     {
    03712       // According to the wine windef.h header, POINT and POINTL are equivalent
    03713       PolyBezier( dc, (POINT*)lpoints, cptl );
    03714     }
    03715 #ifdef ENABLE_EDITING
    03716
    03719     void edit ( void ) const
    03720     {
    03721       printf( "*POLYBEZIER*\n" );
    03722       edit_rectl( "rclBounds", rclBounds );
    03723 #if 0
    03724       printf( "\tcptl              : %ld\n", cptl );
    03725       printf( "\taptl->\n" );
    03726       for ( unsigned int i = 0; i < cptl; i++ )
    03727         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
    03728 #else
    03729       edit_pointlarray( "\t", cptl, lpoints );
    03730 #endif
    03731     }
    03732 #endif /* ENABLE_EDITING */
    03733   };
    03734
    03736
    03739   class EMRPOLYBEZIER16 : public METARECORD, ::EMRPOLYBEZIER16 {
    03740     POINT16* lpoints;
    03741   public:
    03747     EMRPOLYBEZIER16 ( const RECTL* bounds, const POINT16* points, INT n )
    03748     {
    03749       cpts = n;
    03750       apts[0].x = 0;            // Really unused
    03751       apts[0].y = 0;
    03752
    03753       emr.iType = EMR_POLYBEZIER16;
    03754       // The (cptl-1) below is to account for aptl, which isn't written out
    03755       emr.nSize = sizeof( ::EMRPOLYBEZIER16 ) + sizeof( POINT16 ) * (cpts-1);
    03756
    03757       lpoints = new POINT16[cpts];
    03758
    03759       for (int i=0; i<n; i++) {
    03760         lpoints[i].x = points[i].x;
    03761         lpoints[i].y = points[i].y;
    03762       }
    03763
    03764       rclBounds = *bounds;
    03765     }
    03772     EMRPOLYBEZIER16 ( const RECTL* bounds, const POINT* points, INT n )
    03773     {
    03774       cpts = n;
    03775       apts[0].x = 0;            // Really unused
    03776       apts[0].y = 0;
    03777
    03778       emr.iType = EMR_POLYBEZIER16;
    03779       // The (cptl-1) below is to account for aptl, which isn't written out
    03780       emr.nSize = sizeof( ::EMRPOLYBEZIER16 ) + sizeof( POINT16 ) * (cpts-1);
    03781
    03782       lpoints = new POINT16[cpts];
    03783
    03784       for (int i=0; i<n; i++) {
    03785         lpoints[i].x = points[i].x;
    03786         lpoints[i].y = points[i].y;
    03787       }
    03788
    03789       rclBounds = *bounds;
    03790     }
    03795     EMRPOLYBEZIER16 ( DATASTREAM& ds )
    03796     {
    03797       ds >> emr >> rclBounds >> cpts;
    03798
    03799       lpoints = new POINT16[cpts];
    03800
    03801       POINT16ARRAY points( lpoints, cpts );
    03802
    03803       ds >> points;
    03804     }
    03808     ~EMRPOLYBEZIER16 ( )
    03809     {
    03810       if ( lpoints ) delete[] lpoints;
    03811     }
    03815     bool serialize ( DATASTREAM ds )
    03816     {
    03817       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
    03818       return true;
    03819     }
    03823     int size ( void ) const { return emr.nSize; }
    03829     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    03830     {
    03831       // According to the wine windef.h header, POINT and POINTL are equivalent
    03832       PolyBezier16( dc, lpoints, cpts );
    03833     }
    03834 #ifdef ENABLE_EDITING
    03835
    03838     void edit ( void ) const
    03839     {
    03840       printf( "*POLYBEZIER16*\n" );
    03841       edit_rectl( "rclBounds", rclBounds );
    03842       edit_point16array( "\t", cpts, lpoints );
    03843     }
    03844 #endif /* ENABLE_EDITING */
    03845   };
    03846
    03848
    03851   class EMRPOLYBEZIERTO : public METARECORD, ::EMRPOLYBEZIER {
    03852     POINTL* lpoints;
    03853   public:
    03859     EMRPOLYBEZIERTO ( const RECTL* bounds, const POINT* points, INT n )
    03860     {
    03861       cptl = n;
    03862       aptl[0].x = 0;            // Really unused
    03863       aptl[0].y = 0;
    03864
    03865       emr.iType = EMR_POLYBEZIERTO;
    03866       // The (cptl-1) below is to account for aptl, which isn't written out
    03867       emr.nSize = sizeof( ::EMRPOLYBEZIERTO ) + sizeof( POINTL ) * (cptl-1);
    03868
    03869       lpoints = new POINTL[cptl];
    03870
    03871       for (int i=0; i<n; i++) {
    03872         lpoints[i].x = points[i].x;
    03873         lpoints[i].y = points[i].y;
    03874       }
    03875
    03876       rclBounds = *bounds;
    03877     }
    03882     EMRPOLYBEZIERTO ( DATASTREAM& ds )
    03883     {
    03884       ds >> emr >> rclBounds >> cptl;
    03885
    03886       lpoints = new POINTL[cptl];
    03887
    03888       POINTLARRAY points( lpoints, cptl );
    03889
    03890       ds >> points;
    03891     }
    03895     ~EMRPOLYBEZIERTO ( )
    03896     {
    03897       if ( lpoints ) delete[] lpoints;
    03898     }
    03902     bool serialize ( DATASTREAM ds )
    03903     {
    03904       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
    03905       return true;
    03906     }
    03910     int size ( void ) const { return emr.nSize; }
    03916     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    03917     {
    03918       // According to the wine windef.h header, POINT and POINTL are equivalent
    03919       PolyBezierTo( dc, (POINT*)lpoints, cptl );
    03920     }
    03921 #ifdef ENABLE_EDITING
    03922
    03925     void edit ( void ) const
    03926     {
    03927       printf( "*POLYBEZIERTO*\n" );
    03928       edit_rectl( "rclBounds", rclBounds );
    03929 #if 0
    03930       printf( "\tcptl              : %ld\n", cptl );
    03931       printf( "\taptl->\n" );
    03932       for ( unsigned int i = 0; i < cptl; i++ )
    03933         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
    03934 #else
    03935       edit_pointlarray( "\t", cptl, lpoints );
    03936 #endif
    03937     }
    03938 #endif /* ENABLE_EDITING */
    03939   };
    03940
    03942
    03945   class EMRPOLYBEZIERTO16 : public METARECORD, ::EMRPOLYBEZIER16 {
    03946     POINT16* lpoints;
    03947   public:
    03953     EMRPOLYBEZIERTO16 ( const RECTL* bounds, const POINT16* points, INT n )
    03954     {
    03955       cpts = n;
    03956       apts[0].x = 0;            // Really unused
    03957       apts[0].y = 0;
    03958
    03959       emr.iType = EMR_POLYBEZIERTO16;
    03960       // The (cptl-1) below is to account for aptl, which isn't written out
    03961       emr.nSize = sizeof( ::EMRPOLYBEZIERTO16 ) + sizeof( POINT16 ) * (cpts-1);
    03962
    03963       lpoints = new POINT16[cpts];
    03964
    03965       for (int i=0; i<n; i++) {
    03966         lpoints[i].x = points[i].x;
    03967         lpoints[i].y = points[i].y;
    03968       }
    03969
    03970       rclBounds = *bounds;
    03971     }
    03978     EMRPOLYBEZIERTO16 ( const RECTL* bounds, const POINT* points, INT n )
    03979     {
    03980       cpts = n;
    03981       apts[0].x = 0;            // Really unused
    03982       apts[0].y = 0;
    03983
    03984       emr.iType = EMR_POLYBEZIERTO16;
    03985       // The (cptl-1) below is to account for aptl, which isn't written out
    03986       emr.nSize = sizeof( ::EMRPOLYBEZIERTO16 ) + sizeof( POINT16 ) * (cpts-1);
    03987
    03988       lpoints = new POINT16[cpts];
    03989
    03990       for (int i=0; i<n; i++) {
    03991         lpoints[i].x = points[i].x;
    03992         lpoints[i].y = points[i].y;
    03993       }
    03994
    03995       rclBounds = *bounds;
    03996     }
    04001     EMRPOLYBEZIERTO16 ( DATASTREAM& ds )
    04002     {
    04003       ds >> emr >> rclBounds >> cpts;
    04004
    04005       lpoints = new POINT16[cpts];
    04006
    04007       POINT16ARRAY points( lpoints, cpts );
    04008
    04009       ds >> points;
    04010     }
    04014     ~EMRPOLYBEZIERTO16 ( )
    04015     {
    04016       if ( lpoints ) delete[] lpoints;
    04017     }
    04021     bool serialize ( DATASTREAM ds )
    04022     {
    04023       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
    04024       return true;
    04025     }
    04029     int size ( void ) const { return emr.nSize; }
    04035     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    04036     {
    04037       // According to the wine windef.h header, POINT and POINTL are equivalent
    04038       PolyBezierTo16( dc, lpoints, cpts );
    04039     }
    04040 #ifdef ENABLE_EDITING
    04041
    04044     void edit ( void ) const
    04045     {
    04046       printf( "*POLYBEZIERTO16*\n" );
    04047       edit_rectl( "rclBounds", rclBounds );
    04048       edit_point16array( "\t", cpts, lpoints );
    04049     }
    04050 #endif /* ENABLE_EDITING */
    04051   };
    04052
    04054
    04057   class EMRPOLYLINETO : public METARECORD, ::EMRPOLYLINETO {
    04058     POINTL* lpoints;
    04059   public:
    04065     EMRPOLYLINETO ( const RECTL* bounds, const POINT* points, INT n )
    04066     {
    04067       cptl = n;
    04068       aptl[0].x = 0;
    04069       aptl[0].y = 0;
    04070
    04071       emr.iType = EMR_POLYLINETO;
    04072       // The (cptl-1) below is to account for aptl, which isn't written out
    04073       emr.nSize = sizeof( ::EMRPOLYLINETO ) + sizeof( POINTL ) * (cptl-1);
    04074
    04075       lpoints = new POINTL[cptl];
    04076
    04077       for (int i=0; i<n; i++) {
    04078         lpoints[i].x = points[i].x;
    04079         lpoints[i].y = points[i].y;
    04080       }
    04081
    04082       rclBounds = *bounds;
    04083     }
    04088     EMRPOLYLINETO ( DATASTREAM& ds )
    04089     {
    04090       ds >> emr >> rclBounds >> cptl;
    04091
    04092       lpoints = new POINTL[cptl];
    04093
    04094       POINTLARRAY points( lpoints, cptl );
    04095
    04096       ds >> points;
    04097     }
    04101     ~EMRPOLYLINETO ( )
    04102     {
    04103       if ( lpoints ) delete[] lpoints;
    04104     }
    04108     bool serialize ( DATASTREAM ds )
    04109     {
    04110       ds << emr << rclBounds << cptl << POINTLARRAY( lpoints, cptl );
    04111       return true;
    04112     }
    04116     int size ( void ) const { return emr.nSize; }
    04122     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    04123     {
    04124       // According to the wine windef.h header, POINT and POINTL are equivalent
    04125       PolylineTo( dc, (POINT*)lpoints, cptl );
    04126     }
    04127 #ifdef ENABLE_EDITING
    04128
    04131     void edit ( void ) const
    04132     {
    04133       printf( "*POLYLINETO*\n" );
    04134       edit_rectl( "rclBounds", rclBounds );
    04135 #if 0
    04136       printf( "\tcptl              : %ld\n", cptl );
    04137       printf( "\taptl->\n" );
    04138       for ( unsigned int i = 0; i < cptl; i++ )
    04139         printf( "\t\t%ld, %ld\n", lpoints[i].x, lpoints[i].y );
    04140 #else
    04141       edit_pointlarray( "\t", cptl, lpoints );
    04142 #endif
    04143     }
    04144 #endif /* ENABLE_EDITING */
    04145   };
    04146
    04148
    04151   class EMRPOLYLINETO16 : public METARECORD, ::EMRPOLYLINETO16 {
    04152     POINT16* lpoints;
    04153   public:
    04159     EMRPOLYLINETO16 ( const RECTL* bounds, const POINT16* points, INT n )
    04160     {
    04161       cpts = n;
    04162       apts[0].x = 0;
    04163       apts[0].y = 0;
    04164
    04165       emr.iType = EMR_POLYLINETO16;
    04166       // The (cptl-1) below is to account for aptl, which isn't written out
    04167       emr.nSize = sizeof( ::EMRPOLYLINETO16 ) + sizeof( POINT16 ) * (cpts-1);
    04168
    04169       lpoints = new POINT16[cpts];
    04170
    04171       for (int i=0; i<n; i++) {
    04172         lpoints[i].x = points[i].x;
    04173         lpoints[i].y = points[i].y;
    04174       }
    04175
    04176       rclBounds = *bounds;
    04177     }
    04184     EMRPOLYLINETO16 ( const RECTL* bounds, const POINT* points, INT n )
    04185     {
    04186       cpts = n;
    04187       apts[0].x = 0;
    04188       apts[0].y = 0;
    04189
    04190       emr.iType = EMR_POLYLINETO16;
    04191       // The (cptl-1) below is to account for aptl, which isn't written out
    04192       emr.nSize = sizeof( ::EMRPOLYLINETO16 ) + sizeof( POINT16 ) * (cpts-1);
    04193
    04194       lpoints = new POINT16[cpts];
    04195
    04196       for (int i=0; i<n; i++) {
    04197         lpoints[i].x = points[i].x;
    04198         lpoints[i].y = points[i].y;
    04199       }
    04200
    04201       rclBounds = *bounds;
    04202     }
    04207     EMRPOLYLINETO16 ( DATASTREAM& ds )
    04208     {
    04209       ds >> emr >> rclBounds >> cpts;
    04210
    04211       lpoints = new POINT16[cpts];
    04212
    04213       POINT16ARRAY points( lpoints, cpts );
    04214
    04215       ds >> points;
    04216     }
    04220     ~EMRPOLYLINETO16 ( )
    04221     {
    04222       if ( lpoints ) delete[] lpoints;
    04223     }
    04227     bool serialize ( DATASTREAM ds )
    04228     {
    04229       ds << emr << rclBounds << cpts << POINT16ARRAY( lpoints, cpts );
    04230       return true;
    04231     }
    04235     int size ( void ) const { return emr.nSize; }
    04241     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    04242     {
    04243       // According to the wine windef.h header, POINT and POINTL are equivalent
    04244       PolylineTo16( dc, lpoints, cpts );
    04245     }
    04246 #ifdef ENABLE_EDITING
    04247
    04250     void edit ( void ) const
    04251     {
    04252       printf( "*POLYLINETO16*\n" );
    04253       edit_rectl( "rclBounds", rclBounds );
    04254       edit_point16array( "\t", cpts, lpoints );
    04255     }
    04256 #endif /* ENABLE_EDITING */
    04257   };
    04258
    04260
    04265   class EMREXTTEXTOUTA : public METARECORD, ::EMREXTTEXTOUTA {
    04266     PSTR string_a;
    04267     int string_size;
    04268
    04269     INT* dx_i;
    04270   public:
    04280     EMREXTTEXTOUTA ( const RECTL* bounds, DWORD graphicsMode, FLOAT xScale,
    04281                      FLOAT yScale, const PEMRTEXT text, LPCSTR string,
    04282                      const INT* dx )
    04283     {
    04284       emr.iType = EMR_EXTTEXTOUTA;
    04285       emr.nSize = sizeof( ::EMREXTTEXTOUTA );
    04286
    04287       rclBounds = *bounds;
    04288
    04289       iGraphicsMode = graphicsMode;
    04290       exScale = xScale;
    04291       eyScale = yScale;
    04292
    04293       emrtext = *text;
    04294
    04295       string_size = ROUND_TO_LONG( emrtext.nChars );
    04296
    04297       string_a = new CHAR[ string_size ];
    04298
    04299       memset( string_a, 0, sizeof(CHAR) * string_size );
    04300
    04301       for ( unsigned int i=0; i<emrtext.nChars; i++ )
    04302         string_a[i] = *string++;
    04303
    04304       emrtext.offString = emr.nSize;
    04305       emr.nSize += string_size * sizeof(CHAR);
    04306
    04307       if ( dx ) {
    04308
    04309         dx_i = new INT[ emrtext.nChars ];
    04310
    04311         for ( unsigned int i=0; i<emrtext.nChars; i++ )
    04312           dx_i[i] = *dx++;
    04313
    04314         emrtext.offDx = emr.nSize;
    04315         emr.nSize += emrtext.nChars * sizeof(INT);
    04316       }
    04317       else {
    04318         emrtext.offDx = 0;
    04319         dx_i = 0;
    04320       }
    04321     }
    04326     EMREXTTEXTOUTA ( DATASTREAM& ds )
    04327     {
    04328       ds >> emr >> rclBounds >> iGraphicsMode >> exScale >> eyScale >> emrtext;
    04329
    04330       if ( emrtext.offString != 0 ) {
    04331         string_size = ROUND_TO_LONG( emrtext.nChars );
    04332
    04333         string_a = new CHAR[ string_size ];
    04334
    04335         memset( string_a, 0, sizeof(CHAR) * string_size );
    04336
    04337         CHARSTR string( string_a, string_size );
    04338
    04339         ds >> string;
    04340       }
    04341       else
    04342         string_a = 0;
    04343
    04344       if ( emrtext.offDx ) {
    04345         dx_i = new INT[ emrtext.nChars ];
    04346
    04347         INTARRAY dx_is( dx_i, emrtext.nChars );
    04348
    04349         ds >> dx_is;
    04350       }
    04351       else
    04352         dx_i = 0;
    04353     }
    04358     ~EMREXTTEXTOUTA ( )
    04359     {
    04360       if ( string_a ) delete[] string_a;
    04361       if ( dx_i ) delete[] dx_i;
    04362     }
    04366     bool serialize ( DATASTREAM ds )
    04367     {
    04368       ds << emr << rclBounds << iGraphicsMode << exScale << eyScale
    04369          << emrtext << CHARSTR( string_a, string_size );
    04370       if ( dx_i )
    04371         ds << INTARRAY( dx_i, emrtext.nChars );
    04372       return true;
    04373     }
    04377     int size ( void ) const { return emr.nSize; }
    04383     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    04384     {
    04385       RECT rect;
    04386       rect.left = emrtext.rcl.left;
    04387       rect.top = emrtext.rcl.top;
    04388       rect.right = emrtext.rcl.right;
    04389       rect.bottom = emrtext.rcl.bottom;
    04390
    04391       ExtTextOutA( dc, emrtext.ptlReference.x, emrtext.ptlReference.y,
    04392                    emrtext.fOptions, &rect, string_a, emrtext.nChars,
    04393                    dx_i );
    04394     }
    04395 #ifdef ENABLE_EDITING
    04396
    04399     void edit ( void ) const
    04400     {
    04401       printf( "*EXTTEXTOUTA*\n" );
    04402       edit_rectl( "rclBounds", rclBounds );
    04403       printf( "\tiGraphicsMode\t: " );
    04404       switch ( iGraphicsMode ) {
    04405       case GM_COMPATIBLE: printf( "GM_COMPATIBLE\n" ); break;
    04406       case GM_ADVANCED: printf( "GM_ADVANCED\n" ); break;
    04407       default: printf( "unknown(%ld)\n", iGraphicsMode );
    04408       }
    04409       printf( "\texScale\t\t: %f\n", exScale );
    04410       printf( "\teyScale\t\t: %f\n", eyScale );
    04411       printf( "\tptlReference\t: (%ld,%ld)\n", emrtext.ptlReference.x,
    04412               emrtext.ptlReference.y );
    04413       printf( "\tnChars\t\t: %ld\n", emrtext.nChars );
    04414       printf( "\toffString\t: %ld\n", emrtext.offString );
    04415       printf( "\tfOptions\t: " );
    04416       if ( emrtext.fOptions == 0 )
    04417         printf( "None" );
    04418       else {
    04419         if ( emrtext.fOptions & ETO_GRAYED ) {
    04420           printf( "ETO_GRAYED" );
    04421           if ( emrtext.fOptions & ~ETO_GRAYED )
    04422             printf( " | " );
    04423         }
    04424         if ( emrtext.fOptions & ETO_OPAQUE ) {
    04425           printf( "ETO_OPAQUE" );
    04426           if ( emrtext.fOptions & ~(ETO_GRAYED | ETO_OPAQUE) )
    04427             printf( " | " );
    04428         }
    04429         if ( emrtext.fOptions & ETO_CLIPPED ) {
    04430           printf( "ETO_CLIPPED" );
    04431           if ( emrtext.fOptions & ~(ETO_GRAYED | ETO_OPAQUE | ETO_CLIPPED ) )
    04432             printf( " | " );
    04433         }
    04434         if ( emrtext.fOptions & ETO_GLYPH_INDEX ) {
    04435           printf( "ETO_GLYPH_INDEX" );
    04436           if ( emrtext.fOptions &
    04437                ~(ETO_GRAYED | ETO_OPAQUE | ETO_CLIPPED | ETO_GLYPH_INDEX) )
    04438             printf( " | " );
    04439         }
    04440         if ( emrtext.fOptions & ETO_RTLREADING ) {
    04441           printf( "ETO_RTLREADING" );
    04442           if ( emrtext.fOptions &
    04443                ~(ETO_GRAYED | ETO_OPAQUE | ETO_CLIPPED | ETO_GLYPH_INDEX |
    04444                  ETO_RTLREADING) )
    04445             printf( " | " );
    04446         }
    04447         if ( emrtext.fOptions & ETO_IGNORELANGUAGE )
    04448           printf( "ETO_IGNORELANGUAGE" );
    04449       }
    04450       printf( "\n" );
    04451       edit_rectl( "rcl\t", emrtext.rcl );
    04452       printf( "\toffDx\t\t: %ld\n", emrtext.offDx );
    04453       printf( "\tString:\n\t\t%s\n",  string_a );
    04454
    04455       if ( emrtext.offDx != 0 ) {
    04456         printf( "\tOffsets:\n\t\t" );
    04457         for ( unsigned int i = 0; i < emrtext.nChars; i++ )
    04458           printf( "%d ", dx_i[i] );
    04459         printf( "\n" );
    04460       }
    04461     }
    04462 #endif /* ENABLE_EDITING */
    04463   };
    04464
    04466
    04469   class EMRSETPIXELV : public METARECORD, ::EMRSETPIXELV {
    04470   public:
    04476     EMRSETPIXELV ( INT x, INT y, COLORREF color )
    04477     {
    04478       emr.iType = EMR_SETPIXELV;
    04479       emr.nSize = sizeof( ::EMRSETPIXELV );
    04480       ptlPixel.x = x;
    04481       ptlPixel.y = y;
    04482       crColor = color;
    04483     }
    04488     EMRSETPIXELV ( DATASTREAM& ds )
    04489     {
    04490       ds >> emr >> ptlPixel >> crColor;
    04491     }
    04495     bool serialize ( DATASTREAM ds )
    04496     {
    04497       ds << emr << ptlPixel << crColor;
    04498       return true;
    04499     }
    04503     int size ( void ) const { return emr.nSize; }
    04509     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    04510     {
    04511       SetPixel( dc, ptlPixel.x, ptlPixel.y, crColor );
    04512     }
    04513 #ifdef ENABLE_EDITING
    04514
    04517     void edit ( void ) const
    04518     {
    04519       printf( "*SETPIXELV*\n" );
    04520       edit_pointl( "ptlPixel", ptlPixel );
    04521       edit_color( "crColor\t", crColor );
    04522     }
    04523 #endif /* ENABLE_EDITING */
    04524   };
    04525
    04526   class PEN;
    04527   class EXTPEN;
    04528   class BRUSH;
    04529   class FONT;
    04530   class PALETTE;
    04531
    04533
    04536   class EMRCREATEPEN : public METARECORD, public ::EMRCREATEPEN
    04537   {
    04538   public:
    04543     EMRCREATEPEN ( PEN* pen, HGDIOBJ handle );
    04548     EMRCREATEPEN ( DATASTREAM& ds );
    04552     bool serialize ( DATASTREAM ds )
    04553     {
    04554       ds << emr << ihPen << lopn;
    04555       return true;
    04556     }
    04560     int size ( void ) const { return emr.nSize; }
    04566     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
    04567 #ifdef ENABLE_EDITING
    04568
    04571     void edit ( void ) const
    04572     {
    04573       printf( "*CREATEPEN*\n" );
    04574       printf( "\tihPen\t\t: 0x%lx\n", ihPen );
    04575       edit_pen_style( "lopn.lopnStyle", lopn.lopnStyle );
    04576       printf( "\tlopn.lopnWidth\t: %ld, %ld\n", lopn.lopnWidth.x, lopn.lopnWidth.y );
    04577       edit_color( "lopn.lopnColor", lopn.lopnColor );
    04578     }
    04579 #endif /* ENABLE_EDITING */
    04580   };
    04581
    04583
    04587   class EMREXTCREATEPEN : public METARECORD, public ::EMREXTCREATEPEN
    04588   {
    04589   public:
    04594     EMREXTCREATEPEN ( EXTPEN* pen, HGDIOBJ handle );
    04599     EMREXTCREATEPEN ( DATASTREAM& ds );
    04603     bool serialize ( DATASTREAM ds )
    04604     {
    04605       ds << emr << ihPen << offBmi << cbBmi << offBits << cbBits << elp;
    04606       return true;
    04607     }
    04611     int size ( void ) const { return emr.nSize; }
    04617     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
    04618 #ifdef ENABLE_EDITING
    04619
    04622     void edit ( void ) const
    04623     {
    04624       printf( "*EXTCREATEPEN*\n" );
    04625       printf( "\tihPen\t\t\t: 0x%lx\n", ihPen );
    04626       printf( "\toffBmi\t\t\t: %ld\n",  offBmi );
    04627       printf( "\tcbBmi\t\t\t: %ld\n", cbBmi );
    04628       printf( "\toffBits\t\t\t: %ld\n", offBits );
    04629       printf( "\tcbBits\t\t\t: %ld\n", cbBits );
    04630       edit_pen_style( "elp.elpPenStyle\t", elp.elpPenStyle );
    04631       printf( "\telp.elpWidth\t\t: %ld\n", elp.elpWidth );
    04632       edit_brush_style( "elp.elpBrushStyle", elp.elpBrushStyle );
    04633       edit_color( "elp.elpColor\t", elp.elpColor );
    04634       edit_brush_hatch( "elp.elpHatch\t", elp.elpHatch );
    04635       printf( "\telp.elpNumEntries\t: %ld\n", elp.elpNumEntries );
    04636     }
    04637 #endif /* ENABLE_EDITING */
    04638   };
    04639
    04641
    04644   class EMRCREATEBRUSHINDIRECT : public METARECORD, public ::EMRCREATEBRUSHINDIRECT
    04645   {
    04646   public:
    04651     EMRCREATEBRUSHINDIRECT ( BRUSH* brush, HGDIOBJ handle );
    04656     EMRCREATEBRUSHINDIRECT ( DATASTREAM& ds );
    04660     bool serialize ( DATASTREAM ds )
    04661     {
    04662       ds << emr << ihBrush << lb;
    04663       return true;
    04664     }
    04668     int size ( void ) const { return emr.nSize; }
    04674     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
    04675 #ifdef ENABLE_EDITING
    04676
    04679     void edit ( void ) const
    04680     {
    04681       printf( "*CREATEBRUSHINDIRECT*\n" );
    04682       printf( "\tihBrush\t\t: 0x%lx\n", ihBrush );
    04683       edit_brush_style( "lb.lbStyle", lb.lbStyle );
    04684       edit_color( "lb.lbColor", lb.lbColor );
    04685       edit_brush_hatch( "lb.lbHatch", lb.lbHatch );
    04686     }
    04687 #endif /* ENABLE_EDITING */
    04688   };
    04689
    04691
    04694   class EMREXTCREATEFONTINDIRECTW : public METARECORD, public ::EMREXTCREATEFONTINDIRECTW
    04695   {
    04696   public:
    04701     EMREXTCREATEFONTINDIRECTW ( FONT* font, HGDIOBJ handle );
    04706     EMREXTCREATEFONTINDIRECTW ( DATASTREAM& ds );
    04710     bool serialize ( DATASTREAM ds )
    04711     {
    04712       // Since EMF records have to be multiples of 4 bytes, this
    04713       // should perhaps be a general thing, but we know it's currently
    04714       // only a problem for this structure.
    04715
    04716       ds << emr << ihFont << elfw << PADDING( 2 );
    04717
    04718       return true;
    04719     }
    04723     int size ( void ) const { return emr.nSize; }
    04729     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
    04730 #ifdef ENABLE_EDITING
    04731
    04734     void edit ( void ) const
    04735     {
    04736       printf( "*EXTCREATEFONTINDIRECTW*\n" );
    04737       printf( "\tihFont\t\t\t: %ld\n", ihFont );
    04738       printf( "\tlfHeight\t\t: %ld\n", elfw.elfLogFont.lfHeight );
    04739       printf( "\tlfWidth\t\t\t: %ld\n", elfw.elfLogFont.lfWidth );
    04740       printf( "\tlfEscapement\t\t: %ld\n", elfw.elfLogFont.lfEscapement );
    04741       printf( "\tlfOrientation\t\t: %ld\n", elfw.elfLogFont.lfOrientation );
    04742       printf( "\tlfWeight\t\t: " );
    04743       switch ( elfw.elfLogFont.lfWeight ) {
    04744       case FW_DONTCARE: printf( "FW_DONTCARE\n" ); break;
    04745       case FW_THIN: printf( "FW_THIN\n" ); break;
    04746       case FW_EXTRALIGHT: printf( "FW_EXTRALIGHT\n" ); break;
    04747       case FW_LIGHT: printf( "FW_LIGHT\n" ); break;
    04748       case FW_NORMAL: printf( "FW_NORMAL\n" ); break;
    04749       case FW_MEDIUM: printf( "FW_MEDIUM\n" ); break;
    04750       case FW_SEMIBOLD: printf( "FW_SEMIBOLD\n" ); break;
    04751       case FW_BOLD: printf( "FW_BOLD\n" ); break;
    04752       case FW_EXTRABOLD: printf( "FW_EXTRABOLD\n" ); break;
    04753       case FW_BLACK: printf( "FW_BLACK\n" ); break;
    04754       }
    04755       printf( "\tlfItalic\t\t: %d\n", elfw.elfLogFont.lfItalic );
    04756       printf( "\tlfUnderline\t\t: %d\n", elfw.elfLogFont.lfUnderline );
    04757       printf( "\tlfStrikeOut\t\t: %d\n", elfw.elfLogFont.lfStrikeOut );
    04758       printf( "\tlfCharSet\t\t: %d\n", elfw.elfLogFont.lfCharSet );
    04759       printf( "\tlfOutPrecision\t\t: %d\n", elfw.elfLogFont.lfOutPrecision );
    04760       printf( "\tlfClipPrecision\t\t: %d\n", elfw.elfLogFont.lfClipPrecision );
    04761       printf( "\tlfQuality\t\t: %d\n", elfw.elfLogFont.lfQuality );
    04762       printf( "\tlfPitchAndFamily\t: %d\n", elfw.elfLogFont.lfPitchAndFamily );
    04763       int i = 0;
    04764       printf( "\tlfFaceName\t\t: '" );
    04765       while ( elfw.elfLogFont.lfFaceName[i] != 0 && i < LF_FACESIZE ) {
    04766         putchar( elfw.elfLogFont.lfFaceName[i] );
    04767         i++;
    04768       }
    04769       puts( "'" );
    04770
    04771       i = 0;
    04772       printf( "\telfFullName\t\t: '" );
    04773       while ( elfw.elfFullName[i] != 0 && i < LF_FULLFACESIZE ) {
    04774         putchar( elfw.elfFullName[i] );
    04775         i++;
    04776       }
    04777       puts( "'" );
    04778
    04779       i = 0;
    04780       printf( "\telfStyle\t\t: '" );
    04781       while ( elfw.elfStyle[i] != 0 && i < LF_FACESIZE ) {
    04782         putchar( elfw.elfStyle[i] );
    04783         i++;
    04784       }
    04785       puts( "'" );
    04786
    04787       printf( "\telfVersion\t\t: %ld\n", elfw.elfVersion );
    04788       printf( "\telfStyleSize\t\t: %ld\n", elfw.elfStyleSize );
    04789       printf( "\telfMatch\t\t: %ld\n", elfw.elfMatch );
    04790       printf( "\telfVendorId\t\t: '%s'\n", elfw.elfVendorId );
    04791       printf( "\telfCulture\t\t: %ld\n", elfw.elfCulture );
    04792       printf( "\telfPanose\t\t:\n" );
    04793       printf( "\t\tbFamilyType\t\t: %d\n", elfw.elfPanose.bFamilyType );
    04794       printf( "\t\tbSerifStyle\t\t: %d\n", elfw.elfPanose.bSerifStyle );
    04795       printf( "\t\tbWeight\t\t\t: %d\n", elfw.elfPanose.bWeight );
    04796       printf( "\t\tbProportion\t\t: %d\n", elfw.elfPanose.bProportion );
    04797       printf( "\t\tbContrast\t\t: %d\n", elfw.elfPanose.bContrast );
    04798       printf( "\t\tbStrokeVariation\t: %d\n", elfw.elfPanose.bStrokeVariation );
    04799       printf( "\t\tbArmStyle\t\t: %d\n", elfw.elfPanose.bArmStyle );
    04800       printf( "\t\tbLetterform\t\t: %d\n", elfw.elfPanose.bLetterform );
    04801       printf( "\t\tbMidline\t\t: %d\n", elfw.elfPanose.bMidline );
    04802       printf( "\t\tbXHeight\t\t: %d\n", elfw.elfPanose.bXHeight );
    04803     }
    04804 #endif /* ENABLE_EDITING */
    04805   };
    04806
    04808
    04811   class EMRCREATEPALETTE : public METARECORD, public ::EMRCREATEPALETTE
    04812   {
    04813   public:
    04818     EMRCREATEPALETTE ( PALETTE* palette, HGDIOBJ handle );
    04823     EMRCREATEPALETTE ( DATASTREAM& ds );
    04827     bool serialize ( DATASTREAM ds )
    04828     {
    04829       ds << emr << ihPal << lgpl;
    04830       return true;
    04831     }
    04835     int size ( void ) const { return emr.nSize; }
    04841     void execute ( METAFILEDEVICECONTEXT* source, HDC dc ) const;
    04842 #ifdef ENABLE_EDITING
    04843
    04846     void edit ( void ) const
    04847     {
    04848       printf( "*CREATEPALETTE* (not really handled by libEMF)\n" );
    04849     }
    04850 #endif /* ENABLE_EDITING */
    04851   };
    04852
    04854
    04857   class EMRFILLPATH : public METARECORD, ::EMRFILLPATH {
    04858   public:
    04863     EMRFILLPATH ( const RECTL* bounds )
    04864     {
    04865       emr.iType = EMR_FILLPATH;
    04866       emr.nSize = sizeof( ::EMRFILLPATH );
    04867       rclBounds = *bounds;
    04868     }
    04873     EMRFILLPATH ( DATASTREAM& ds )
    04874     {
    04875       ds >> emr >> rclBounds;
    04876     }
    04880     bool serialize ( DATASTREAM ds )
    04881     {
    04882       ds << emr << rclBounds;
    04883       return true;
    04884     }
    04888     int size ( void ) const { return emr.nSize; }
    04894     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    04895     {
    04896       FillPath( dc );
    04897     }
    04898 #ifdef ENABLE_EDITING
    04899
    04902     void edit ( void ) const
    04903     {
    04904       printf( "*FILLPATH*\n" );
    04905       edit_rectl( "rclBounds", rclBounds );
    04906     }
    04907 #endif /* ENABLE_EDITING */
    04908   };
    04910
    04913   class EMRSTROKEPATH : public METARECORD, ::EMRSTROKEPATH {
    04914   public:
    04919     EMRSTROKEPATH ( const RECTL* bounds )
    04920     {
    04921       emr.iType = EMR_STROKEPATH;
    04922       emr.nSize = sizeof( ::EMRSTROKEPATH );
    04923       rclBounds = *bounds;
    04924     }
    04929     EMRSTROKEPATH ( DATASTREAM& ds )
    04930     {
    04931       ds >> emr >> rclBounds;
    04932     }
    04936     bool serialize ( DATASTREAM ds )
    04937     {
    04938       ds << emr << rclBounds;
    04939       return true;
    04940     }
    04944     int size ( void ) const { return emr.nSize; }
    04950     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    04951     {
    04952       StrokePath( dc );
    04953     }
    04954 #ifdef ENABLE_EDITING
    04955
    04958     void edit ( void ) const
    04959     {
    04960       printf( "*STROKEPATH*\n" );
    04961       edit_rectl( "rclBounds", rclBounds );
    04962     }
    04963 #endif /* ENABLE_EDITING */
    04964   };
    04966
    04969   class EMRBEGINPATH : public METARECORD, ::EMRBEGINPATH {
    04970   public:
    04974     EMRBEGINPATH ( void )
    04975     {
    04976       emr.iType = EMR_BEGINPATH;
    04977       emr.nSize = sizeof( ::EMRBEGINPATH );
    04978     }
    04983     EMRBEGINPATH ( DATASTREAM& ds )
    04984     {
    04985       ds >> emr;
    04986     }
    04990     bool serialize ( DATASTREAM ds )
    04991     {
    04992       ds << emr;
    04993       return true;
    04994     }
    04998     int size ( void ) const { return emr.nSize; }
    05004     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    05005     {
    05006       BeginPath( dc );
    05007     }
    05008 #ifdef ENABLE_EDITING
    05009
    05012     void edit ( void ) const
    05013     {
    05014       printf( "*BEGINPATH*\n" );
    05015     }
    05016 #endif /* ENABLE_EDITING */
    05017   };
    05019
    05022   class EMRENDPATH : public METARECORD, ::EMRENDPATH {
    05023   public:
    05027     EMRENDPATH ( void )
    05028     {
    05029       emr.iType = EMR_ENDPATH;
    05030       emr.nSize = sizeof( ::EMRENDPATH );
    05031     }
    05036     EMRENDPATH ( DATASTREAM& ds )
    05037     {
    05038       ds >> emr;
    05039     }
    05043     bool serialize ( DATASTREAM ds )
    05044     {
    05045       ds << emr;
    05046       return true;
    05047     }
    05051     int size ( void ) const { return emr.nSize; }
    05057     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    05058     {
    05059       EndPath( dc );
    05060     }
    05061 #ifdef ENABLE_EDITING
    05062
    05065     void edit ( void ) const
    05066     {
    05067       printf( "*ENDPATH*\n" );
    05068     }
    05069 #endif /* ENABLE_EDITING */
    05070   };
    05072
    05075   class EMRCLOSEFIGURE : public METARECORD, ::EMRCLOSEFIGURE {
    05076   public:
    05080     EMRCLOSEFIGURE ( void )
    05081     {
    05082       emr.iType = EMR_CLOSEFIGURE;
    05083       emr.nSize = sizeof( ::EMRCLOSEFIGURE );
    05084     }
    05089     EMRCLOSEFIGURE ( DATASTREAM& ds )
    05090     {
    05091       ds >> emr;
    05092     }
    05096     bool serialize ( DATASTREAM ds )
    05097     {
    05098       ds << emr;
    05099       return true;
    05100     }
    05104     int size ( void ) const { return emr.nSize; }
    05110     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    05111     {
    05112       CloseFigure( dc );
    05113     }
    05114 #ifdef ENABLE_EDITING
    05115
    05118     void edit ( void ) const
    05119     {
    05120       printf( "*CLOSEFIGURE*\n" );
    05121     }
    05122 #endif /* ENABLE_EDITING */
    05123   };
    05125
    05129   class EMRSAVEDC : public METARECORD, ::EMRSAVEDC {
    05130   public:
    05134     EMRSAVEDC ( void )
    05135     {
    05136       emr.iType = EMR_SAVEDC;
    05137       emr.nSize = sizeof( ::EMRSAVEDC );
    05138     }
    05143     EMRSAVEDC ( DATASTREAM& ds )
    05144     {
    05145       ds >> emr;
    05146     }
    05150     bool serialize ( DATASTREAM ds )
    05151     {
    05152       ds << emr;
    05153       return true;
    05154     }
    05158     int size ( void ) const { return emr.nSize; }
    05164     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    05165     {
    05166       SaveDC( dc );
    05167     }
    05168 #ifdef ENABLE_EDITING
    05169
    05172     void edit ( void ) const
    05173     {
    05174       printf( "*SAVEDC*\n" );
    05175     }
    05176 #endif /* ENABLE_EDITING */
    05177   };
    05179
    05182   class EMRRESTOREDC : public METARECORD, ::EMRRESTOREDC {
    05183   public:
    05187     EMRRESTOREDC ( INT n )
    05188     {
    05189       emr.iType = EMR_RESTOREDC;
    05190       emr.nSize = sizeof( ::EMRRESTOREDC );
    05191       iRelative = n;
    05192     }
    05197     EMRRESTOREDC ( DATASTREAM& ds )
    05198     {
    05199       ds >> emr >> iRelative;
    05200     }
    05204     bool serialize ( DATASTREAM ds )
    05205     {
    05206       ds << emr << iRelative;
    05207       return true;
    05208     }
    05212     int size ( void ) const { return emr.nSize; }
    05218     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    05219     {
    05220       RestoreDC( dc, iRelative );
    05221     }
    05222 #ifdef ENABLE_EDITING
    05223
    05226     void edit ( void ) const
    05227     {
    05228       printf( "*RESTOREDC*\n" );
    05229       printf( "\tiRelative: %ld\n", iRelative );
    05230     }
    05231 #endif /* ENABLE_EDITING */
    05232   };
    05234
    05237   class EMRSETMETARGN : public METARECORD, ::EMRSETMETARGN {
    05238   public:
    05242     EMRSETMETARGN ( void )
    05243     {
    05244       emr.iType = EMR_SETMETARGN;
    05245       emr.nSize = sizeof( ::EMRSETMETARGN );
    05246     }
    05251     EMRSETMETARGN ( DATASTREAM& ds )
    05252     {
    05253       ds >> emr;
    05254     }
    05258     bool serialize ( DATASTREAM ds )
    05259     {
    05260       ds << emr;
    05261       return true;
    05262     }
    05266     int size ( void ) const { return emr.nSize; }
    05272     void execute ( METAFILEDEVICECONTEXT* /*source*/, HDC dc ) const
    05273     {
    05274       SetMetaRgn( dc );
    05275     }
    05276 #ifdef ENABLE_EDITING
    05277
    05280     void edit ( void ) const
    05281     {
    05282       printf( "*SETMETARGN*\n" );
    05283     }
    05284 #endif /* ENABLE_EDITING */
    05285   };
    05286
    05288
    05291   class PEN : public GRAPHICSOBJECT, public LOGPEN {
    05292   public:
    05296     PEN ( const LOGPEN* lpen )
    05297     {
    05298       lopnStyle = lpen->lopnStyle;
    05299       lopnWidth = lpen->lopnWidth;
    05300       lopnColor = lpen->lopnColor;
    05301     }
    05305     OBJECTTYPE getType ( void ) const { return O_PEN; }
    05312     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
    05313     {
    05314       contexts[dc] = emf_handle;
    05315       return new EMRCREATEPEN( this, emf_handle );
    05316     }
    05317   };
    05318
    05320
    05323   class EXTPEN : public GRAPHICSOBJECT, public EXTLOGPEN {
    05324   public:
    05328     EXTPEN ( const EXTLOGPEN* lpen )
    05329     {
    05330       elpPenStyle = lpen->elpPenStyle;
    05331       elpWidth = lpen->elpWidth;
    05332       elpBrushStyle = lpen->elpBrushStyle;
    05333       elpColor = lpen->elpColor;
    05334       elpHatch = lpen->elpHatch;
    05335       elpNumEntries = 0;
    05336       elpStyleEntry[0] = 0;
    05337     }
    05341     OBJECTTYPE getType ( void ) const { return O_EXTPEN; }
    05348     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
    05349     {
    05350       contexts[dc] = emf_handle;
    05351       return new EMREXTCREATEPEN( this, emf_handle );
    05352     }
    05353   };
    05354
    05356
    05359   class BRUSH : public GRAPHICSOBJECT, public LOGBRUSH {
    05360   public:
    05364     BRUSH ( const LOGBRUSH* lbrush )
    05365     {
    05366       lbStyle = lbrush->lbStyle;
    05367       lbColor = lbrush->lbColor;
    05368       lbHatch = lbrush->lbHatch;
    05369     }
    05373     OBJECTTYPE getType ( void ) const { return O_BRUSH; }
    05380     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
    05381     {
    05382       contexts[dc] = emf_handle;
    05383       return new EMRCREATEBRUSHINDIRECT( this, emf_handle );
    05384     }
    05385   };
    05386
    05388
    05391   class FONT : public GRAPHICSOBJECT, public EXTLOGFONTW {
    05392   public:
    05396     FONT ( const LOGFONTW* lfont )
    05397     {
    05398       this->elfLogFont = *lfont;
    05399       // There are a lot more entries in the EXTLOGFONTW structure than
    05400       // the API has values for, so we invent them here
    05401       memset( &elfFullName, 0, sizeof elfFullName );
    05402       memset( &elfStyle, 0, sizeof elfStyle );
    05403       elfVersion = ELF_VERSION;
    05404       elfStyleSize = 0;
    05405       elfMatch = 0;
    05406       elfReserved = 0;
    05407       memset( &elfVendorId, 0, sizeof elfVendorId );
    05408       elfCulture = ELF_CULTURE_LATIN;
    05409       memset( &elfPanose, 1, sizeof(PANOSE) );
    05410     }
    05414     OBJECTTYPE getType ( void ) const { return O_FONT; }
    05421     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
    05422     {
    05423       contexts[dc] = emf_handle;
    05424       return new EMREXTCREATEFONTINDIRECTW( this, emf_handle );
    05425     }
    05426   };
    05427
    05429
    05432   class PALETTE : public GRAPHICSOBJECT, public LOGPALETTE {
    05433   public:
    05437     PALETTE ( const LOGPALETTE* lpalette )
    05438     {
    05439       (void)lpalette;
    05440       palVersion = 0;
    05441       palNumEntries = 0;
    05442       PALETTEENTRY zero_entry = { 0, 0, 0, 0 };
    05443       palPalEntry[0] = zero_entry;
    05444     }
    05448     OBJECTTYPE getType ( void ) const { return O_PALETTE; }
    05455     METARECORD* newEMR ( HDC dc, HGDIOBJ emf_handle )
    05456     {
    05457       contexts[dc] = emf_handle;
    05458       return new EMRCREATEPALETTE( this, emf_handle );
    05459     }
    05460   };
    05461
    05463
    05469   class METAFILEDEVICECONTEXT : public OBJECT {
    05477     void init ( const RECT* size, LPCWSTR description_w ) {
    05478
    05479       // Evidently, metafile handles are numbered from 1, so don't
    05480       // ever use 0.
    05481
    05482       handles.push_back( true );
    05483
    05484       // Keep some of our graphics state in a header record
    05485
    05486       header = new ENHMETAHEADER ( description_w );
    05487       records.push_back( header );
    05488
    05489       // Compute the size and position of the metafile on the "page"
    05490
    05491       if ( size ) {
    05492         update_frame = false;
    05493
    05494         header->rclFrame.left = size->left;
    05495         header->rclFrame.top = size->top;
    05496         header->rclFrame.right = size->right;
    05497         header->rclFrame.bottom = size->bottom;
    05498
    05499         header->rclBounds.left =
    05500           size->left * header->szlDevice.cx / ( header->szlMillimeters.cx * 100 );
    05501         header->rclBounds.top =
    05502           size->top * header->szlDevice.cy / ( header->szlMillimeters.cy * 100 );
    05503         header->rclBounds.right =
    05504           size->right * header->szlDevice.cx / ( header->szlMillimeters.cx * 100 );
    05505         header->rclBounds.bottom =
    05506           size->bottom * header->szlDevice.cy / ( header->szlMillimeters.cy * 100 );
    05507       }
    05508       else {
    05509         update_frame = true;
    05510
    05511         header->rclBounds.left = -10;
    05512         header->rclBounds.top = -10;
    05513         header->rclBounds.right = 10;
    05514         header->rclBounds.bottom = 10;
    05515
    05516         header->rclFrame.left = (LONG)floor( (float)header->rclBounds.left *
    05517           header->szlMillimeters.cx * 100 / header->szlDevice.cx );
    05518         header->rclFrame.top = (LONG)floor( (float)header->rclBounds.top *
    05519           header->szlMillimeters.cy * 100 / header->szlDevice.cy );
    05520         header->rclFrame.right = (LONG)ceil( (float)header->rclBounds.right *
    05521           header->szlMillimeters.cx * 100 / header->szlDevice.cx );
    05522         header->rclFrame.bottom = (LONG)ceil( (float)header->rclBounds.bottom *
    05523           header->szlMillimeters.cy * 100 / header->szlDevice.cy );
    05524       }
    05525
    05526       // Some default graphics state (are they really, though?)
    05527
    05528       SIZEL default_resolution = { RESOLUTION, RESOLUTION };
    05529       resolution = default_resolution;
    05530       SIZEL default_viewport_ext = { 1, 1 };
    05531       viewport_ext = default_viewport_ext;
    05532       POINT default_viewport_org = { 0, 0 };
    05533       viewport_org = default_viewport_org;
    05534       SIZEL default_window_ext = { 1, 1 };
    05535       window_ext = default_window_ext;
    05536       POINT default_window_org = { 0, 0 };
    05537       window_org = default_window_org;
    05538
    05539       min_device_point = viewport_org;
    05540       max_device_point = viewport_org;
    05541
    05542       pen = (PEN*)globalObjects.find( BLACK_PEN | ENHMETA_STOCK_OBJECT );
    05543       brush = (BRUSH*)globalObjects.find( BLACK_BRUSH | ENHMETA_STOCK_OBJECT );
    05544       font = (FONT*)globalObjects.find( DEVICE_DEFAULT_FONT | ENHMETA_STOCK_OBJECT);
    05545       palette = (PALETTE*)globalObjects.find( DEFAULT_PALETTE|ENHMETA_STOCK_OBJECT);
    05546
    05547       text_alignment = TA_BASELINE;
    05548       text_color = RGB(0,0,0);
    05549       bk_color = RGB(0xff,0xff,0xff);
    05550       bk_mode = OPAQUE;
    05551       polyfill_mode = ALTERNATE;
    05552       map_mode = MM_TEXT;
    05553
    05554       handle = globalObjects.add( this );
    05555     }
    05556
    05557   public:
    05561     ::FILE* fp;
    05566     DATASTREAM ds;
    05570     ENHMETAHEADER* header;
    05574     std::vector< EMF::METARECORD* > records;
    05575
    05576     // Keep a small set of graphics state information
    05577     SIZEL resolution;
    05578     SIZEL viewport_ext;
    05579     POINT viewport_org;
    05580     SIZEL window_ext;
    05581     POINT window_org;
    05582     bool update_frame;
    05583     POINT min_device_point;
    05584     POINT max_device_point;
    05585     POINT point;
    05586     PEN* pen;
    05587     BRUSH* brush;
    05588     FONT* font;
    05589     PALETTE* palette;
    05590     UINT text_alignment;
    05591     COLORREF text_color;
    05592     COLORREF bk_color;
    05593     INT bk_mode;
    05594     INT polyfill_mode;
    05595     INT map_mode;
    05596
    05602     std::vector< bool > handles;
    05603
    05609     std::map< HGDIOBJ, HGDIOBJ > emf_handles;
    05610
    05621       METAFILEDEVICECONTEXT ( FILE* fp_, const RECT* size,
    05622                               LPCWSTR description_w )
    05623         : fp(fp_), ds( fp_ )
    05624     {
    05625           init( size, description_w );
    05626     }
    05631     virtual ~METAFILEDEVICECONTEXT ( )
    05632     {
    05633       // Purge all the metarecords (if there are any) {this include the
    05634       // header record, too}
    05635       if ( records.size() > 0 )
    05636         deleteMetafile();
    05637     }
    05641     OBJECTTYPE getType ( void ) const { return O_METAFILEDEVICECONTEXT; }
    05646     DWORD nextHandle ( void )
    05647     {
    05648       for ( unsigned int i = 1; i < handles.size(); i++ ) {
    05649         if ( !handles[i] ) {
    05650           handles[i] = true;
    05651           return i;
    05652         }
    05653       }
    05654       handles.push_back( true );
    05655       // Well, it appears that even StockObject handles count for something.
    05656       // Not sure what the right value here is, then.
    05657       header->nHandles = handles.size();
    05658       return handles.size()-1;
    05659     }
    05663     void clearHandle ( DWORD handle )
    05664     {
    05665       handles[handle] = false;
    05666     }
    05672     void appendRecord ( METARECORD* record )
    05673     {
    05674       records.push_back( record );
    05675
    05676       header->nBytes += record->size();
    05677       header->nRecords++;
    05678     }
    05684     void appendHandle ( METARECORD* record )
    05685     {
    05686       records.push_back( record );
    05687
    05688       header->nBytes += record->size();
    05689       header->nRecords++;
    05690     }
    05695     void deleteMetafile ( void )
    05696     {
    05697       for ( std::vector<METARECORD*>::const_iterator r = records.begin();
    05698             r != records.end();
    05699             r++ ) {
    05700         delete *r;
    05701       }
    05702       records.clear();
    05703     }
    05708     void mergePoint ( const LONG& x, const LONG& y )
    05709     {
    05710       POINT p;
    05711       p.x = x;
    05712       p.y = y;
    05713       mergePoint( p );
    05714     }
    05719     void mergePoint( const POINT& p )
    05720     {
    05721       POINT device_point;
    05722
    05723       // *** Note, it's possible for the global transformation matrix to
    05724       // affect this too. ***
    05725
    05726       device_point.x = (LONG)( (float)( p.x - window_org.x ) / window_ext.cx *
    05727         viewport_ext.cx + viewport_org.x );
    05728
    05729       device_point.y = (LONG)( (float)( p.y - window_org.y ) / window_ext.cy *
    05730         viewport_ext.cy + viewport_org.y );
    05731
    05732       // If the user didn't specify a bounding rectangle in the constructor,
    05733       // compute one from this data, too.
    05734       if ( device_point.x < min_device_point.x ) {
    05735         min_device_point.x = device_point.x;
    05736         if ( update_frame ) {
    05737           header->rclBounds.left = min_device_point.x - 10;
    05738           header->rclFrame.left = (LONG)floor( (float)header->rclBounds.left *
    05739             header->szlMillimeters.cx * 100 / header->szlDevice.cx );
    05740         }
    05741       }
    05742       else if ( device_point.x > max_device_point.x ) {
    05743         max_device_point.x = device_point.x;
    05744         if ( update_frame ) {
    05745           header->rclBounds.right = max_device_point.x + 10;
    05746           header->rclFrame.right = (LONG)ceil( (float)header->rclBounds.right *
    05747             header->szlMillimeters.cx * 100 / header->szlDevice.cx );
    05748         }
    05749       }
    05750
    05751       if ( device_point.y < min_device_point.y ) {
    05752         min_device_point.y = device_point.y;
    05753         if ( update_frame ) {
    05754           header->rclBounds.top = min_device_point.y - 10;
    05755           header->rclFrame.top = (LONG)floor( (float)header->rclBounds.top *
    05756             header->szlMillimeters.cy * 100 / header->szlDevice.cy );
    05757         }
    05758       }
    05759       else if ( device_point.y > max_device_point.y ) {
    05760         max_device_point.y = device_point.y;
    05761         if ( update_frame ) {
    05762           header->rclBounds.bottom = max_device_point.y + 10;
    05763           header->rclFrame.bottom = (LONG)ceil( (float)header->rclBounds.bottom *
    05764             header->szlMillimeters.cy * 100 / header->szlDevice.cy );
    05765         }
    05766       }
    05767     }
    05768   };
    05769
    05770 } // close EMF namespace
    05771
    05772 #endif /* _LIBEMF_H */