LCOV - code coverage report
Current view: top level - libreoffice/svtools/source/filter/wmf - wmfwr.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 632 1068 59.2 %
Date: 2012-12-27 Functions: 50 62 80.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "wmfwr.hxx"
      21             : #include <unotools/fontcvt.hxx>
      22             : #include "emfwr.hxx"
      23             : #include <rtl/crc.h>
      24             : #include <rtl/tencinfo.h>
      25             : #include <tools/bigint.hxx>
      26             : #include <tools/helpers.hxx>
      27             : #include <tools/tenccvt.hxx>
      28             : #include <osl/endian.h>
      29             : #include <i18nutil/unicode.hxx> //unicode::getUnicodeScriptType
      30             : 
      31             : #include <vcl/metric.hxx>
      32             : #include <basegfx/polygon/b2dpolygon.hxx>
      33             : #include <basegfx/polygon/b2dpolypolygon.hxx>
      34             : 
      35             : //====================== MS-Windows-defines ===============================
      36             : 
      37             : #define W_META_SETBKCOLOR           0x0201
      38             : #define W_META_SETBKMODE            0x0102
      39             : #define W_META_SETMAPMODE           0x0103
      40             : #define W_META_SETROP2              0x0104
      41             : #define W_META_SETRELABS            0x0105
      42             : #define W_META_SETPOLYFILLMODE      0x0106
      43             : #define W_META_SETSTRETCHBLTMODE    0x0107
      44             : #define W_META_SETTEXTCHAREXTRA     0x0108
      45             : #define W_META_SETTEXTCOLOR         0x0209
      46             : #define W_META_SETTEXTJUSTIFICATION 0x020A
      47             : #define W_META_SETWINDOWORG         0x020B
      48             : #define W_META_SETWINDOWEXT         0x020C
      49             : #define W_META_SETVIEWPORTORG       0x020D
      50             : #define W_META_SETVIEWPORTEXT       0x020E
      51             : #define W_META_OFFSETWINDOWORG      0x020F
      52             : #define W_META_SCALEWINDOWEXT       0x0410
      53             : #define W_META_OFFSETVIEWPORTORG    0x0211
      54             : #define W_META_SCALEVIEWPORTEXT     0x0412
      55             : #define W_META_LINETO               0x0213
      56             : #define W_META_MOVETO               0x0214
      57             : #define W_META_EXCLUDECLIPRECT      0x0415
      58             : #define W_META_INTERSECTCLIPRECT    0x0416
      59             : #define W_META_ARC                  0x0817
      60             : #define W_META_ELLIPSE              0x0418
      61             : #define W_META_FLOODFILL            0x0419
      62             : #define W_META_PIE                  0x081A
      63             : #define W_META_RECTANGLE            0x041B
      64             : #define W_META_ROUNDRECT            0x061C
      65             : #define W_META_PATBLT               0x061D
      66             : #define W_META_SAVEDC               0x001E
      67             : #define W_META_SETPIXEL             0x041F
      68             : #define W_META_OFFSETCLIPRGN        0x0220
      69             : #define W_META_TEXTOUT              0x0521
      70             : #define W_META_BITBLT               0x0922
      71             : #define W_META_STRETCHBLT           0x0B23
      72             : #define W_META_POLYGON              0x0324
      73             : #define W_META_POLYLINE             0x0325
      74             : #define W_META_ESCAPE               0x0626
      75             : #define W_META_RESTOREDC            0x0127
      76             : #define W_META_FILLREGION           0x0228
      77             : #define W_META_FRAMEREGION          0x0429
      78             : #define W_META_INVERTREGION         0x012A
      79             : #define W_META_PAINTREGION          0x012B
      80             : #define W_META_SELECTCLIPREGION     0x012C
      81             : #define W_META_SELECTOBJECT         0x012D
      82             : #define W_META_SETTEXTALIGN         0x012E
      83             : #define W_META_DRAWTEXT             0x062F
      84             : #define W_META_CHORD                0x0830
      85             : #define W_META_SETMAPPERFLAGS       0x0231
      86             : #define W_META_EXTTEXTOUT           0x0a32
      87             : #define W_META_SETDIBTODEV          0x0d33
      88             : #define W_META_SELECTPALETTE        0x0234
      89             : #define W_META_REALIZEPALETTE       0x0035
      90             : #define W_META_ANIMATEPALETTE       0x0436
      91             : #define W_META_SETPALENTRIES        0x0037
      92             : #define W_META_POLYPOLYGON          0x0538
      93             : #define W_META_RESIZEPALETTE        0x0139
      94             : #define W_META_DIBBITBLT            0x0940
      95             : #define W_META_DIBSTRETCHBLT        0x0b41
      96             : #define W_META_DIBCREATEPATTERNBRUSH 0x0142
      97             : #define W_META_STRETCHDIB           0x0f43
      98             : #define W_META_EXTFLOODFILL         0x0548
      99             : #define W_META_RESETDC              0x014C
     100             : #define W_META_STARTDOC             0x014D
     101             : #define W_META_STARTPAGE            0x004F
     102             : #define W_META_ENDPAGE              0x0050
     103             : #define W_META_ABORTDOC             0x0052
     104             : #define W_META_ENDDOC               0x005E
     105             : #define W_META_DELETEOBJECT         0x01f0
     106             : #define W_META_CREATEPALETTE        0x00f7
     107             : #define W_META_CREATEBRUSH          0x00F8
     108             : #define W_META_CREATEPATTERNBRUSH   0x01F9
     109             : #define W_META_CREATEPENINDIRECT    0x02FA
     110             : #define W_META_CREATEFONTINDIRECT   0x02FB
     111             : #define W_META_CREATEBRUSHINDIRECT  0x02FC
     112             : #define W_META_CREATEBITMAPINDIRECT 0x02FD
     113             : #define W_META_CREATEBITMAP         0x06FE
     114             : #define W_META_CREATEREGION         0x06FF
     115             : 
     116             : #define W_TRANSPARENT     1
     117             : #define W_OPAQUE          2
     118             : 
     119             : #define W_R2_BLACK            1
     120             : #define W_R2_NOTMERGEPEN      2
     121             : #define W_R2_MASKNOTPEN       3
     122             : #define W_R2_NOTCOPYPEN       4
     123             : #define W_R2_MASKPENNOT       5
     124             : #define W_R2_NOT              6
     125             : #define W_R2_XORPEN           7
     126             : #define W_R2_NOTMASKPEN       8
     127             : #define W_R2_MASKPEN          9
     128             : #define W_R2_NOTXORPEN        10
     129             : #define W_R2_NOP              11
     130             : #define W_R2_MERGENOTPEN      12
     131             : #define W_R2_COPYPEN          13
     132             : #define W_R2_MERGEPENNOT      14
     133             : #define W_R2_MERGEPEN         15
     134             : #define W_R2_WHITE            16
     135             : 
     136             : #define W_TA_NOUPDATECP      0x0000
     137             : #define W_TA_UPDATECP        0x0001
     138             : #define W_TA_LEFT            0x0000
     139             : #define W_TA_RIGHT           0x0002
     140             : #define W_TA_CENTER          0x0006
     141             : #define W_TA_TOP             0x0000
     142             : #define W_TA_BOTTOM          0x0008
     143             : #define W_TA_BASELINE        0x0018
     144             : #define W_TA_RTLREADING      0x0100
     145             : 
     146             : #define W_SRCCOPY             0x00CC0020L
     147             : #define W_SRCPAINT            0x00EE0086L
     148             : #define W_SRCAND              0x008800C6L
     149             : #define W_SRCINVERT           0x00660046L
     150             : #define W_SRCERASE            0x00440328L
     151             : #define W_NOTSRCCOPY          0x00330008L
     152             : #define W_NOTSRCERASE         0x001100A6L
     153             : #define W_MERGECOPY           0x00C000CAL
     154             : #define W_MERGEPAINT          0x00BB0226L
     155             : #define W_PATCOPY             0x00F00021L
     156             : #define W_PATPAINT            0x00FB0A09L
     157             : #define W_PATINVERT           0x005A0049L
     158             : #define W_DSTINVERT           0x00550009L
     159             : #define W_BLACKNESS           0x00000042L
     160             : #define W_WHITENESS           0x00FF0062L
     161             : 
     162             : #define W_PS_SOLID            0
     163             : #define W_PS_DASH             1
     164             : #define W_PS_DOT              2
     165             : #define W_PS_DASHDOT          3
     166             : #define W_PS_DASHDOTDOT       4
     167             : #define W_PS_NULL             5
     168             : #define W_PS_INSIDEFRAME      6
     169             : 
     170             : #define W_LF_FACESIZE       32
     171             : 
     172             : #define W_ANSI_CHARSET          0
     173             : #define W_DEFAULT_CHARSET       1
     174             : #define W_SYMBOL_CHARSET        2
     175             : #define W_SHIFTJIS_CHARSET    128
     176             : #define W_HANGEUL_CHARSET     129
     177             : #define W_GB2312_CHARSET      134
     178             : #define W_CHINESEBIG5_CHARSET 136
     179             : #define W_OEM_CHARSET         255
     180             : /*WINVER >= 0x0400*/
     181             : #define W_JOHAB_CHARSET      130
     182             : #define W_HEBREW_CHARSET     177
     183             : #define W_ARABIC_CHARSET     178
     184             : #define W_GREEK_CHARSET      161
     185             : #define W_TURKISH_CHARSET    162
     186             : #define W_VIETNAMESE_CHARSET 163
     187             : #define W_THAI_CHARSET       222
     188             : #define W_EASTEUROPE_CHARSET 238
     189             : #define W_RUSSIAN_CHARSET    204
     190             : #define W_MAC_CHARSET        77
     191             : #define W_BALTIC_CHARSET     186
     192             : 
     193             : #define W_DEFAULT_PITCH       0x00
     194             : #define W_FIXED_PITCH         0x01
     195             : #define W_VARIABLE_PITCH      0x02
     196             : 
     197             : #define W_FF_DONTCARE         0x00
     198             : #define W_FF_ROMAN            0x10
     199             : #define W_FF_SWISS            0x20
     200             : #define W_FF_MODERN           0x30
     201             : #define W_FF_SCRIPT           0x40
     202             : #define W_FF_DECORATIVE       0x50
     203             : 
     204             : #define W_FW_DONTCARE       0
     205             : #define W_FW_THIN           100
     206             : #define W_FW_EXTRALIGHT     200
     207             : #define W_FW_LIGHT          300
     208             : #define W_FW_NORMAL         400
     209             : #define W_FW_MEDIUM         500
     210             : #define W_FW_SEMIBOLD       600
     211             : #define W_FW_BOLD           700
     212             : #define W_FW_EXTRABOLD      800
     213             : #define W_FW_HEAVY          900
     214             : #define W_FW_ULTRALIGHT     200
     215             : #define W_FW_REGULAR        400
     216             : #define W_FW_DEMIBOLD       600
     217             : #define W_FW_ULTRABOLD      800
     218             : #define W_FW_BLACK          900
     219             : 
     220             : #define W_BS_SOLID          0
     221             : #define W_BS_HOLLOW         1
     222             : #define W_BS_HATCHED        2
     223             : #define W_BS_PATTERN        3
     224             : #define W_BS_INDEXED        4
     225             : #define W_BS_DIBPATTERN     5
     226             : 
     227             : #define W_HS_HORIZONTAL     0
     228             : #define W_HS_VERTICAL       1
     229             : #define W_HS_FDIAGONAL      2
     230             : #define W_HS_BDIAGONAL      3
     231             : #define W_HS_CROSS          4
     232             : #define W_HS_DIAGCROSS      5
     233             : 
     234             : #define W_MFCOMMENT         15
     235             : 
     236             : #define PRIVATE_ESCAPE_UNICODE          2
     237             : 
     238             : //========================== Methoden von WMFWriter ==========================
     239             : 
     240        2723 : void WMFWriter::MayCallback()
     241             : {
     242        2723 :     if ( xStatusIndicator.is() )
     243             :     {
     244             :         sal_uLong nPercent;
     245             : 
     246             :         // Wir gehen mal einfach so davon aus, dass 16386 Actions einer Bitmap entsprechen
     247             :         // (in der Regel wird ein Metafile entweder nur Actions oder einige Bitmaps und fast
     248             :         // keine Actions enthalten. Dann ist das Verhaeltnis ziemlich unwichtig)
     249             : 
     250             :         nPercent=((nWrittenBitmaps<<14)+(nActBitmapPercent<<14)/100+nWrittenActions)
     251             :                 *100
     252           0 :                 /((nNumberOfBitmaps<<14)+nNumberOfActions);
     253             : 
     254           0 :         if ( nPercent >= nLastPercent + 3 )
     255             :         {
     256           0 :             nLastPercent = nPercent;
     257           0 :             if( nPercent <= 100 )
     258           0 :                 xStatusIndicator->setValue( nPercent );
     259             :         }
     260             :     }
     261        2723 : }
     262             : 
     263          29 : void WMFWriter::CountActionsAndBitmaps( const GDIMetaFile & rMTF )
     264             : {
     265             :     size_t nAction, nActionCount;
     266             : 
     267          29 :     nActionCount = rMTF.GetActionSize();
     268             : 
     269        2752 :     for ( nAction=0; nAction < nActionCount; nAction++ )
     270             :     {
     271        2723 :         MetaAction* pMA = rMTF.GetAction( nAction );
     272             : 
     273        2723 :         switch( pMA->GetType() )
     274             :         {
     275             :             case META_BMP_ACTION:
     276             :             case META_BMPSCALE_ACTION:
     277             :             case META_BMPSCALEPART_ACTION:
     278             :             case META_BMPEX_ACTION:
     279             :             case META_BMPEXSCALE_ACTION:
     280             :             case META_BMPEXSCALEPART_ACTION:
     281           0 :                 nNumberOfBitmaps++;
     282           0 :             break;
     283             :         }
     284        2723 :         nNumberOfActions++;
     285             :     }
     286          29 : }
     287             : 
     288             : 
     289        8498 : void WMFWriter::WritePointXY(const Point & rPoint)
     290             : {
     291        8498 :     Point aPt( pVirDev->LogicToLogic(rPoint,aSrcMapMode,aTargetMapMode) );
     292        8498 :     *pWMF << ((short)aPt.X()) << ((short)aPt.Y());
     293        8498 : }
     294             : 
     295             : 
     296         337 : void WMFWriter::WritePointYX(const Point & rPoint)
     297             : {
     298         337 :     Point aPt( pVirDev->LogicToLogic(rPoint,aSrcMapMode,aTargetMapMode) );
     299         337 :     *pWMF << ((short)aPt.Y()) << ((short)aPt.X());
     300         337 : }
     301             : 
     302             : 
     303          61 : sal_Int32 WMFWriter::ScaleWidth( sal_Int32 nDX )
     304             : {
     305          61 :     Size aSz( pVirDev->LogicToLogic(Size(nDX,0),aSrcMapMode,aTargetMapMode) );
     306          61 :     return aSz.Width();
     307             : }
     308             : 
     309             : 
     310         167 : void WMFWriter::WriteSize(const Size & rSize)
     311             : {
     312         167 :     Size aSz( pVirDev->LogicToLogic(rSize,aSrcMapMode,aTargetMapMode) );
     313         167 :     *pWMF << ((short)aSz.Width()) << ((short)aSz.Height());
     314         167 : }
     315             : 
     316             : 
     317         428 : void WMFWriter::WriteHeightWidth(const Size & rSize)
     318             : {
     319         428 :     Size aSz( pVirDev->LogicToLogic(rSize,aSrcMapMode,aTargetMapMode) );
     320         428 :     *pWMF << ((short)aSz.Height()) << ((short)aSz.Width());
     321         428 : }
     322             : 
     323             : 
     324          48 : void WMFWriter::WriteRectangle(const Rectangle & rRect)
     325             : {
     326          48 :     WritePointYX(Point(rRect.Right()+1,rRect.Bottom()+1));
     327          48 :     WritePointYX(rRect.TopLeft());
     328          48 : }
     329             : 
     330             : 
     331         694 : void WMFWriter::WriteColor(const Color & rColor)
     332             : {
     333         694 :     *pWMF << (sal_uInt8) rColor.GetRed() << (sal_uInt8) rColor.GetGreen() << (sal_uInt8) rColor.GetBlue() << (sal_uInt8) 0;
     334         694 : }
     335             : 
     336             : 
     337        3925 : void WMFWriter::WriteRecordHeader(sal_uInt32 nSizeWords, sal_uInt16 nType)
     338             : {
     339        3925 :     nActRecordPos=pWMF->Tell();
     340        3925 :     if (nSizeWords>nMaxRecordSize) nMaxRecordSize=nSizeWords;
     341        3925 :     *pWMF << nSizeWords << nType;
     342        3925 : }
     343             : 
     344             : 
     345         724 : void WMFWriter::UpdateRecordHeader()
     346             : {
     347             :     sal_uLong nPos;
     348             :     sal_uInt32 nSize;
     349             : 
     350         724 :     nPos=pWMF->Tell(); nSize=nPos-nActRecordPos;
     351         724 :     if ((nSize & 1)!=0) {
     352           0 :         *pWMF << (sal_uInt8)0;
     353           0 :         nPos++; nSize++;
     354             :     }
     355         724 :     nSize/=2;
     356         724 :     if (nSize>nMaxRecordSize) nMaxRecordSize=nSize;
     357         724 :     pWMF->Seek(nActRecordPos);
     358         724 :     *pWMF << nSize;
     359         724 :     pWMF->Seek(nPos);
     360         724 : }
     361             : 
     362             : 
     363           0 : void WMFWriter::WMFRecord_Arc(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
     364             : {
     365           0 :     WriteRecordHeader(0x0000000b,W_META_ARC);
     366           0 :     WritePointYX(rEndPt);
     367           0 :     WritePointYX(rStartPt);
     368           0 :     WriteRectangle(rRect);
     369           0 : }
     370             : 
     371           0 : void WMFWriter::WMFRecord_Chord(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
     372             : {
     373           0 :     WriteRecordHeader(0x0000000b,W_META_CHORD);
     374           0 :     WritePointYX(rEndPt);
     375           0 :     WritePointYX(rStartPt);
     376           0 :     WriteRectangle(rRect);
     377           0 : }
     378             : 
     379             : 
     380         167 : void WMFWriter::WMFRecord_CreateBrushIndirect(const Color& rColor)
     381             : {
     382         167 :     WriteRecordHeader(0x00000007,W_META_CREATEBRUSHINDIRECT);
     383             : 
     384         167 :     if( rColor==Color(COL_TRANSPARENT) )
     385           0 :         *pWMF << (sal_uInt16) W_BS_HOLLOW;
     386             :     else
     387         167 :         *pWMF << (sal_uInt16) W_BS_SOLID;
     388             : 
     389         167 :     WriteColor( rColor );
     390         167 :     *pWMF << (sal_uInt16) 0;
     391         167 : }
     392             : 
     393             : 
     394         399 : void WMFWriter::WMFRecord_CreateFontIndirect(const Font & rFont)
     395             : {
     396             :     sal_uInt16 nWeight,i;
     397             :     sal_uInt8 nPitchFamily;
     398             : 
     399         399 :     WriteRecordHeader(0x00000000,W_META_CREATEFONTINDIRECT);
     400         399 :     WriteHeightWidth(Size(rFont.GetSize().Width(),-rFont.GetSize().Height()));
     401         399 :     *pWMF << (short)rFont.GetOrientation() << (short)rFont.GetOrientation();
     402             : 
     403         399 :     switch (rFont.GetWeight()) {
     404           0 :         case WEIGHT_THIN:       nWeight=W_FW_THIN;       break;
     405           0 :         case WEIGHT_ULTRALIGHT: nWeight=W_FW_ULTRALIGHT; break;
     406           0 :         case WEIGHT_LIGHT:      nWeight=W_FW_LIGHT;      break;
     407           0 :         case WEIGHT_SEMILIGHT:  nWeight=W_FW_LIGHT;      break;
     408         370 :         case WEIGHT_NORMAL:     nWeight=W_FW_NORMAL;     break;
     409           0 :         case WEIGHT_MEDIUM:     nWeight=W_FW_MEDIUM;     break;
     410           0 :         case WEIGHT_SEMIBOLD:   nWeight=W_FW_SEMIBOLD;   break;
     411           0 :         case WEIGHT_BOLD:       nWeight=W_FW_BOLD;       break;
     412           0 :         case WEIGHT_ULTRABOLD:  nWeight=W_FW_ULTRABOLD;  break;
     413           0 :         case WEIGHT_BLACK:      nWeight=W_FW_BLACK;      break;
     414          29 :         default:                nWeight=W_FW_DONTCARE;
     415             :     }
     416         399 :     *pWMF << nWeight;
     417             : 
     418         399 :     if (rFont.GetItalic()==ITALIC_NONE)       *pWMF << (sal_uInt8)0; else  *pWMF << (sal_uInt8)1;
     419         399 :     if (rFont.GetUnderline()==UNDERLINE_NONE) *pWMF << (sal_uInt8)0; else  *pWMF << (sal_uInt8)1;
     420         399 :     if (rFont.GetStrikeout()==STRIKEOUT_NONE) *pWMF << (sal_uInt8)0; else  *pWMF << (sal_uInt8)1;
     421             : 
     422         399 :     CharSet     eFontNameEncoding = rFont.GetCharSet();
     423         399 :     sal_uInt8   nCharSet = rtl_getBestWindowsCharsetFromTextEncoding( eFontNameEncoding );
     424         399 :     if ( eFontNameEncoding == RTL_TEXTENCODING_SYMBOL )
     425           0 :         eFontNameEncoding = RTL_TEXTENCODING_MS_1252;
     426         399 :     if ( nCharSet == 1 )
     427           0 :         nCharSet = W_ANSI_CHARSET;
     428         399 :     *pWMF << nCharSet;
     429             : 
     430         399 :     *pWMF << (sal_uInt8)0 << (sal_uInt8)0 << (sal_uInt8)0;
     431             : 
     432         399 :     switch (rFont.GetPitch()) {
     433           0 :         case PITCH_FIXED:    nPitchFamily=W_FIXED_PITCH;    break;
     434           0 :         case PITCH_VARIABLE: nPitchFamily=W_VARIABLE_PITCH; break;
     435         399 :         default:             nPitchFamily=W_DEFAULT_PITCH;
     436             :     }
     437         399 :     switch (rFont.GetFamily()) {
     438           0 :         case FAMILY_DECORATIVE: nPitchFamily|=W_FF_DECORATIVE; break;
     439           0 :         case FAMILY_MODERN:     nPitchFamily|=W_FF_MODERN;     break;
     440         232 :         case FAMILY_ROMAN:      nPitchFamily|=W_FF_ROMAN;      break;
     441           0 :         case FAMILY_SCRIPT:     nPitchFamily|=W_FF_SCRIPT;     break;
     442           0 :         case FAMILY_SWISS:      nPitchFamily|=W_FF_SWISS;      break;
     443         167 :         default:                nPitchFamily|=W_FF_DONTCARE;
     444             :     }
     445         399 :     *pWMF << nPitchFamily;
     446             : 
     447         399 :     rtl::OString aFontName(rtl::OUStringToOString(rFont.GetName(), eFontNameEncoding));
     448       13167 :     for ( i = 0; i < W_LF_FACESIZE; i++ )
     449             :     {
     450       12768 :         sal_Char nChar = ( i < aFontName.getLength() ) ? aFontName[i] : 0;
     451       12768 :         *pWMF << nChar;
     452             :     }
     453         399 :     UpdateRecordHeader();
     454         399 : }
     455             : 
     456         167 : void WMFWriter::WMFRecord_CreatePenIndirect(const Color& rColor, const LineInfo& rLineInfo )
     457             : {
     458         167 :     WriteRecordHeader(0x00000008,W_META_CREATEPENINDIRECT);
     459         167 :     sal_uInt16 nStyle = rColor == Color( COL_TRANSPARENT ) ? W_PS_NULL : W_PS_SOLID;
     460         167 :     switch( rLineInfo.GetStyle() )
     461             :     {
     462             :         case LINE_DASH :
     463             :         {
     464           0 :             if ( rLineInfo.GetDotCount() )
     465             :             {
     466           0 :                 if ( !rLineInfo.GetDashCount() )
     467           0 :                     nStyle = W_PS_DOT;
     468             :                 else
     469             :                 {
     470           0 :                     if ( !rLineInfo.GetDotCount() == 1 )
     471           0 :                         nStyle = W_PS_DASHDOT;
     472             :                     else
     473           0 :                         nStyle = W_PS_DASHDOTDOT;
     474             :                 }
     475             :             }
     476             :             else
     477           0 :                 nStyle = W_PS_DASH;
     478             :         }
     479           0 :         break;
     480             :         case LINE_NONE :
     481           0 :             nStyle = W_PS_NULL;
     482           0 :         break;
     483             :         default:
     484         167 :         break;
     485             :     }
     486         167 :     *pWMF << nStyle;
     487             : 
     488         167 :     WriteSize( Size( rLineInfo.GetWidth(), 0 ) );
     489         167 :     WriteColor( rColor );
     490         167 : }
     491             : 
     492         646 : void WMFWriter::WMFRecord_DeleteObject(sal_uInt16 nObjectHandle)
     493             : {
     494         646 :     WriteRecordHeader(0x00000004,W_META_DELETEOBJECT);
     495         646 :     *pWMF << nObjectHandle;
     496         646 : }
     497             : 
     498             : 
     499           0 : void WMFWriter::WMFRecord_Ellipse(const Rectangle & rRect)
     500             : {
     501           0 :     WriteRecordHeader(0x00000007,W_META_ELLIPSE);
     502           0 :     WriteRectangle(rRect);
     503           0 : }
     504             : 
     505         305 : bool IsStarSymbol(const String &rStr)
     506             : {
     507         305 :     return rStr.EqualsIgnoreCaseAscii("starsymbol") ||
     508         305 :         rStr.EqualsIgnoreCaseAscii("opensymbol");
     509             : }
     510             : 
     511         119 : void WMFWriter::WMFRecord_Escape( sal_uInt32 nEsc, sal_uInt32 nLen, const sal_Int8* pData )
     512             : {
     513             : #ifdef OSL_BIGENDIAN
     514             :     sal_uInt32 nTmp = OSL_SWAPDWORD( nEsc );
     515             :     sal_uInt32 nCheckSum = rtl_crc32( 0, &nTmp, 4 );
     516             : #else
     517         119 :     sal_uInt32 nCheckSum = rtl_crc32( 0, &nEsc, 4 );
     518             : #endif
     519         119 :     if ( nLen )
     520         119 :         nCheckSum = rtl_crc32( nCheckSum, pData, nLen );
     521             : 
     522         119 :     WriteRecordHeader( 3 + 9 + ( ( nLen + 1 ) >> 1 ), W_META_ESCAPE );
     523         119 :     *pWMF << (sal_uInt16)W_MFCOMMENT
     524         238 :           << (sal_uInt16)( nLen + 14 )  // we will always have a fourteen byte escape header:
     525         119 :           << (sal_uInt16)0x4f4f         // OO
     526         119 :           << (sal_uInt32)0xa2c2a        // evil magic number
     527         119 :           << (sal_uInt32)nCheckSum      // crc32 checksum about nEsc & pData
     528         238 :           << (sal_uInt32)nEsc;          // escape number
     529         119 :     pWMF->Write( pData, nLen );
     530         119 :     if ( nLen & 1 )
     531           0 :         *pWMF << (sal_uInt8)0;          // pad byte
     532         119 : }
     533             : 
     534             : /* if return value is true, then a complete unicode string and also a polygon replacement has been written,
     535             :     so there is no more action necessary
     536             : */
     537         331 : sal_Bool WMFWriter::WMFRecord_Escape_Unicode( const Point& rPoint, const String& rUniStr, const sal_Int32* pDXAry )
     538             : {
     539         331 :     sal_Bool bEscapeUsed = sal_False;
     540             : 
     541         331 :     sal_uInt32 i, nStringLen = rUniStr.Len();
     542         331 :     if ( nStringLen )
     543             :     {
     544             :         // first we will check if a comment is necessary
     545         331 :         if ( aSrcFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL )     // symbol is always byte character, so there is no unicode loss
     546             :         {
     547         331 :             const sal_Unicode* pBuf = rUniStr.GetBuffer();
     548         331 :             const rtl_TextEncoding aTextEncodingOrg = aSrcFont.GetCharSet();
     549         331 :             rtl::OString aByteStr(rtl::OUStringToOString(rUniStr, aTextEncodingOrg));
     550         331 :             rtl::OUString aUniStr2(rtl::OStringToOUString(aByteStr, aTextEncodingOrg));
     551         331 :             const sal_Unicode* pConversion = aUniStr2.getStr();  // this is the unicode array after bytestring <-> unistring conversion
     552         638 :             for ( i = 0; i < nStringLen; i++ )
     553             :             {
     554         372 :                 if ( *pBuf++ != *pConversion++ )
     555          65 :                     break;
     556             :             }
     557             : 
     558         331 :             if  ( i != nStringLen )                             // after conversion the characters are not original,
     559             :             {                                                   // try again, with determining a better charset from unicode char
     560          65 :                 pBuf = rUniStr.GetBuffer();
     561          65 :                 const sal_Unicode* pCheckChar = pBuf;
     562          65 :                 rtl_TextEncoding aTextEncoding = getBestMSEncodingByChar(*pCheckChar); // try the first character
     563          67 :                 for ( i = 1; i < nStringLen; i++)
     564             :                 {
     565           4 :                     if (aTextEncoding != aTextEncodingOrg) // found something
     566           2 :                         break;
     567           2 :                     pCheckChar++;
     568           2 :                     aTextEncoding = getBestMSEncodingByChar(*pCheckChar); // try the next character
     569             :                 }
     570             : 
     571          65 :                 aByteStr = rtl::OUStringToOString(rUniStr,  aTextEncoding);
     572          65 :                 aUniStr2 = rtl::OStringToOUString(aByteStr, aTextEncoding);
     573          65 :                 pConversion = aUniStr2.getStr(); // this is the unicode array after bytestring <-> unistring conversion
     574         108 :                 for ( i = 0; i < nStringLen; i++ )
     575             :                 {
     576          69 :                     if ( *pBuf++ != *pConversion++ )
     577          26 :                         break;
     578             :                 }
     579          65 :                 if (i == nStringLen)
     580             :                 {
     581          39 :                     aSrcFont.SetCharSet (aTextEncoding);
     582          39 :                     SetAllAttr();
     583             :                 }
     584             :             }
     585             : 
     586         331 :             if ( ( i != nStringLen ) || IsStarSymbol( aSrcFont.GetName() ) )    // after conversion the characters are not original, so we
     587             :             {                                                                   // will store the unicode string and a polypoly replacement
     588         119 :                 Color aOldFillColor( aSrcFillColor );
     589         119 :                 Color aOldLineColor( aSrcLineColor );
     590         119 :                 aSrcLineInfo  = LineInfo();
     591         119 :                 aSrcFillColor = aSrcTextColor;
     592         119 :                 aSrcLineColor = Color( COL_TRANSPARENT );
     593         119 :                 SetLineAndFillAttr();
     594         119 :                 pVirDev->SetFont( aSrcFont );
     595         119 :                 std::vector<PolyPolygon> aPolyPolyVec;
     596         119 :                 if ( pVirDev->GetTextOutlines( aPolyPolyVec, rUniStr ) )
     597             :                 {
     598         119 :                     sal_uInt32 nDXCount = pDXAry ? nStringLen : 0;
     599         119 :                     sal_uInt32 nSkipActions = aPolyPolyVec.size();
     600             :                     sal_Int32 nStrmLen = 8 +
     601             :                                            + sizeof( nStringLen ) + ( nStringLen * 2 )
     602             :                                            + sizeof( nDXCount ) + ( nDXCount * 4 )
     603         119 :                                            + sizeof( nSkipActions );
     604             : 
     605         119 :                     SvMemoryStream aMemoryStream( nStrmLen );
     606         119 :                     Point aPt( pVirDev->LogicToLogic( rPoint, aSrcMapMode, aTargetMapMode ) );
     607         119 :                     aMemoryStream << static_cast<sal_Int32>(aPt.X())
     608         238 :                                   << static_cast<sal_Int32>(aPt.Y())
     609         119 :                                   << nStringLen;
     610         238 :                     for ( i = 0; i < nStringLen; i++ )
     611         119 :                         aMemoryStream << rUniStr.GetChar( (sal_uInt16)i );
     612         119 :                     aMemoryStream << nDXCount;
     613         119 :                     for ( i = 0; i < nDXCount; i++ )
     614           0 :                         aMemoryStream << pDXAry[ i ];
     615         119 :                     aMemoryStream << nSkipActions;
     616         119 :                     WMFRecord_Escape( PRIVATE_ESCAPE_UNICODE, nStrmLen, (const sal_Int8*)aMemoryStream.GetData() );
     617             : 
     618         119 :                     std::vector<PolyPolygon>::iterator aIter( aPolyPolyVec.begin() );
     619         311 :                     while ( aIter != aPolyPolyVec.end() )
     620             :                     {
     621          73 :                         PolyPolygon aPolyPoly( *aIter++ );
     622          73 :                         aPolyPoly.Move( rPoint.X(), rPoint.Y() );
     623          73 :                         WMFRecord_PolyPolygon( aPolyPoly );
     624          73 :                     }
     625         119 :                     aSrcFillColor = aOldFillColor;
     626         119 :                     aSrcLineColor = aOldLineColor;
     627         119 :                     bEscapeUsed = sal_True;
     628         119 :                 }
     629         331 :             }
     630             :         }
     631             :     }
     632         331 :     return bEscapeUsed;
     633             : }
     634             : 
     635         212 : void WMFWriter::WMFRecord_ExtTextOut( const Point & rPoint,
     636             :     const String & rString, const sal_Int32 * pDXAry )
     637             : {
     638         212 :     sal_uInt16 nOriginalTextLen = rString.Len();
     639             : 
     640         212 :     if ( (nOriginalTextLen <= 1) || (pDXAry == NULL) )
     641             :     {
     642         192 :         WMFRecord_TextOut(rPoint, rString);
     643         212 :         return;
     644             :     }
     645          20 :     rtl_TextEncoding eChrSet = aSrcFont.GetCharSet();
     646          20 :     rtl::OString aByteString(rtl::OUStringToOString(rString, eChrSet));
     647          20 :     TrueExtTextOut(rPoint,rString,aByteString,pDXAry);
     648             : }
     649             : 
     650          20 : void WMFWriter::TrueExtTextOut( const Point & rPoint, const String & rString,
     651             :     const rtl::OString& rByteString, const sal_Int32 * pDXAry )
     652             : {
     653          20 :     WriteRecordHeader( 0, W_META_EXTTEXTOUT );
     654          20 :     WritePointYX( rPoint );
     655          20 :     sal_uInt16 nNewTextLen = static_cast<sal_uInt16>(rByteString.getLength());
     656          20 :     *pWMF << nNewTextLen << (sal_uInt16)0;
     657          20 :     write_uInt8s_FromOString(*pWMF, rByteString, nNewTextLen);
     658          20 :     if ( nNewTextLen & 1 )
     659          15 :         *pWMF << (sal_uInt8)0;
     660             : 
     661          20 :     sal_uInt16 nOriginalTextLen = rString.Len();
     662          20 :     sal_Int16* pConvertedDXAry = new sal_Int16[ nOriginalTextLen ];
     663          20 :     sal_Int32 j = 0;
     664          20 :     pConvertedDXAry[ j++ ] = (sal_Int16)ScaleWidth( pDXAry[ 0 ] );
     665          41 :     for (sal_uInt16 i = 1; i < ( nOriginalTextLen - 1 ); ++i)
     666          21 :         pConvertedDXAry[ j++ ] = (sal_Int16)ScaleWidth( pDXAry[ i ] - pDXAry[ i - 1 ] );
     667          20 :     pConvertedDXAry[ j ] = (sal_Int16)ScaleWidth( pDXAry[ nOriginalTextLen - 2 ] / ( nOriginalTextLen - 1 ) );
     668             : 
     669          81 :     for (sal_uInt16 i = 0; i < nOriginalTextLen; ++i)
     670             :     {
     671          61 :         sal_Int16 nDx = pConvertedDXAry[ i ];
     672          61 :         *pWMF << nDx;
     673          61 :         if ( nOriginalTextLen < nNewTextLen )
     674             :         {
     675           0 :             sal_Unicode nUniChar = rString.GetChar(i);
     676           0 :             rtl::OString aTemp(&nUniChar, 1, aSrcFont.GetCharSet());
     677           0 :             j = aTemp.getLength();
     678           0 :             while ( --j > 0 )
     679           0 :                 *pWMF << (sal_uInt16)0;
     680             :         }
     681             :     }
     682          20 :     delete[] pConvertedDXAry;
     683          20 :     UpdateRecordHeader();
     684          20 : }
     685             : 
     686           0 : void WMFWriter::WMFRecord_LineTo(const Point & rPoint)
     687             : {
     688           0 :     WriteRecordHeader(0x00000005,W_META_LINETO);
     689           0 :     WritePointYX(rPoint);
     690           0 : }
     691             : 
     692             : 
     693           0 : void WMFWriter::WMFRecord_MoveTo(const Point & rPoint)
     694             : {
     695           0 :     WriteRecordHeader(0x00000005,W_META_MOVETO);
     696           0 :     WritePointYX(rPoint);
     697           0 : }
     698             : 
     699             : 
     700           0 : void WMFWriter::WMFRecord_Pie(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
     701             : {
     702           0 :     WriteRecordHeader(0x0000000b,W_META_PIE);
     703           0 :     WritePointYX(rEndPt);
     704           0 :     WritePointYX(rStartPt);
     705           0 :     WriteRectangle(rRect);
     706           0 : }
     707             : 
     708             : 
     709           0 : void WMFWriter::WMFRecord_Polygon(const Polygon & rPoly)
     710             : {
     711             :     sal_uInt16 nSize,i;
     712             : 
     713           0 :     Polygon aSimplePoly;
     714           0 :     if ( rPoly.HasFlags() )
     715           0 :         rPoly.AdaptiveSubdivide( aSimplePoly );
     716             :     else
     717           0 :         aSimplePoly = rPoly;
     718           0 :     nSize = aSimplePoly.GetSize();
     719           0 :     WriteRecordHeader(((sal_uLong)nSize)*2+4,W_META_POLYGON);
     720           0 :     *pWMF << nSize;
     721           0 :     for (i=0; i<nSize; i++) WritePointXY(aSimplePoly.GetPoint(i));
     722           0 : }
     723             : 
     724             : 
     725           0 : void WMFWriter::WMFRecord_PolyLine(const Polygon & rPoly)
     726             : {
     727             :     sal_uInt16 nSize,i;
     728           0 :     Polygon aSimplePoly;
     729           0 :     if ( rPoly.HasFlags() )
     730           0 :         rPoly.AdaptiveSubdivide( aSimplePoly );
     731             :     else
     732           0 :         aSimplePoly = rPoly;
     733           0 :     nSize=aSimplePoly.GetSize();
     734           0 :     WriteRecordHeader(((sal_uLong)nSize)*2+4,W_META_POLYLINE);
     735           0 :     *pWMF << nSize;
     736           0 :     for (i=0; i<nSize; i++) WritePointXY(aSimplePoly.GetPoint(i));
     737           0 : }
     738             : 
     739             : 
     740          73 : void WMFWriter::WMFRecord_PolyPolygon(const PolyPolygon & rPolyPoly)
     741             : {
     742             :     const Polygon * pPoly;
     743             :     sal_uInt16 nCount,nSize,i,j;
     744             : 
     745          73 :     nCount=rPolyPoly.Count();
     746          73 :     PolyPolygon aSimplePolyPoly( rPolyPoly );
     747         338 :     for ( i = 0; i < nCount; i++ )
     748             :     {
     749         265 :         if ( aSimplePolyPoly[ i ].HasFlags() )
     750             :         {
     751         178 :             Polygon aSimplePoly;
     752         178 :             aSimplePolyPoly[ i ].AdaptiveSubdivide( aSimplePoly );
     753         178 :             aSimplePolyPoly[ i ] = aSimplePoly;
     754             :         }
     755             :     }
     756          73 :     WriteRecordHeader(0,W_META_POLYPOLYGON);
     757          73 :     *pWMF << nCount;
     758          73 :     for (i=0; i<nCount; i++) *pWMF << ((sal_uInt16)(aSimplePolyPoly.GetObject(i).GetSize()));
     759         338 :     for (i=0; i<nCount; i++) {
     760         265 :         pPoly=&(aSimplePolyPoly.GetObject(i));
     761         265 :         nSize=pPoly->GetSize();
     762         265 :         for (j=0; j<nSize; j++) WritePointXY(pPoly->GetPoint(j));
     763             :     }
     764          73 :     UpdateRecordHeader();
     765          73 : }
     766             : 
     767             : 
     768          19 : void WMFWriter::WMFRecord_Rectangle(const Rectangle & rRect)
     769             : {
     770          19 :     WriteRecordHeader( 0x00000007,W_META_RECTANGLE );
     771          19 :     WriteRectangle( rRect );
     772          19 : }
     773             : 
     774             : 
     775         379 : void WMFWriter::WMFRecord_RestoreDC()
     776             : {
     777         379 :     WriteRecordHeader(0x00000004,W_META_RESTOREDC);
     778         379 :     *pWMF << (short)-1;
     779         379 : }
     780             : 
     781             : 
     782           0 : void WMFWriter::WMFRecord_RoundRect(const Rectangle & rRect, long nHorzRound, long nVertRound)
     783             : {
     784           0 :     WriteRecordHeader(0x00000009,W_META_ROUNDRECT);
     785           0 :     WriteHeightWidth(Size(nHorzRound,nVertRound));
     786           0 :     WriteRectangle(rRect);
     787           0 : }
     788             : 
     789             : 
     790         379 : void WMFWriter::WMFRecord_SaveDC()
     791             : {
     792         379 :     WriteRecordHeader(0x00000003,W_META_SAVEDC);
     793         379 : }
     794             : 
     795             : 
     796         733 : void WMFWriter::WMFRecord_SelectObject(sal_uInt16 nObjectHandle)
     797             : {
     798         733 :     WriteRecordHeader(0x00000004,W_META_SELECTOBJECT);
     799         733 :     *pWMF << nObjectHandle;
     800         733 : }
     801             : 
     802             : 
     803          29 : void WMFWriter::WMFRecord_SetBkMode(sal_Bool bTransparent)
     804             : {
     805          29 :     WriteRecordHeader(0x00000004,W_META_SETBKMODE);
     806          29 :     if (bTransparent==sal_True) *pWMF << (sal_uInt16)W_TRANSPARENT;
     807           0 :     else                    *pWMF << (sal_uInt16)W_OPAQUE;
     808          29 : }
     809             : 
     810          29 : void WMFWriter::WMFRecord_SetStretchBltMode()
     811             : {
     812          29 :     WriteRecordHeader( 0x00000004, W_META_SETSTRETCHBLTMODE );
     813          29 :     *pWMF << (sal_uInt16) 3; // STRETCH_DELETESCANS
     814          29 : }
     815             : 
     816           0 : void WMFWriter::WMFRecord_SetPixel(const Point & rPoint, const Color & rColor)
     817             : {
     818           0 :     WriteRecordHeader(0x00000007,W_META_SETPIXEL);
     819           0 :     WriteColor(rColor);
     820           0 :     WritePointYX(rPoint);
     821           0 : }
     822             : 
     823             : 
     824          29 : void WMFWriter::WMFRecord_SetROP2(RasterOp eROP)
     825             : {
     826             :     sal_uInt16 nROP2;
     827             : 
     828          29 :     switch (eROP) {
     829           0 :         case ROP_INVERT: nROP2=W_R2_NOT;        break;
     830           0 :         case ROP_XOR:    nROP2=W_R2_XORPEN;     break;
     831          29 :         default:         nROP2=W_R2_COPYPEN;
     832             :     }
     833          29 :     WriteRecordHeader(0x00000004,W_META_SETROP2);
     834          29 :     *pWMF << nROP2;
     835          29 : }
     836             : 
     837             : 
     838          29 : void WMFWriter::WMFRecord_SetTextAlign(FontAlign eFontAlign, sal_uInt32 eHorTextAlign)
     839             : {
     840             :     sal_uInt16 nAlign;
     841             : 
     842          29 :     switch (eFontAlign) {
     843           0 :         case ALIGN_TOP:    nAlign=W_TA_TOP; break;
     844           0 :         case ALIGN_BOTTOM: nAlign=W_TA_BOTTOM; break;
     845          29 :         default:           nAlign=W_TA_BASELINE;
     846             :     }
     847          29 :     nAlign|=eHorTextAlign;
     848          29 :     nAlign|=W_TA_NOUPDATECP;
     849             : 
     850          29 :     WriteRecordHeader(0x00000004,W_META_SETTEXTALIGN);
     851          29 :     *pWMF << nAlign;
     852          29 : }
     853             : 
     854             : 
     855         360 : void WMFWriter::WMFRecord_SetTextColor(const Color & rColor)
     856             : {
     857         360 :     WriteRecordHeader(0x00000005,W_META_SETTEXTCOLOR);
     858         360 :     WriteColor(rColor);
     859         360 : }
     860             : 
     861             : 
     862          29 : void WMFWriter::WMFRecord_SetWindowExt(const Size & rSize)
     863             : {
     864          29 :     WriteRecordHeader(0x00000005,W_META_SETWINDOWEXT);
     865          29 :     WriteHeightWidth(rSize);
     866          29 : }
     867             : 
     868             : 
     869          29 : void WMFWriter::WMFRecord_SetWindowOrg(const Point & rPoint)
     870             : {
     871          29 :     WriteRecordHeader(0x00000005,W_META_SETWINDOWORG);
     872          29 :     WritePointYX(rPoint);
     873          29 : }
     874             : 
     875             : 
     876           0 : void WMFWriter::WMFRecord_StretchDIB( const Point & rPoint, const Size & rSize,
     877             :                                       const Bitmap & rBitmap, sal_uInt32 nROP )
     878             : {
     879             :     sal_uLong nPosAnf,nPosEnd;
     880             : 
     881           0 :     nActBitmapPercent=50;
     882           0 :     MayCallback();
     883             : 
     884           0 :     WriteRecordHeader(0x00000000,W_META_STRETCHDIB);
     885             : 
     886             :     // Die Reihenfolge im Metafile soll jetzt sein:
     887             :     // einige Parameter (laenge 22), dann die Bitmap ohne FILEHEADER.
     888             :     // Da aber *pWMF << rBitmap einen FILEHEADER der Laenge 14
     889             :     // erzeugt, schreiben wir zuerst die Bitmap an die richtige Position
     890             :     // Und ueberschreiben hinterher den FILEHEADER mit den Parametern.
     891           0 :     nPosAnf=pWMF->Tell(); // Position merken, wo Parameter hin sollen
     892           0 :     *pWMF << (sal_Int32)0 << (sal_Int32)0; // 8 bytes auffuellen (diese 8 bytes +
     893             :                                            // 14 bytes ueberfluessigen FILEHEADER
     894             :                                            // = 22 bytes Parameter)
     895           0 :     *pWMF << rBitmap; // Bitmap schreiben
     896             : 
     897             :     // Parameter schreiben:
     898           0 :     nPosEnd=pWMF->Tell();
     899           0 :     pWMF->Seek(nPosAnf);
     900             : 
     901             :     // Raster-Op bestimmen, falls nichts uebergeben wurde
     902           0 :     if( !nROP )
     903             :     {
     904           0 :         switch( eSrcRasterOp )
     905             :         {
     906           0 :             case ROP_INVERT: nROP = W_DSTINVERT; break;
     907           0 :             case ROP_XOR:    nROP = W_SRCINVERT; break;
     908           0 :             default:         nROP = W_SRCCOPY;
     909             :         }
     910             :     }
     911             : 
     912           0 :     *pWMF << nROP <<
     913           0 :              (short) 0 <<
     914           0 :              (short) rBitmap.GetSizePixel().Height() <<
     915           0 :              (short) rBitmap.GetSizePixel().Width() <<
     916           0 :              (short) 0 <<
     917           0 :              (short) 0;
     918             : 
     919           0 :     WriteHeightWidth(rSize);
     920           0 :     WritePointYX(rPoint);
     921           0 :     pWMF->Seek(nPosEnd);
     922             : 
     923           0 :     UpdateRecordHeader();
     924             : 
     925           0 :     nWrittenBitmaps++;
     926           0 :     nActBitmapPercent=0;
     927           0 : }
     928             : 
     929             : 
     930         192 : void WMFWriter::WMFRecord_TextOut(const Point & rPoint, const String & rStr)
     931             : {
     932         192 :     rtl_TextEncoding eChrSet = aSrcFont.GetCharSet();
     933         192 :     rtl::OString aString(rtl::OUStringToOString(rStr, eChrSet));
     934         192 :     TrueTextOut(rPoint, aString);
     935         192 : }
     936             : 
     937         192 : void WMFWriter::TrueTextOut(const Point & rPoint, const rtl::OString& rString)
     938             : {
     939         192 :     WriteRecordHeader(0,W_META_TEXTOUT);
     940             : 
     941         192 :     write_lenPrefixed_uInt8s_FromOString<sal_uInt16>(*pWMF, rString);
     942         192 :     sal_Int32 nLen = rString.getLength();
     943         192 :     if ((nLen&1)!=0) *pWMF << (sal_uInt8)0;
     944         192 :     WritePointYX(rPoint);
     945         192 :     UpdateRecordHeader();
     946         192 : }
     947             : 
     948          29 : void WMFWriter::WMFRecord_EndOfFile()
     949             : {
     950          29 :     WriteRecordHeader(0x00000003,0x0000);
     951          29 : }
     952             : 
     953             : 
     954          29 : void WMFWriter::WMFRecord_IntersectClipRect( const Rectangle& rRect )
     955             : {
     956          29 :     WriteRecordHeader( 0x00000007, W_META_INTERSECTCLIPRECT );
     957          29 :     WriteRectangle(rRect);
     958          29 : }
     959             : 
     960             : 
     961         733 : sal_uInt16 WMFWriter::AllocHandle()
     962             : {
     963             :     sal_uInt16 i;
     964             : 
     965        1853 :     for (i=0; i<MAXOBJECTHANDLES; i++) {
     966        1853 :         if (bHandleAllocated[i]==sal_False) {
     967         733 :             bHandleAllocated[i]=sal_True;
     968         733 :             return i;
     969             :         }
     970             :     }
     971           0 :     bStatus=sal_False;
     972           0 :     return 0xffff;
     973             : }
     974             : 
     975             : 
     976         646 : void WMFWriter::FreeHandle(sal_uInt16 nObjectHandle)
     977             : {
     978         646 :     if (nObjectHandle<MAXOBJECTHANDLES) bHandleAllocated[nObjectHandle]=sal_False;
     979         646 : }
     980             : 
     981             : 
     982         167 : void WMFWriter::CreateSelectDeletePen( const Color& rColor, const LineInfo& rLineInfo )
     983             : {
     984             :     sal_uInt16 nOldHandle;
     985             : 
     986         167 :     nOldHandle=nDstPenHandle;
     987         167 :     nDstPenHandle=AllocHandle();
     988         167 :     WMFRecord_CreatePenIndirect( rColor, rLineInfo );
     989         167 :     WMFRecord_SelectObject(nDstPenHandle);
     990         167 :     if (nOldHandle<MAXOBJECTHANDLES) {
     991         138 :         WMFRecord_DeleteObject(nOldHandle);
     992         138 :         FreeHandle(nOldHandle);
     993             :     }
     994         167 : }
     995             : 
     996             : 
     997         399 : void WMFWriter::CreateSelectDeleteFont(const Font & rFont)
     998             : {
     999             :     sal_uInt16 nOldHandle;
    1000             : 
    1001         399 :     nOldHandle=nDstFontHandle;
    1002         399 :     nDstFontHandle=AllocHandle();
    1003         399 :     WMFRecord_CreateFontIndirect(rFont);
    1004         399 :     WMFRecord_SelectObject(nDstFontHandle);
    1005         399 :     if (nOldHandle<MAXOBJECTHANDLES) {
    1006         370 :         WMFRecord_DeleteObject(nOldHandle);
    1007         370 :         FreeHandle(nOldHandle);
    1008             :     }
    1009         399 : }
    1010             : 
    1011             : 
    1012         167 : void WMFWriter::CreateSelectDeleteBrush(const Color& rColor)
    1013             : {
    1014             :     sal_uInt16 nOldHandle;
    1015             : 
    1016         167 :     nOldHandle=nDstBrushHandle;
    1017         167 :     nDstBrushHandle=AllocHandle();
    1018         167 :     WMFRecord_CreateBrushIndirect(rColor);
    1019         167 :     WMFRecord_SelectObject(nDstBrushHandle);
    1020         167 :     if (nOldHandle<MAXOBJECTHANDLES) {
    1021         138 :         WMFRecord_DeleteObject(nOldHandle);
    1022         138 :         FreeHandle(nOldHandle);
    1023             :     }
    1024         167 : }
    1025             : 
    1026             : 
    1027         887 : void WMFWriter::SetLineAndFillAttr()
    1028             : {
    1029         887 :     if ( eDstROP2 != eSrcRasterOp )
    1030             :     {
    1031           0 :         eDstROP2=eSrcRasterOp;
    1032           0 :         WMFRecord_SetROP2(eDstROP2);
    1033             :     }
    1034         887 :     if ( ( aDstLineColor != aSrcLineColor ) || ( aDstLineInfo != aSrcLineInfo ) )
    1035             :     {
    1036         138 :         aDstLineColor = aSrcLineColor;
    1037         138 :         aDstLineInfo  = aSrcLineInfo;
    1038         138 :         CreateSelectDeletePen( aDstLineColor, aDstLineInfo );
    1039             :     }
    1040         887 :     if ( aDstFillColor != aSrcFillColor )
    1041             :     {
    1042         138 :         aDstFillColor = aSrcFillColor;
    1043         138 :         CreateSelectDeleteBrush( aDstFillColor );
    1044             :     }
    1045         887 :     if ( bDstIsClipping != bSrcIsClipping ||
    1046           0 :         (bSrcIsClipping==sal_True && aDstClipRegion!=aSrcClipRegion)) {
    1047           0 :         bDstIsClipping=bSrcIsClipping;
    1048           0 :         aDstClipRegion=aSrcClipRegion;
    1049             :     }
    1050         887 : }
    1051             : 
    1052         749 : void WMFWriter::SetAllAttr()
    1053             : {
    1054         749 :     SetLineAndFillAttr();
    1055         749 :     if ( aDstTextColor != aSrcTextColor )
    1056             :     {
    1057         331 :         aDstTextColor = aSrcTextColor;
    1058         331 :         WMFRecord_SetTextColor(aDstTextColor);
    1059             :     }
    1060         749 :     if ( eDstTextAlign != eSrcTextAlign || eDstHorTextAlign != eSrcHorTextAlign )
    1061             :     {
    1062           0 :         eDstTextAlign = eSrcTextAlign;
    1063           0 :         eDstHorTextAlign = eSrcHorTextAlign;
    1064           0 :         WMFRecord_SetTextAlign( eDstTextAlign, eDstHorTextAlign );
    1065             :     }
    1066         749 :     if ( aDstFont != aSrcFont )
    1067             :     {
    1068         370 :         pVirDev->SetFont(aSrcFont);
    1069         370 :         if ( aDstFont.GetName() != aSrcFont.GetName() )
    1070             :         {
    1071         331 :             FontCharMap aFontCharMap;
    1072         331 :             if ( pVirDev->GetFontCharMap( aFontCharMap ) )
    1073             :             {
    1074         331 :                 if ( ( aFontCharMap.GetFirstChar() & 0xff00 ) == 0xf000 )
    1075           0 :                     aSrcFont.SetCharSet( RTL_TEXTENCODING_SYMBOL );
    1076         331 :                 else if ( aSrcFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
    1077           0 :                     aSrcFont.SetCharSet( RTL_TEXTENCODING_MS_1252 );
    1078         331 :             }
    1079             :         }
    1080         370 :         aDstFont = aSrcFont;
    1081         370 :         CreateSelectDeleteFont(aDstFont);
    1082             :     }
    1083         749 : }
    1084             : 
    1085             : 
    1086           0 : void WMFWriter::HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon)
    1087             : {
    1088           0 :     if(rLinePolygon.count())
    1089             :     {
    1090           0 :         basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon);
    1091           0 :         basegfx::B2DPolyPolygon aFillPolyPolygon;
    1092             : 
    1093           0 :         rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon);
    1094             : 
    1095           0 :         if(aLinePolyPolygon.count())
    1096             :         {
    1097           0 :             aSrcLineInfo = rInfo;
    1098           0 :             SetLineAndFillAttr();
    1099             : 
    1100           0 :             for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++)
    1101             :             {
    1102           0 :                 const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a));
    1103           0 :                 WMFRecord_PolyLine(Polygon(aCandidate));
    1104           0 :             }
    1105             :         }
    1106             : 
    1107           0 :         if(aFillPolyPolygon.count())
    1108             :         {
    1109           0 :             const Color aOldLineColor(aSrcLineColor);
    1110           0 :             const Color aOldFillColor(aSrcFillColor);
    1111             : 
    1112           0 :             aSrcLineColor = Color( COL_TRANSPARENT );
    1113           0 :             aSrcFillColor = aOldLineColor;
    1114           0 :             SetLineAndFillAttr();
    1115             : 
    1116           0 :             for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++)
    1117             :             {
    1118           0 :                 const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a));
    1119           0 :                 WMFRecord_Polygon(Polygon(aPolygon));
    1120           0 :             }
    1121             : 
    1122           0 :             aSrcLineColor = aOldLineColor;
    1123           0 :             aSrcFillColor = aOldFillColor;
    1124           0 :             SetLineAndFillAttr();
    1125           0 :         }
    1126             :     }
    1127           0 : }
    1128             : 
    1129          29 : void WMFWriter::WriteRecords( const GDIMetaFile & rMTF )
    1130             : {
    1131             :     MetaAction* pMA;
    1132             : 
    1133          29 :     if( bStatus )
    1134             :     {
    1135          29 :         size_t nACount = rMTF.GetActionSize();
    1136             : 
    1137          29 :         WMFRecord_SetStretchBltMode();
    1138             : 
    1139        2752 :         for( size_t nA = 0; nA < nACount; nA++ )
    1140             :         {
    1141        2723 :             pMA = rMTF.GetAction( nA );
    1142             : 
    1143        2723 :             switch( pMA->GetType() )
    1144             :             {
    1145             :                 case META_PIXEL_ACTION:
    1146             :                 {
    1147           0 :                     const MetaPixelAction* pA = (const MetaPixelAction *) pMA;
    1148           0 :                     aSrcLineInfo = LineInfo();
    1149           0 :                     SetLineAndFillAttr();
    1150           0 :                     WMFRecord_SetPixel( pA->GetPoint(), pA->GetColor() );
    1151             :                 }
    1152           0 :                 break;
    1153             : 
    1154             :                 case META_POINT_ACTION:
    1155             :                 {
    1156           0 :                     const MetaPointAction*  pA = (const MetaPointAction*) pMA;
    1157           0 :                     const Point&            rPt = pA->GetPoint();
    1158           0 :                     aSrcLineInfo = LineInfo();
    1159           0 :                     SetLineAndFillAttr();
    1160           0 :                     WMFRecord_MoveTo( rPt);
    1161           0 :                     WMFRecord_LineTo( rPt );
    1162             :                 }
    1163           0 :                 break;
    1164             : 
    1165             :                 case META_LINE_ACTION:
    1166             :                 {
    1167           0 :                     const MetaLineAction* pA = (const MetaLineAction *) pMA;
    1168           0 :                     if(pA->GetLineInfo().IsDefault())
    1169             :                     {
    1170           0 :                         aSrcLineInfo = pA->GetLineInfo();
    1171           0 :                         SetLineAndFillAttr();
    1172           0 :                         WMFRecord_MoveTo( pA->GetStartPoint() );
    1173           0 :                         WMFRecord_LineTo( pA->GetEndPoint() );
    1174             :                     }
    1175             :                     else
    1176             :                     {
    1177             :                         // LineInfo used; handle Dash/Dot and fat lines
    1178           0 :                         basegfx::B2DPolygon aPolygon;
    1179           0 :                         aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y()));
    1180           0 :                         aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y()));
    1181           0 :                         HandleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon);
    1182             :                     }
    1183             :                 }
    1184           0 :                 break;
    1185             : 
    1186             :                 case META_RECT_ACTION:
    1187             :                 {
    1188          19 :                     const MetaRectAction* pA = (const MetaRectAction*) pMA;
    1189          19 :                     aSrcLineInfo = LineInfo();
    1190          19 :                     SetLineAndFillAttr();
    1191          19 :                     WMFRecord_Rectangle( pA->GetRect() );
    1192             :                 }
    1193          19 :                 break;
    1194             : 
    1195             :                 case META_ROUNDRECT_ACTION:
    1196             :                 {
    1197           0 :                     const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pMA;
    1198           0 :                     aSrcLineInfo = LineInfo();
    1199           0 :                     SetLineAndFillAttr();
    1200           0 :                     WMFRecord_RoundRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
    1201             :                 }
    1202           0 :                 break;
    1203             : 
    1204             :                 case META_ELLIPSE_ACTION:
    1205             :                 {
    1206           0 :                     const MetaEllipseAction* pA = (const MetaEllipseAction*) pMA;
    1207           0 :                     aSrcLineInfo = LineInfo();
    1208           0 :                     SetLineAndFillAttr();
    1209           0 :                     WMFRecord_Ellipse( pA->GetRect() );
    1210             :                 }
    1211           0 :                 break;
    1212             : 
    1213             :                 case META_ARC_ACTION:
    1214             :                 {
    1215           0 :                     const MetaArcAction* pA = (const MetaArcAction*) pMA;
    1216           0 :                     aSrcLineInfo = LineInfo();
    1217           0 :                     SetLineAndFillAttr();
    1218           0 :                     WMFRecord_Arc( pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint() );
    1219             :                 }
    1220           0 :                 break;
    1221             : 
    1222             :                 case META_PIE_ACTION:
    1223             :                 {
    1224           0 :                     const MetaPieAction* pA = (const MetaPieAction*) pMA;
    1225           0 :                     aSrcLineInfo = LineInfo();
    1226           0 :                     SetLineAndFillAttr();
    1227           0 :                     WMFRecord_Pie( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
    1228             :                 }
    1229           0 :                 break;
    1230             : 
    1231             : 
    1232             :                 case META_CHORD_ACTION:
    1233             :                 {
    1234           0 :                     const MetaChordAction* pA = (const MetaChordAction*) pMA;
    1235           0 :                     aSrcLineInfo = LineInfo();
    1236           0 :                     SetLineAndFillAttr();
    1237           0 :                     WMFRecord_Chord( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
    1238             :                 }
    1239           0 :                 break;
    1240             : 
    1241             :                 case META_POLYLINE_ACTION:
    1242             :                 {
    1243           0 :                     const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pMA;
    1244           0 :                     const Polygon&              rPoly = pA->GetPolygon();
    1245             : 
    1246           0 :                     if( rPoly.GetSize() )
    1247             :                     {
    1248           0 :                         if(pA->GetLineInfo().IsDefault())
    1249             :                         {
    1250           0 :                             aSrcLineInfo = pA->GetLineInfo();
    1251           0 :                             SetLineAndFillAttr();
    1252           0 :                             WMFRecord_PolyLine( rPoly );
    1253             :                         }
    1254             :                         else
    1255             :                         {
    1256             :                             // LineInfo used; handle Dash/Dot and fat lines
    1257           0 :                             HandleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon());
    1258             :                         }
    1259             :                     }
    1260             :                 }
    1261           0 :                 break;
    1262             : 
    1263             :                 case META_POLYGON_ACTION:
    1264             :                 {
    1265           0 :                     const MetaPolygonAction* pA = (const MetaPolygonAction*) pMA;
    1266           0 :                     aSrcLineInfo = LineInfo();
    1267           0 :                     SetLineAndFillAttr();
    1268           0 :                     WMFRecord_Polygon( pA->GetPolygon() );
    1269             :                 }
    1270           0 :                 break;
    1271             : 
    1272             :                 case META_POLYPOLYGON_ACTION:
    1273             :                 {
    1274           0 :                     const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pMA;
    1275           0 :                     aSrcLineInfo = LineInfo();
    1276           0 :                     SetLineAndFillAttr();
    1277           0 :                     WMFRecord_PolyPolygon( pA->GetPolyPolygon() );
    1278             :                 }
    1279           0 :                 break;
    1280             : 
    1281             :                 case META_TEXTRECT_ACTION:
    1282             :                 {
    1283           0 :                     const MetaTextRectAction * pA = (const MetaTextRectAction*)pMA;
    1284           0 :                     String aTemp( pA->GetText() );
    1285           0 :                     aSrcLineInfo = LineInfo();
    1286           0 :                     SetAllAttr();
    1287             : 
    1288           0 :                     Point aPos( pA->GetRect().TopLeft() );
    1289           0 :                     if ( !WMFRecord_Escape_Unicode( aPos, aTemp, NULL ) )
    1290           0 :                         WMFRecord_TextOut( aPos, aTemp );
    1291             :                 }
    1292           0 :                 break;
    1293             : 
    1294             :                 case META_TEXT_ACTION:
    1295             :                 {
    1296           0 :                     const MetaTextAction * pA = (const MetaTextAction*) pMA;
    1297           0 :                     String aTemp( pA->GetText(), pA->GetIndex(), pA->GetLen() );
    1298           0 :                     aSrcLineInfo = LineInfo();
    1299           0 :                     SetAllAttr();
    1300           0 :                     if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, NULL ) )
    1301           0 :                         WMFRecord_TextOut( pA->GetPoint(), aTemp );
    1302             :                 }
    1303           0 :                 break;
    1304             : 
    1305             :                 case META_TEXTARRAY_ACTION:
    1306             :                 {
    1307           0 :                     const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pMA;
    1308             : 
    1309           0 :                     String aTemp( pA->GetText(), pA->GetIndex(), pA->GetLen() );
    1310           0 :                     aSrcLineInfo = LineInfo();
    1311           0 :                     SetAllAttr();
    1312           0 :                     if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, pA->GetDXArray() ) )
    1313           0 :                         WMFRecord_ExtTextOut( pA->GetPoint(), aTemp, pA->GetDXArray() );
    1314             :                 }
    1315           0 :                 break;
    1316             : 
    1317             :                 case META_STRETCHTEXT_ACTION:
    1318             :                 {
    1319         331 :                     const MetaStretchTextAction* pA = (const MetaStretchTextAction *) pMA;
    1320         331 :                     String aTemp( pA->GetText(), pA->GetIndex(), pA->GetLen() );
    1321             : 
    1322             :                     sal_uInt16 nLen,i;
    1323             :                     sal_Int32 nNormSize;
    1324             : 
    1325         331 :                     pVirDev->SetFont( aSrcFont );
    1326         331 :                     nLen = aTemp.Len();
    1327         331 :                     sal_Int32* pDXAry = nLen ? new sal_Int32[ nLen ] : NULL;
    1328         331 :                     nNormSize = pVirDev->GetTextArray( aTemp, pDXAry );
    1329         374 :                     for ( i = 0; i < ( nLen - 1 ); i++ )
    1330          43 :                         pDXAry[ i ] = pDXAry[ i ] * (sal_Int32)pA->GetWidth() / nNormSize;
    1331         331 :                     if ( ( nLen <= 1 ) || ( (sal_Int32)pA->GetWidth() == nNormSize ) )
    1332         311 :                         delete[] pDXAry, pDXAry = NULL;
    1333         331 :                     aSrcLineInfo = LineInfo();
    1334         331 :                     SetAllAttr();
    1335         331 :                     if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, pDXAry ) )
    1336         212 :                         WMFRecord_ExtTextOut( pA->GetPoint(), aTemp, pDXAry );
    1337         331 :                     delete[] pDXAry;
    1338             :                 }
    1339         331 :                 break;
    1340             : 
    1341             :                 case META_BMP_ACTION:
    1342             :                 {
    1343           0 :                     const MetaBmpAction* pA = (const MetaBmpAction *) pMA;
    1344           0 :                     WMFRecord_StretchDIB( pA->GetPoint(), pA->GetBitmap().GetSizePixel(), pA->GetBitmap() );
    1345             :                 }
    1346           0 :                 break;
    1347             : 
    1348             :                 case META_BMPSCALE_ACTION:
    1349             :                 {
    1350           0 :                     const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pMA;
    1351           0 :                     WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), pA->GetBitmap() );
    1352             :                 }
    1353           0 :                 break;
    1354             : 
    1355             :                 case META_BMPSCALEPART_ACTION:
    1356             :                 {
    1357           0 :                     const MetaBmpScalePartAction*   pA = (const MetaBmpScalePartAction*) pMA;
    1358           0 :                     Bitmap                          aTmp( pA->GetBitmap() );
    1359             : 
    1360           0 :                     if( aTmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ) )
    1361           0 :                         WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aTmp );
    1362             :                 }
    1363           0 :                 break;
    1364             : 
    1365             :                 case META_BMPEX_ACTION:
    1366             :                 {
    1367           0 :                     const MetaBmpExAction*  pA = (const MetaBmpExAction *) pMA;
    1368           0 :                     Bitmap                  aBmp( pA->GetBitmapEx().GetBitmap() );
    1369           0 :                     Bitmap                  aMsk( pA->GetBitmapEx().GetMask() );
    1370             : 
    1371           0 :                     if( !!aMsk )
    1372             :                     {
    1373           0 :                         aBmp.Replace( aMsk, COL_WHITE );
    1374           0 :                         aMsk.Invert();
    1375           0 :                         WMFRecord_StretchDIB( pA->GetPoint(), aMsk.GetSizePixel(), aBmp, W_SRCPAINT );
    1376           0 :                         WMFRecord_StretchDIB( pA->GetPoint(), aBmp.GetSizePixel(), aBmp, W_SRCAND );
    1377             :                     }
    1378             :                     else
    1379           0 :                         WMFRecord_StretchDIB( pA->GetPoint(), aBmp.GetSizePixel(), aBmp );
    1380             :                 }
    1381           0 :                 break;
    1382             : 
    1383             :                 case META_BMPEXSCALE_ACTION:
    1384             :                 {
    1385           0 :                     const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pMA;
    1386           0 :                     Bitmap                      aBmp( pA->GetBitmapEx().GetBitmap() );
    1387           0 :                     Bitmap                      aMsk( pA->GetBitmapEx().GetMask() );
    1388             : 
    1389           0 :                     if( !!aMsk )
    1390             :                     {
    1391           0 :                         aBmp.Replace( aMsk, COL_WHITE );
    1392           0 :                         aMsk.Invert();
    1393           0 :                         WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aMsk, W_SRCPAINT );
    1394           0 :                         WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aBmp, W_SRCAND );
    1395             :                     }
    1396             :                     else
    1397           0 :                         WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aBmp );
    1398             :                 }
    1399           0 :                 break;
    1400             : 
    1401             :                 case META_BMPEXSCALEPART_ACTION:
    1402             :                 {
    1403           0 :                     const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pMA;
    1404           0 :                     BitmapEx                        aBmpEx( pA->GetBitmapEx() );
    1405           0 :                     aBmpEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
    1406           0 :                     Bitmap                          aBmp( aBmpEx.GetBitmap() );
    1407           0 :                     Bitmap                          aMsk( aBmpEx.GetMask() );
    1408             : 
    1409           0 :                     if( !!aMsk )
    1410             :                     {
    1411           0 :                         aBmp.Replace( aMsk, COL_WHITE );
    1412           0 :                         aMsk.Invert();
    1413           0 :                         WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aMsk, W_SRCPAINT );
    1414           0 :                         WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aBmp, W_SRCAND );
    1415             :                     }
    1416             :                     else
    1417           0 :                         WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aBmp );
    1418             :                 }
    1419           0 :                 break;
    1420             : 
    1421             :                 case META_GRADIENT_ACTION:
    1422             :                 {
    1423           0 :                     const MetaGradientAction*   pA = (const MetaGradientAction*) pMA;
    1424           0 :                     GDIMetaFile                 aTmpMtf;
    1425             : 
    1426           0 :                     pVirDev->AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
    1427           0 :                     WriteRecords( aTmpMtf );
    1428             :                 }
    1429           0 :                 break;
    1430             : 
    1431             :                 case META_HATCH_ACTION:
    1432             :                 {
    1433           0 :                     const MetaHatchAction*  pA = (const MetaHatchAction*) pMA;
    1434           0 :                     GDIMetaFile             aTmpMtf;
    1435             : 
    1436           0 :                     pVirDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
    1437           0 :                     WriteRecords( aTmpMtf );
    1438             :                 }
    1439           0 :                 break;
    1440             : 
    1441             :                 case META_WALLPAPER_ACTION:
    1442             :                 {
    1443           0 :                     const MetaWallpaperAction*  pA = (const MetaWallpaperAction*) pMA;
    1444           0 :                     const Color&                rColor = pA->GetWallpaper().GetColor();
    1445           0 :                     const Color                 aOldLineColor( aSrcLineColor );
    1446           0 :                     const Color                 aOldFillColor( aSrcFillColor );
    1447             : 
    1448           0 :                     aSrcLineColor = rColor;
    1449           0 :                     aSrcFillColor = rColor;
    1450           0 :                     aSrcLineInfo = LineInfo();
    1451           0 :                     SetLineAndFillAttr();
    1452           0 :                     WMFRecord_Rectangle( pA->GetRect() );
    1453           0 :                     aSrcLineColor = aOldLineColor;
    1454           0 :                     aSrcFillColor = aOldFillColor;
    1455             :                 }
    1456           0 :                 break;
    1457             : 
    1458             :                 case META_ISECTRECTCLIPREGION_ACTION:
    1459             :                 {
    1460          29 :                     const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pMA;
    1461          29 :                     WMFRecord_IntersectClipRect( pA->GetRect() );
    1462             :                 }
    1463          29 :                 break;
    1464             : 
    1465             :                 case META_LINECOLOR_ACTION:
    1466             :                 {
    1467          19 :                     const MetaLineColorAction* pA = (const MetaLineColorAction*) pMA;
    1468             : 
    1469          19 :                     if( pA->IsSetting() )
    1470           0 :                         aSrcLineColor = pA->GetColor();
    1471             :                     else
    1472          19 :                         aSrcLineColor = Color( COL_TRANSPARENT );
    1473             :                 }
    1474          19 :                 break;
    1475             : 
    1476             :                 case META_FILLCOLOR_ACTION:
    1477             :                 {
    1478          19 :                     const MetaFillColorAction* pA = (const MetaFillColorAction*) pMA;
    1479             : 
    1480          19 :                     if( pA->IsSetting() )
    1481          19 :                         aSrcFillColor = pA->GetColor();
    1482             :                     else
    1483           0 :                         aSrcFillColor = Color( COL_TRANSPARENT );
    1484             :                 }
    1485          19 :                 break;
    1486             : 
    1487             :                 case META_TEXTCOLOR_ACTION:
    1488             :                 {
    1489         353 :                     const MetaTextColorAction* pA = (const MetaTextColorAction*) pMA;
    1490         353 :                     aSrcTextColor = pA->GetColor();
    1491             :                 }
    1492         353 :                 break;
    1493             : 
    1494             :                 case META_TEXTFILLCOLOR_ACTION:
    1495             :                 {
    1496         350 :                     const MetaTextFillColorAction* pA = (const MetaTextFillColorAction*) pMA;
    1497         350 :                     if( pA->IsSetting() )
    1498           0 :                         aSrcFont.SetFillColor( pA->GetColor() );
    1499             :                     else
    1500         350 :                         aSrcFont.SetFillColor( Color( COL_TRANSPARENT ) );
    1501             :                 }
    1502         350 :                 break;
    1503             : 
    1504             :                 case META_TEXTALIGN_ACTION:
    1505             :                 {
    1506         350 :                     const MetaTextAlignAction* pA = (const MetaTextAlignAction*) pMA;
    1507         350 :                     eSrcTextAlign = pA->GetTextAlign();
    1508             :                 }
    1509         350 :                 break;
    1510             : 
    1511             :                 case META_MAPMODE_ACTION:
    1512             :                 {
    1513           0 :                     const MetaMapModeAction* pA = (const MetaMapModeAction*) pMA;
    1514             : 
    1515           0 :                     if (aSrcMapMode!=pA->GetMapMode())
    1516             :                     {
    1517           0 :                         if( pA->GetMapMode().GetMapUnit() == MAP_RELATIVE )
    1518             :                         {
    1519           0 :                             MapMode aMM = pA->GetMapMode();
    1520           0 :                             Fraction aScaleX = aMM.GetScaleX();
    1521           0 :                             Fraction aScaleY = aMM.GetScaleY();
    1522             : 
    1523           0 :                             Point aOrigin = aSrcMapMode.GetOrigin();
    1524           0 :                             BigInt aX( aOrigin.X() );
    1525           0 :                             aX *= BigInt( aScaleX.GetDenominator() );
    1526           0 :                             if( aOrigin.X() >= 0 )
    1527           0 :                                 if( aScaleX.GetNumerator() >= 0 )
    1528           0 :                                     aX += BigInt( aScaleX.GetNumerator()/2 );
    1529             :                                 else
    1530           0 :                                     aX -= BigInt( (aScaleX.GetNumerator()+1)/2 );
    1531             :                             else
    1532           0 :                                 if( aScaleX.GetNumerator() >= 0 )
    1533           0 :                                     aX -= BigInt( (aScaleX.GetNumerator()-1)/2 );
    1534             :                                 else
    1535           0 :                                     aX += BigInt( aScaleX.GetNumerator()/2 );
    1536           0 :                             aX /= BigInt( aScaleX.GetNumerator() );
    1537           0 :                             aOrigin.X() = (long)aX + aMM.GetOrigin().X();
    1538           0 :                             BigInt aY( aOrigin.Y() );
    1539           0 :                             aY *= BigInt( aScaleY.GetDenominator() );
    1540           0 :                             if( aOrigin.Y() >= 0 )
    1541           0 :                                 if( aScaleY.GetNumerator() >= 0 )
    1542           0 :                                     aY += BigInt( aScaleY.GetNumerator()/2 );
    1543             :                                 else
    1544           0 :                                     aY -= BigInt( (aScaleY.GetNumerator()+1)/2 );
    1545             :                             else
    1546           0 :                                 if( aScaleY.GetNumerator() >= 0 )
    1547           0 :                                     aY -= BigInt( (aScaleY.GetNumerator()-1)/2 );
    1548             :                                 else
    1549           0 :                                     aY += BigInt( aScaleY.GetNumerator()/2 );
    1550           0 :                             aY /= BigInt( aScaleY.GetNumerator() );
    1551           0 :                             aOrigin.Y() = (long)aY + aMM.GetOrigin().Y();
    1552           0 :                             aSrcMapMode.SetOrigin( aOrigin );
    1553             : 
    1554           0 :                             aScaleX *= aSrcMapMode.GetScaleX();
    1555           0 :                             aScaleY *= aSrcMapMode.GetScaleY();
    1556           0 :                             aSrcMapMode.SetScaleX( aScaleX );
    1557           0 :                             aSrcMapMode.SetScaleY( aScaleY );
    1558             :                         }
    1559             :                         else
    1560           0 :                             aSrcMapMode=pA->GetMapMode();
    1561             :                     }
    1562             :                 }
    1563           0 :                 break;
    1564             : 
    1565             :                 case META_FONT_ACTION:
    1566             :                 {
    1567         350 :                     const MetaFontAction* pA = (const MetaFontAction*) pMA;
    1568         350 :                     aSrcFont = pA->GetFont();
    1569             : 
    1570         487 :                     if ( (aSrcFont.GetCharSet() == RTL_TEXTENCODING_DONTKNOW)
    1571         137 :                          || (aSrcFont.GetCharSet() == RTL_TEXTENCODING_UNICODE) )
    1572             :                     {
    1573         350 :                         aSrcFont.SetCharSet( RTL_TEXTENCODING_MS_1252 );
    1574             :                     }
    1575         350 :                     eSrcTextAlign = aSrcFont.GetAlign();
    1576         350 :                     aSrcTextColor = aSrcFont.GetColor();
    1577         350 :                     aSrcFont.SetAlign( ALIGN_BASELINE );
    1578         350 :                     aSrcFont.SetColor( COL_WHITE );
    1579             :                 }
    1580         350 :                 break;
    1581             : 
    1582             :                 case META_PUSH_ACTION:
    1583             :                 {
    1584         379 :                     const MetaPushAction* pA = (const MetaPushAction*)pMA;
    1585             : 
    1586         379 :                     WMFWriterAttrStackMember* pAt = new WMFWriterAttrStackMember;
    1587         379 :                     pAt->nFlags = pA->GetFlags();
    1588         379 :                     pAt->aClipRegion = aSrcClipRegion;
    1589         379 :                     pAt->aLineColor=aSrcLineColor;
    1590         379 :                     pAt->aFillColor=aSrcFillColor;
    1591         379 :                     pAt->eRasterOp=eSrcRasterOp;
    1592         379 :                     pAt->aFont=aSrcFont;
    1593         379 :                     pAt->eTextAlign=eSrcTextAlign;
    1594         379 :                     pAt->aTextColor=aSrcTextColor;
    1595         379 :                     pAt->aMapMode=aSrcMapMode;
    1596         379 :                     pAt->aLineInfo=aDstLineInfo;
    1597         379 :                     pAt->pSucc=pAttrStack;
    1598         379 :                     pAttrStack=pAt;
    1599             : 
    1600         379 :                     SetAllAttr();           // update ( now all source attributes are equal to the destination attributes )
    1601         379 :                     WMFRecord_SaveDC();
    1602             : 
    1603             :                 }
    1604         379 :                 break;
    1605             : 
    1606             :                 case META_POP_ACTION:
    1607             :                 {
    1608         379 :                     WMFWriterAttrStackMember * pAt=pAttrStack;
    1609             : 
    1610         379 :                     if( pAt )
    1611             :                     {
    1612         379 :                         aDstLineInfo = pAt->aLineInfo;
    1613         379 :                         aDstLineColor = pAt->aLineColor;
    1614         379 :                         if ( pAt->nFlags & PUSH_LINECOLOR )
    1615         379 :                             aSrcLineColor = pAt->aLineColor;
    1616         379 :                         aDstFillColor = pAt->aFillColor;
    1617         379 :                         if ( pAt->nFlags & PUSH_FILLCOLOR )
    1618         379 :                             aSrcFillColor = pAt->aFillColor;
    1619         379 :                         eDstROP2 = pAt->eRasterOp;
    1620         379 :                         if ( pAt->nFlags & PUSH_RASTEROP )
    1621          29 :                             eSrcRasterOp = pAt->eRasterOp;
    1622         379 :                         aDstFont = pAt->aFont;
    1623         379 :                         if ( pAt->nFlags & PUSH_FONT )
    1624         379 :                             aSrcFont = pAt->aFont;
    1625         379 :                         eDstTextAlign = pAt->eTextAlign;
    1626         379 :                         if ( pAt->nFlags & ( PUSH_FONT | PUSH_TEXTALIGN ) )
    1627         379 :                             eSrcTextAlign = pAt->eTextAlign;
    1628         379 :                         aDstTextColor = pAt->aTextColor;
    1629         379 :                         if ( pAt->nFlags & ( PUSH_FONT | PUSH_TEXTCOLOR ) )
    1630         379 :                             aSrcTextColor = pAt->aTextColor;
    1631         379 :                         if ( pAt->nFlags & PUSH_MAPMODE )
    1632         379 :                             aSrcMapMode = pAt->aMapMode;
    1633         379 :                         aDstClipRegion = pAt->aClipRegion;
    1634         379 :                         if ( pAt->nFlags & PUSH_CLIPREGION )
    1635          29 :                             aSrcClipRegion = pAt->aClipRegion;
    1636             : 
    1637         379 :                         WMFRecord_RestoreDC();
    1638         379 :                         pAttrStack = pAt->pSucc;
    1639         379 :                         delete pAt;
    1640             :                     }
    1641             :                 }
    1642         379 :                 break;
    1643             : 
    1644             :                 case META_EPS_ACTION :
    1645             :                 {
    1646           0 :                     const MetaEPSAction* pA = (const MetaEPSAction*)pMA;
    1647           0 :                     const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
    1648             : 
    1649           0 :                     size_t nCount = aGDIMetaFile.GetActionSize();
    1650           0 :                     for ( size_t i = 0; i < nCount; i++ )
    1651             :                     {
    1652           0 :                         const MetaAction* pMetaAct = aGDIMetaFile.GetAction( i );
    1653           0 :                         if ( pMetaAct->GetType() == META_BMPSCALE_ACTION )
    1654             :                         {
    1655           0 :                             const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*)pMetaAct;
    1656           0 :                             WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), pBmpScaleAction->GetBitmap() );
    1657           0 :                             break;
    1658             :                         }
    1659           0 :                     }
    1660             :                 }
    1661           0 :                 break;
    1662             : 
    1663             :                 case META_RASTEROP_ACTION:
    1664             :                 {
    1665           0 :                     const MetaRasterOpAction* pA = (const MetaRasterOpAction*) pMA;
    1666           0 :                     eSrcRasterOp=pA->GetRasterOp();
    1667             :                 }
    1668           0 :                 break;
    1669             : 
    1670             :                 case META_TRANSPARENT_ACTION:
    1671             :                 {
    1672           0 :                     aSrcLineInfo = LineInfo();
    1673           0 :                     SetLineAndFillAttr();
    1674           0 :                     WMFRecord_PolyPolygon( ( (MetaTransparentAction*) pMA )->GetPolyPolygon() );
    1675             :                 }
    1676           0 :                 break;
    1677             : 
    1678             :                 case META_FLOATTRANSPARENT_ACTION:
    1679             :                 {
    1680           0 :                     const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pMA;
    1681             : 
    1682           0 :                     GDIMetaFile     aTmpMtf( pA->GetGDIMetaFile() );
    1683           0 :                     Point           aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
    1684           0 :                     const Size      aSrcSize( aTmpMtf.GetPrefSize() );
    1685           0 :                     const Point     aDestPt( pA->GetPoint() );
    1686           0 :                     const Size      aDestSize( pA->GetSize() );
    1687           0 :                     const double    fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
    1688           0 :                     const double    fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
    1689             :                     long            nMoveX, nMoveY;
    1690             : 
    1691           0 :                     aSrcLineInfo = LineInfo();
    1692           0 :                     SetAllAttr();
    1693             : 
    1694           0 :                     if( fScaleX != 1.0 || fScaleY != 1.0 )
    1695             :                     {
    1696           0 :                         aTmpMtf.Scale( fScaleX, fScaleY );
    1697           0 :                         aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
    1698             :                     }
    1699             : 
    1700           0 :                     nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
    1701             : 
    1702           0 :                     if( nMoveX || nMoveY )
    1703           0 :                         aTmpMtf.Move( nMoveX, nMoveY );
    1704             : 
    1705           0 :                     WriteRecords( aTmpMtf );
    1706             :                 }
    1707           0 :                 break;
    1708             : 
    1709             :                 case( META_LAYOUTMODE_ACTION ):
    1710             :                 {
    1711          58 :                     sal_uInt32 nLayoutMode = ( (MetaLayoutModeAction*) pMA )->GetLayoutMode();
    1712          58 :                     eSrcHorTextAlign = 0; // TA_LEFT
    1713          58 :                     if (nLayoutMode & TEXT_LAYOUT_BIDI_RTL)
    1714             :                     {
    1715           0 :                         eSrcHorTextAlign = W_TA_RIGHT | W_TA_RTLREADING;
    1716             :                     }
    1717          58 :                     if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_RIGHT)
    1718           0 :                         eSrcHorTextAlign |= W_TA_RIGHT;
    1719          58 :                     else if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_LEFT)
    1720           0 :                         eSrcHorTextAlign &= ~W_TA_RIGHT;
    1721          58 :                     break;
    1722             :                 }
    1723             : 
    1724             :                 // Unsupported Actions
    1725             :                 case META_MASK_ACTION:
    1726             :                 case META_MASKSCALE_ACTION:
    1727             :                 case META_MASKSCALEPART_ACTION:
    1728             :                 {
    1729             :                     OSL_FAIL( "Unsupported action: MetaMask...Action!" );
    1730             :                 }
    1731           0 :                 break;
    1732             : 
    1733             :                 case META_CLIPREGION_ACTION:
    1734           0 :                 break;
    1735             : 
    1736             :                 case META_ISECTREGIONCLIPREGION_ACTION:
    1737             :                 {
    1738             :                     OSL_FAIL( "Unsupported action: MetaISectRegionClipRegionAction!" );
    1739             :                 }
    1740           0 :                 break;
    1741             : 
    1742             :                 case META_MOVECLIPREGION_ACTION:
    1743             :                 {
    1744             :                     OSL_FAIL( "Unsupported action: MetaMoveClipRegionAction!" );
    1745             :                 }
    1746           0 :                 break;
    1747             : 
    1748             :                 default:
    1749             :                 {
    1750             :                     OSL_FAIL( "Unsupported meta action!" );
    1751             :                 }
    1752          87 :                 break;
    1753             :           }
    1754             : 
    1755        2723 :           nWrittenActions++;
    1756        2723 :           MayCallback();
    1757             : 
    1758        2723 :           if (pWMF->GetError())
    1759           0 :             bStatus=sal_False;
    1760             : 
    1761        2723 :           if(bStatus==sal_False)
    1762           0 :             break;
    1763             :         }
    1764             :     }
    1765          29 : }
    1766             : 
    1767             : // ------------------------------------------------------------------------
    1768             : 
    1769          29 : void WMFWriter::WriteHeader( const GDIMetaFile &, sal_Bool bPlaceable )
    1770             : {
    1771          29 :     if( bPlaceable )
    1772             :     {
    1773             :         sal_uInt16  nCheckSum, nValue;
    1774          29 :         Size    aSize( pVirDev->LogicToLogic(Size(1,1),MapMode(MAP_INCH), aTargetMapMode) );
    1775          29 :         sal_uInt16  nUnitsPerInch = (sal_uInt16) ( ( aSize.Width() + aSize.Height() ) >> 1 );
    1776             : 
    1777          29 :         nCheckSum=0;
    1778          29 :         nValue=0xcdd7;                              nCheckSum^=nValue; *pWMF << nValue;
    1779          29 :         nValue=0x9ac6;                              nCheckSum^=nValue; *pWMF << nValue;
    1780          29 :         nValue=0x0000;                              nCheckSum^=nValue; *pWMF << nValue;
    1781          29 :         nValue=0x0000;                              nCheckSum^=nValue; *pWMF << nValue;
    1782          29 :         nValue=0x0000;                              nCheckSum^=nValue; *pWMF << nValue;
    1783          29 :         nValue=(sal_uInt16) aTargetSize.Width();        nCheckSum^=nValue; *pWMF << nValue;
    1784          29 :         nValue=(sal_uInt16) aTargetSize.Height();       nCheckSum^=nValue; *pWMF << nValue;
    1785          29 :         nValue=nUnitsPerInch;                       nCheckSum^=nValue; *pWMF << nValue;
    1786          29 :         nValue=0x0000;                              nCheckSum^=nValue; *pWMF << nValue;
    1787          29 :         nValue=0x0000;                              nCheckSum^=nValue; *pWMF << nValue;
    1788          29 :         *pWMF << nCheckSum;
    1789             :     }
    1790             : 
    1791          29 :     nMetafileHeaderPos=pWMF->Tell();
    1792          29 :     *pWMF << (sal_uInt16)0x0001           // Typ: Datei
    1793          29 :           << (sal_uInt16)0x0009           // Headerlaenge in Worten
    1794          29 :           << (sal_uInt16)0x0300           // Version als BCD-Zahl
    1795          29 :           << (sal_uInt32) 0x00000000      // Dateilaenge (ohne 1. Header), wird spaeter durch UpdateHeader() berichtigt
    1796          29 :           << (sal_uInt16)MAXOBJECTHANDLES // Maximalezahl der gleichzeitigen Objekte
    1797          29 :           << (sal_uInt32) 0x00000000      // Maximale Record-laenge, wird spaeter durch UpdateHeader() berichtigt
    1798          29 :           << (sal_uInt16)0x0000;          // Reserved
    1799          29 : }
    1800             : 
    1801             : // ------------------------------------------------------------------------
    1802             : 
    1803          29 : void WMFWriter::UpdateHeader()
    1804             : {
    1805             :     sal_uLong nPos;
    1806             :     sal_uInt32 nFileSize;
    1807             : 
    1808          29 :     nPos=pWMF->Tell();                 // Endposition = Gesammtgroesse der Datei
    1809          29 :     nFileSize=nPos-nMetafileHeaderPos; // Groesse des 1. Headers abziehen
    1810          29 :     if ((nFileSize&1)!=0) {            // ggf. auf ganze Worte aufrunden
    1811           0 :         *pWMF << (sal_uInt8)0;
    1812           0 :         nPos++;
    1813           0 :         nFileSize++;
    1814             :     }
    1815          29 :     nFileSize>>=1;                    // In Anzahl Worte umrechnen
    1816          29 :     pWMF->Seek(nMetafileHeaderPos+6); // Zum Dateigroessen-Eintrag im zweiten Header
    1817          29 :     *pWMF << nFileSize;               // Dateigroesse berichtigen
    1818          29 :     pWMF->SeekRel(2);                 // Zum Max-Record-Laenge-Eintrag im zweiten Header
    1819          29 :     *pWMF << nMaxRecordSize;          // und berichtigen
    1820          29 :     pWMF->Seek(nPos);
    1821          29 : }
    1822             : 
    1823             : // ------------------------------------------------------------------------
    1824             : 
    1825          29 : sal_Bool WMFWriter::WriteWMF( const GDIMetaFile& rMTF, SvStream& rTargetStream,
    1826             :                             FilterConfigItem* pFConfigItem, sal_Bool bPlaceable )
    1827             : {
    1828             :     WMFWriterAttrStackMember * pAt;
    1829             : 
    1830          29 :     bEmbedEMF = sal_True;
    1831          29 :     bStatus=sal_True;
    1832          29 :     pConvert = 0;
    1833          29 :     pVirDev = new VirtualDevice;
    1834             : 
    1835          29 :     pFilterConfigItem = pFConfigItem;
    1836          29 :     if ( pFilterConfigItem )
    1837             :     {
    1838          29 :         xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
    1839          29 :         if ( xStatusIndicator.is() )
    1840             :         {
    1841           0 :             rtl::OUString aMsg;
    1842           0 :             xStatusIndicator->start( aMsg, 100 );
    1843             :         }
    1844             :     }
    1845          29 :     nLastPercent=0;
    1846             : 
    1847          29 :     pWMF=&rTargetStream;
    1848          29 :     pWMF->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
    1849             : 
    1850          29 :     nMaxRecordSize=0;
    1851             : 
    1852          29 :     aSrcMapMode=rMTF.GetPrefMapMode();
    1853             : 
    1854          29 :     if( bPlaceable )
    1855             :     {
    1856          29 :         aTargetMapMode = aSrcMapMode;
    1857          29 :         aTargetSize = rMTF.GetPrefSize();
    1858          29 :         nTargetDivisor = CalcSaveTargetMapMode(aTargetMapMode, aTargetSize);
    1859          29 :         aTargetSize.Width() /= nTargetDivisor;
    1860          29 :         aTargetSize.Height() /= nTargetDivisor;
    1861             :     }
    1862             :     else
    1863             :     {
    1864           0 :         aTargetMapMode = MapMode( MAP_INCH );
    1865             : 
    1866           0 :         const long      nUnit = pVirDev->LogicToPixel( Size( 1, 1 ), aTargetMapMode ).Width();
    1867           0 :         const Fraction  aFrac( 1, nUnit );
    1868             : 
    1869           0 :         aTargetMapMode.SetScaleX( aFrac );
    1870           0 :         aTargetMapMode.SetScaleY( aFrac );
    1871           0 :         aTargetSize = pVirDev->LogicToLogic( rMTF.GetPrefSize(), aSrcMapMode, aTargetMapMode );
    1872             :     }
    1873             : 
    1874          29 :     pVirDev->SetMapMode( aTargetMapMode );
    1875             : 
    1876          29 :     pAttrStack=NULL;
    1877             : 
    1878         493 :     for (sal_uInt16 i=0; i<MAXOBJECTHANDLES; i++)
    1879         464 :         bHandleAllocated[i]=sal_False;
    1880             : 
    1881          29 :     nDstPenHandle=0xffff;
    1882          29 :     nDstFontHandle=0xffff;
    1883          29 :     nDstBrushHandle=0xffff;
    1884             : 
    1885          29 :     nNumberOfActions=0;
    1886          29 :     nNumberOfBitmaps=0;
    1887          29 :     nWrittenActions=0;
    1888          29 :     nWrittenBitmaps=0;
    1889          29 :     nActBitmapPercent=0;
    1890             : 
    1891          29 :     CountActionsAndBitmaps(rMTF);
    1892             : 
    1893          29 :     WriteHeader(rMTF,bPlaceable);
    1894          29 :     if( bEmbedEMF )
    1895          29 :         WriteEmbeddedEMF( rMTF );
    1896          29 :     WMFRecord_SetWindowOrg(Point(0,0));
    1897          29 :     WMFRecord_SetWindowExt(rMTF.GetPrefSize());
    1898          29 :     WMFRecord_SetBkMode( sal_True );
    1899             : 
    1900          29 :     eDstROP2 = eSrcRasterOp = ROP_OVERPAINT;
    1901          29 :     WMFRecord_SetROP2(eDstROP2);
    1902             : 
    1903          29 :     aDstLineInfo = LineInfo();
    1904          29 :     aDstLineColor = aSrcLineColor = Color( COL_BLACK );
    1905          29 :     CreateSelectDeletePen( aDstLineColor, aDstLineInfo );
    1906             : 
    1907          29 :     aDstFillColor = aSrcFillColor = Color( COL_WHITE );
    1908          29 :     CreateSelectDeleteBrush( aDstFillColor );
    1909             : 
    1910          29 :     aDstClipRegion = aSrcClipRegion = Region();
    1911          29 :     bDstIsClipping = bSrcIsClipping = sal_False;
    1912             : 
    1913          29 :     Font aFont;
    1914          29 :     aFont.SetCharSet( GetExtendedTextEncoding( RTL_TEXTENCODING_MS_1252 ) );
    1915          29 :     aFont.SetColor( Color( COL_WHITE ) );
    1916          29 :     aFont.SetAlign( ALIGN_BASELINE );
    1917          29 :     aDstFont = aSrcFont = aFont;
    1918          29 :     CreateSelectDeleteFont(aDstFont);
    1919             : 
    1920          29 :     eDstTextAlign = eSrcTextAlign = ALIGN_BASELINE;
    1921          29 :     eDstHorTextAlign = eSrcHorTextAlign = W_TA_LEFT;
    1922          29 :     WMFRecord_SetTextAlign( eDstTextAlign, eDstHorTextAlign );
    1923             : 
    1924          29 :     aDstTextColor = aSrcTextColor = Color( COL_WHITE );
    1925          29 :     WMFRecord_SetTextColor(aDstTextColor);
    1926             : 
    1927             :     // Write records
    1928          29 :     WriteRecords(rMTF);
    1929             : 
    1930          29 :     WMFRecord_EndOfFile();
    1931          29 :     UpdateHeader();
    1932             : 
    1933          58 :     while(pAttrStack)
    1934             :     {
    1935           0 :         pAt=pAttrStack;
    1936           0 :         pAttrStack=pAt->pSucc;
    1937           0 :         delete pAt;
    1938             :     }
    1939             : 
    1940          29 :     delete pVirDev;
    1941          29 :     delete pConvert;
    1942             : 
    1943          29 :     if ( xStatusIndicator.is() )
    1944           0 :         xStatusIndicator->end();
    1945             : 
    1946          29 :     return bStatus;
    1947             : }
    1948             : 
    1949             : // ------------------------------------------------------------------------
    1950             : 
    1951          29 : sal_uInt16 WMFWriter::CalcSaveTargetMapMode(MapMode& rMapMode,
    1952             :                                         const Size& rPrefSize)
    1953             : {
    1954          29 :     Fraction    aDivFrac(2, 1);
    1955          29 :     sal_uInt16      nDivisor = 1;
    1956             : 
    1957          29 :     Size aSize = pVirDev->LogicToLogic( rPrefSize, aSrcMapMode, rMapMode );
    1958             : 
    1959          58 :     while( nDivisor <= 64 && (aSize.Width() > 32767 || aSize.Height() > 32767) )
    1960             :     {
    1961           0 :         Fraction aFrac = rMapMode.GetScaleX();
    1962             : 
    1963           0 :         aFrac *= aDivFrac;
    1964           0 :         rMapMode.SetScaleX(aFrac);
    1965           0 :         aFrac = rMapMode.GetScaleY();
    1966           0 :         aFrac *= aDivFrac;
    1967           0 :         rMapMode.SetScaleY(aFrac);
    1968           0 :         nDivisor <<= 1;
    1969           0 :         aSize = pVirDev->LogicToLogic( rPrefSize, aSrcMapMode, rMapMode );
    1970             :     }
    1971             : 
    1972          29 :     return nDivisor;
    1973             : }
    1974             : 
    1975             : // ------------------------------------------------------------------------
    1976             : 
    1977          29 : void WMFWriter::WriteEmbeddedEMF( const GDIMetaFile& rMTF )
    1978             : {
    1979          29 :     SvMemoryStream aStream;
    1980          29 :     EMFWriter aEMFWriter(aStream);
    1981             : 
    1982          29 :     if( aEMFWriter.WriteEMF( rMTF ) )
    1983             :     {
    1984          29 :         sal_Size nTotalSize = aStream.Tell();
    1985             :         if( nTotalSize > SAL_MAX_UINT32 )
    1986          29 :             return;
    1987          29 :         aStream.Seek( 0 );
    1988          29 :         sal_uInt32 nRemainingSize = static_cast< sal_uInt32 >( nTotalSize );
    1989          29 :         sal_uInt32 nRecCounts = ( (nTotalSize - 1) / 0x2000 ) + 1;
    1990          29 :         sal_uInt16 nCheckSum = 0, nWord;
    1991             : 
    1992          29 :         sal_uInt32 nPos = 0;
    1993             : 
    1994       91792 :         while( nPos + 1 < nTotalSize )
    1995             :         {
    1996       91734 :             aStream >> nWord;
    1997       91734 :             nCheckSum ^= nWord;
    1998       91734 :             nPos += 2;
    1999             :         }
    2000             : 
    2001          29 :         nCheckSum = static_cast< sal_uInt16 >( nCheckSum * -1 );
    2002             : 
    2003          29 :         aStream.Seek( 0 );
    2004          98 :         while( nRemainingSize > 0 )
    2005             :         {
    2006             :             sal_uInt32 nCurSize;
    2007          40 :             if( nRemainingSize > 0x2000 )
    2008             :             {
    2009          11 :                 nCurSize = 0x2000;
    2010          11 :                 nRemainingSize -= 0x2000;
    2011             :             }
    2012             :             else
    2013             :             {
    2014          29 :                 nCurSize = nRemainingSize;
    2015          29 :                 nRemainingSize = 0;
    2016             :             }
    2017             :             WriteEMFRecord( aStream,
    2018             :                             nCurSize,
    2019             :                             nRemainingSize,
    2020             :                             nTotalSize,
    2021             :                             nRecCounts,
    2022          40 :                             nCheckSum );
    2023          40 :             nCheckSum = 0;
    2024             :         }
    2025          29 :     }
    2026             : }
    2027             : 
    2028             : // ------------------------------------------------------------------------
    2029             : 
    2030          40 : void WMFWriter::WriteEMFRecord( SvMemoryStream& rStream, sal_uInt32 nCurSize, sal_uInt32 nRemainingSize,
    2031             :                 sal_uInt32 nTotalSize, sal_uInt32 nRecCounts, sal_uInt16 nCheckSum )
    2032             : {
    2033             :    // according to http://msdn.microsoft.com/en-us/library/dd366152%28PROT.13%29.aspx
    2034          40 :    WriteRecordHeader( 0, W_META_ESCAPE );
    2035          40 :    *pWMF << (sal_uInt16)W_MFCOMMENT         // same as META_ESCAPE_ENHANCED_METAFILE
    2036          80 :           << (sal_uInt16)( nCurSize + 34 )  // we will always have a 34 byte escape header:
    2037          40 :           << (sal_uInt32) 0x43464D57        // WMFC
    2038          40 :           << (sal_uInt32) 0x00000001        // Comment type
    2039          40 :           << (sal_uInt32) 0x00010000        // version
    2040          80 :           << nCheckSum                      // check sum
    2041          40 :           << (sal_uInt32) 0                 // flags = 0
    2042          40 :           << nRecCounts                     // total number of records
    2043          40 :           << nCurSize                       // size of this record's data
    2044          40 :           << nRemainingSize                 // remaining size of data in following records, missing in MSDN documentation
    2045          40 :           << nTotalSize;                    // total size of EMF stream
    2046             : 
    2047          40 :    pWMF->Write( static_cast< const sal_Char* >( rStream.GetData() ) + rStream.Tell(), nCurSize );
    2048          40 :    rStream.SeekRel( nCurSize );
    2049          40 :    UpdateRecordHeader();
    2050          40 : }
    2051             : 
    2052             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10