EMF: libemf.h Source File

- Main Page
- Classes
- Files

- File List

# libemf.h

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