| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_svtools.hxx" |
| |
| #include "emfwr.hxx" |
| #include <vcl/salbtype.hxx> |
| #include <basegfx/polygon/b2dpolygon.hxx> |
| #include <basegfx/polygon/b2dpolypolygon.hxx> |
| #include <vcl/lineinfo.hxx> |
| #include <vcl/dibtools.hxx> |
| |
| // ----------- |
| // - Defines - |
| // ----------- |
| |
| #define WIN_EMR_HEADER 1 |
| #define WIN_EMR_POLYBEZIER 2 |
| #define WIN_EMR_POLYGON 3 |
| #define WIN_EMR_POLYLINE 4 |
| #define WIN_EMR_POLYBEZIERTO 5 |
| #define WIN_EMR_POLYLINETO 6 |
| #define WIN_EMR_POLYPOLYLINE 7 |
| #define WIN_EMR_POLYPOLYGON 8 |
| #define WIN_EMR_SETWINDOWEXTEX 9 |
| #define WIN_EMR_SETWINDOWORGEX 10 |
| #define WIN_EMR_SETVIEWPORTEXTEX 11 |
| #define WIN_EMR_SETVIEWPORTORGEX 12 |
| #define WIN_EMR_SETBRUSHORGEX 13 |
| #define WIN_EMR_EOF 14 |
| #define WIN_EMR_SETPIXELV 15 |
| #define WIN_EMR_SETMAPPERFLAGS 16 |
| #define WIN_EMR_SETMAPMODE 17 |
| #define WIN_EMR_SETBKMODE 18 |
| #define WIN_EMR_SETPOLYFILLMODE 19 |
| #define WIN_EMR_SETROP2 20 |
| #define WIN_EMR_SETSTRETCHBLTMODE 21 |
| #define WIN_EMR_SETTEXTALIGN 22 |
| #define WIN_EMR_SETCOLORADJUSTMENT 23 |
| #define WIN_EMR_SETTEXTCOLOR 24 |
| #define WIN_EMR_SETBKCOLOR 25 |
| #define WIN_EMR_OFFSETCLIPRGN 26 |
| #define WIN_EMR_MOVETOEX 27 |
| #define WIN_EMR_SETMETARGN 28 |
| #define WIN_EMR_EXCLUDECLIPRECT 29 |
| #define WIN_EMR_INTERSECTCLIPRECT 30 |
| #define WIN_EMR_SCALEVIEWPORTEXTEX 31 |
| #define WIN_EMR_SCALEWINDOWEXTEX 32 |
| #define WIN_EMR_SAVEDC 33 |
| #define WIN_EMR_RESTOREDC 34 |
| #define WIN_EMR_SETWORLDTRANSFORM 35 |
| #define WIN_EMR_MODIFYWORLDTRANSFORM 36 |
| #define WIN_EMR_SELECTOBJECT 37 |
| #define WIN_EMR_CREATEPEN 38 |
| #define WIN_EMR_CREATEBRUSHINDIRECT 39 |
| #define WIN_EMR_DELETEOBJECT 40 |
| #define WIN_EMR_ANGLEARC 41 |
| #define WIN_EMR_ELLIPSE 42 |
| #define WIN_EMR_RECTANGLE 43 |
| #define WIN_EMR_ROUNDRECT 44 |
| #define WIN_EMR_ARC 45 |
| #define WIN_EMR_CHORD 46 |
| #define WIN_EMR_PIE 47 |
| #define WIN_EMR_SELECTPALETTE 48 |
| #define WIN_EMR_CREATEPALETTE 49 |
| #define WIN_EMR_SETPALETTEENTRIES 50 |
| #define WIN_EMR_RESIZEPALETTE 51 |
| #define WIN_EMR_REALIZEPALETTE 52 |
| #define WIN_EMR_EXTFLOODFILL 53 |
| #define WIN_EMR_LINETO 54 |
| #define WIN_EMR_ARCTO 55 |
| #define WIN_EMR_POLYDRAW 56 |
| #define WIN_EMR_SETARCDIRECTION 57 |
| #define WIN_EMR_SETMITERLIMIT 58 |
| #define WIN_EMR_BEGINPATH 59 |
| #define WIN_EMR_ENDPATH 60 |
| #define WIN_EMR_CLOSEFIGURE 61 |
| #define WIN_EMR_FILLPATH 62 |
| #define WIN_EMR_STROKEANDFILLPATH 63 |
| #define WIN_EMR_STROKEPATH 64 |
| #define WIN_EMR_FLATTENPATH 65 |
| #define WIN_EMR_WIDENPATH 66 |
| #define WIN_EMR_SELECTCLIPPATH 67 |
| #define WIN_EMR_ABORTPATH 68 |
| |
| #define WIN_EMR_GDICOMMENT 70 |
| #define WIN_EMR_FILLRGN 71 |
| #define WIN_EMR_FRAMERGN 72 |
| #define WIN_EMR_INVERTRGN 73 |
| #define WIN_EMR_PAINTRGN 74 |
| #define WIN_EMR_EXTSELECTCLIPRGN 75 |
| #define WIN_EMR_BITBLT 76 |
| #define WIN_EMR_STRETCHBLT 77 |
| #define WIN_EMR_MASKBLT 78 |
| #define WIN_EMR_PLGBLT 79 |
| #define WIN_EMR_SETDIBITSTODEVICE 80 |
| #define WIN_EMR_STRETCHDIBITS 81 |
| #define WIN_EMR_EXTCREATEFONTINDIRECTW 82 |
| #define WIN_EMR_EXTTEXTOUTA 83 |
| #define WIN_EMR_EXTTEXTOUTW 84 |
| #define WIN_EMR_POLYBEZIER16 85 |
| #define WIN_EMR_POLYGON16 86 |
| #define WIN_EMR_POLYLINE16 87 |
| #define WIN_EMR_POLYBEZIERTO16 88 |
| #define WIN_EMR_POLYLINETO16 89 |
| #define WIN_EMR_POLYPOLYLINE16 90 |
| #define WIN_EMR_POLYPOLYGON16 91 |
| #define WIN_EMR_POLYDRAW16 92 |
| #define WIN_EMR_CREATEMONOBRUSH 93 |
| #define WIN_EMR_CREATEDIBPATTERNBRUSHPT 94 |
| #define WIN_EMR_EXTCREATEPEN 95 |
| #define WIN_EMR_POLYTEXTOUTA 96 |
| #define WIN_EMR_POLYTEXTOUTW 97 |
| |
| #define WIN_SRCCOPY 0x00CC0020L |
| #define WIN_SRCPAINT 0x00EE0086L |
| #define WIN_SRCAND 0x008800C6L |
| #define WIN_SRCINVERT 0x00660046L |
| |
| #define HANDLE_INVALID 0xffffffff |
| #define MAXHANDLES 65000 |
| |
| #define LINE_SELECT 0x00000001 |
| #define FILL_SELECT 0x00000002 |
| #define TEXT_SELECT 0x00000004 |
| |
| /* Text Alignment Options */ |
| #define TA_NOUPDATECP 0 |
| #define TA_UPDATECP 1 |
| |
| #define TA_LEFT 0 |
| #define TA_RIGHT 2 |
| #define TA_CENTER 6 |
| |
| #define TA_TOP 0 |
| #define TA_BOTTOM 8 |
| #define TA_BASELINE 24 |
| #define TA_RTLREADING 256 |
| #define TA_MASK (TA_BASELINE+TA_CENTER+TA_UPDATECP+TA_RTLREADING) |
| |
| #define MM_ANISOTROPIC 8 |
| |
| // ------------- |
| // - EMFWriter - |
| // ------------- |
| |
| sal_Bool EMFWriter::WriteEMF( const GDIMetaFile& rMtf, SvStream& rOStm, FilterConfigItem* pFilterConfigItem ) |
| { |
| const sal_uLong nHeaderPos = rOStm.Tell(); |
| |
| mpHandlesUsed = new sal_Bool[ MAXHANDLES ]; |
| memset( mpHandlesUsed, 0, MAXHANDLES * sizeof( sal_Bool ) ); |
| mnHorTextAlign = mnHandleCount = mnLastPercent = mnRecordPos = mnRecordCount = 0; |
| mnLineHandle = mnFillHandle = mnTextHandle = HANDLE_INVALID; |
| mbRecordOpen = sal_False; |
| |
| mpStm = &rOStm; |
| maVDev.EnableOutput( sal_False ); |
| maVDev.SetMapMode( rMtf.GetPrefMapMode() ); |
| mpFilterConfigItem = pFilterConfigItem; |
| |
| // don't work with pixel as destination map mode -> higher resolution preferrable |
| maDestMapMode.SetMapUnit( MAP_100TH_MM ); |
| |
| const Size aMtfSizePix( maVDev.LogicToPixel( rMtf.GetPrefSize(), rMtf.GetPrefMapMode() ) ); |
| const Size aMtfSizeLog( maVDev.LogicToLogic( rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MAP_100TH_MM ) ); |
| |
| // seek over header |
| // use [MS-EMF 2.2.11] HeaderExtension2 Object, otherwise resulting EMF cannot be converted with GetWinMetaFileBits() |
| rOStm.SeekRel( 108 ); |
| |
| // write initial values |
| |
| // set 100th mm map mode in EMF |
| ImplBeginRecord( WIN_EMR_SETMAPMODE ); |
| (*mpStm) << (sal_Int32) MM_ANISOTROPIC; |
| ImplEndRecord(); |
| |
| ImplBeginRecord( WIN_EMR_SETVIEWPORTEXTEX ); |
| (*mpStm) << (sal_Int32) maVDev.ImplGetDPIX() << (sal_Int32) maVDev.ImplGetDPIY(); |
| ImplEndRecord(); |
| |
| ImplBeginRecord( WIN_EMR_SETWINDOWEXTEX ); |
| (*mpStm) << (sal_Int32) 2540 << (sal_Int32) 2540; |
| ImplEndRecord(); |
| |
| ImplBeginRecord( WIN_EMR_SETVIEWPORTORGEX ); |
| (*mpStm) << (sal_Int32) 0 << (sal_Int32) 0; |
| ImplEndRecord(); |
| |
| ImplBeginRecord( WIN_EMR_SETWINDOWORGEX ); |
| (*mpStm) << (sal_Int32) 0 << (sal_Int32) 0; |
| ImplEndRecord(); |
| |
| ImplWriteRasterOp( ROP_OVERPAINT ); |
| |
| ImplBeginRecord( WIN_EMR_SETBKMODE ); |
| (*mpStm) << (sal_uInt32) 1; // TRANSPARENT |
| ImplEndRecord(); |
| |
| // write emf data |
| ImplWrite( rMtf ); |
| |
| ImplBeginRecord( WIN_EMR_EOF ); |
| (*mpStm)<< (sal_uInt32)0 // nPalEntries |
| << (sal_uInt32)0x10 // offPalEntries |
| << (sal_uInt32)0x14; // nSizeLast |
| ImplEndRecord(); |
| |
| |
| // write header |
| const sal_uLong nEndPos = mpStm->Tell(); mpStm->Seek( nHeaderPos ); |
| |
| (*mpStm) << (sal_uInt32) 0x00000001 << (sal_uInt32) 108 //use [MS-EMF 2.2.11] HeaderExtension2 Object |
| << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) ( aMtfSizePix.Width() - 1 ) << (sal_Int32) ( aMtfSizePix.Height() - 1 ) |
| << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) ( aMtfSizeLog.Width() - 1 ) << (sal_Int32) ( aMtfSizeLog.Height() - 1 ) |
| << (sal_uInt32) 0x464d4520 << (sal_uInt32) 0x10000 << (sal_uInt32) ( nEndPos - nHeaderPos ) |
| << (sal_uInt32) mnRecordCount << (sal_uInt16) ( mnHandleCount + 1 ) << (sal_uInt16) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 |
| << (sal_Int32) aMtfSizePix.Width() << (sal_Int32) aMtfSizePix.Height() |
| << (sal_Int32) ( aMtfSizeLog.Width() / 100 ) << (sal_Int32) ( aMtfSizeLog.Height() / 100 ) |
| << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 |
| << (sal_Int32) ( aMtfSizeLog.Width() * 10 ) << (sal_Int32) ( aMtfSizeLog.Height() * 10 ); //use [MS-EMF 2.2.11] HeaderExtension2 Object |
| |
| mpStm->Seek( nEndPos ); |
| delete[] mpHandlesUsed; |
| |
| return( mpStm->GetError() == ERRCODE_NONE ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| sal_uLong EMFWriter::ImplAcquireHandle() |
| { |
| sal_uLong nHandle = HANDLE_INVALID; |
| |
| for( sal_uLong i = 0; i < MAXHANDLES && ( HANDLE_INVALID == nHandle ); i++ ) |
| { |
| if( !mpHandlesUsed[ i ] ) |
| { |
| mpHandlesUsed[ i ] = sal_True; |
| |
| if( ( nHandle = i ) == mnHandleCount ) |
| mnHandleCount++; |
| } |
| } |
| |
| DBG_ASSERT( nHandle != HANDLE_INVALID, "No more handles available" ); |
| return( nHandle != HANDLE_INVALID ? nHandle + 1 : HANDLE_INVALID ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplReleaseHandle( sal_uLong nHandle ) |
| { |
| DBG_ASSERT( nHandle && ( nHandle < MAXHANDLES ), "Handle out of range" ); |
| mpHandlesUsed[ nHandle - 1 ] = sal_False; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplBeginRecord( sal_uInt32 nType ) |
| { |
| DBG_ASSERT( !mbRecordOpen, "Another record is already opened!" ); |
| |
| if( !mbRecordOpen ) |
| { |
| mbRecordOpen = sal_True; |
| mnRecordPos = mpStm->Tell(); |
| |
| (*mpStm) << nType; |
| mpStm->SeekRel( 4 ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplEndRecord() |
| { |
| DBG_ASSERT( mbRecordOpen, "Record was not opened!" ); |
| |
| if( mbRecordOpen ) |
| { |
| sal_Int32 nFillBytes, nActPos = mpStm->Tell(); |
| mpStm->Seek( mnRecordPos + 4 ); |
| nFillBytes = nActPos - mnRecordPos; |
| nFillBytes += 3; // each record has to be dword aligned |
| nFillBytes ^= 3; |
| nFillBytes &= 3; |
| *mpStm << (sal_uInt32)( ( nActPos - mnRecordPos ) + nFillBytes ); |
| mpStm->Seek( nActPos ); |
| while( nFillBytes-- ) |
| *mpStm << (sal_uInt8)0; |
| mnRecordCount++; |
| mbRecordOpen = sal_False; |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| sal_Bool EMFWriter::ImplPrepareHandleSelect( sal_uInt32& rHandle, sal_uLong nSelectType ) |
| { |
| if( rHandle != HANDLE_INVALID ) |
| { |
| sal_uInt32 nStockObject = 0x80000000; |
| |
| if( LINE_SELECT == nSelectType ) |
| nStockObject |= 0x00000007; |
| else if( FILL_SELECT == nSelectType ) |
| nStockObject |= 0x00000001; |
| else if( TEXT_SELECT == nSelectType ) |
| nStockObject |= 0x0000000a; |
| |
| // select stock object first |
| ImplBeginRecord( WIN_EMR_SELECTOBJECT ); |
| ( *mpStm ) << nStockObject; |
| ImplEndRecord(); |
| |
| // destroy handle of created object |
| ImplBeginRecord( WIN_EMR_DELETEOBJECT ); |
| ( *mpStm ) << rHandle; |
| ImplEndRecord(); |
| |
| // mark handle as free |
| ImplReleaseHandle( rHandle ); |
| } |
| |
| rHandle = ImplAcquireHandle(); |
| |
| return( HANDLE_INVALID != rHandle ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplCheckLineAttr() |
| { |
| if( mbLineChanged && ImplPrepareHandleSelect( mnLineHandle, LINE_SELECT ) ) |
| { |
| sal_uInt32 nStyle = maVDev.IsLineColor() ? 0 : 5; |
| sal_uInt32 nWidth = 0, nHeight = 0; |
| |
| ImplBeginRecord( WIN_EMR_CREATEPEN ); |
| (*mpStm) << mnLineHandle << nStyle << nWidth << nHeight; |
| ImplWriteColor( maVDev.GetLineColor() ); |
| ImplEndRecord(); |
| |
| ImplBeginRecord( WIN_EMR_SELECTOBJECT ); |
| (*mpStm) << mnLineHandle; |
| ImplEndRecord(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplCheckFillAttr() |
| { |
| if( mbFillChanged && ImplPrepareHandleSelect( mnFillHandle, FILL_SELECT ) ) |
| { |
| sal_uInt32 nStyle = maVDev.IsFillColor() ? 0 : 1; |
| sal_uInt32 nPatternStyle = 0; |
| |
| ImplBeginRecord( WIN_EMR_CREATEBRUSHINDIRECT ); |
| (*mpStm) << mnFillHandle << nStyle; |
| ImplWriteColor( maVDev.GetFillColor() ); |
| (*mpStm) << nPatternStyle; |
| ImplEndRecord(); |
| |
| ImplBeginRecord( WIN_EMR_SELECTOBJECT ); |
| (*mpStm) << mnFillHandle; |
| ImplEndRecord(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplCheckTextAttr() |
| { |
| if( mbTextChanged && ImplPrepareHandleSelect( mnTextHandle, TEXT_SELECT ) ) |
| { |
| const Font& rFont = maVDev.GetFont(); |
| String aFontName( rFont.GetName() ); |
| sal_Int32 nWeight; |
| sal_uInt16 i; |
| sal_uInt8 nPitchAndFamily; |
| |
| ImplBeginRecord( WIN_EMR_EXTCREATEFONTINDIRECTW ); |
| (*mpStm) << mnTextHandle; |
| ImplWriteExtent( -rFont.GetSize().Height() ); |
| ImplWriteExtent( rFont.GetSize().Width() ); |
| (*mpStm) << (sal_Int32) rFont.GetOrientation() << (sal_Int32) rFont.GetOrientation(); |
| |
| switch( rFont.GetWeight() ) |
| { |
| case WEIGHT_THIN: nWeight = 100; break; |
| case WEIGHT_ULTRALIGHT: nWeight = 200; break; |
| case WEIGHT_LIGHT: nWeight = 300; break; |
| case WEIGHT_SEMILIGHT: nWeight = 300; break; |
| case WEIGHT_NORMAL: nWeight = 400; break; |
| case WEIGHT_MEDIUM: nWeight = 500; break; |
| case WEIGHT_SEMIBOLD: nWeight = 600; break; |
| case WEIGHT_BOLD: nWeight = 700; break; |
| case WEIGHT_ULTRABOLD: nWeight = 800; break; |
| case WEIGHT_BLACK: nWeight = 900; break; |
| default: nWeight = 0; break; |
| } |
| |
| (*mpStm) << nWeight; |
| (*mpStm) << (sal_uInt8) ( ( ITALIC_NONE == rFont.GetItalic() ) ? 0 : 1 ); |
| (*mpStm) << (sal_uInt8) ( ( UNDERLINE_NONE == rFont.GetUnderline() ) ? 0 : 1 ); |
| (*mpStm) << (sal_uInt8) ( ( STRIKEOUT_NONE == rFont.GetStrikeout() ) ? 0 : 1 ); |
| (*mpStm) << (sal_uInt8) ( ( RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet() ) ? 2 : 0 ); |
| (*mpStm) << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0; |
| |
| switch( rFont.GetPitch() ) |
| { |
| case PITCH_FIXED: nPitchAndFamily = 0x01; break; |
| case PITCH_VARIABLE: nPitchAndFamily = 0x02; break; |
| default: nPitchAndFamily = 0x00; break; |
| } |
| |
| switch( rFont.GetFamily() ) |
| { |
| case FAMILY_DECORATIVE: nPitchAndFamily |= 0x50; break; |
| case FAMILY_MODERN: nPitchAndFamily |= 0x30; break; |
| case FAMILY_ROMAN: nPitchAndFamily |= 0x10; break; |
| case FAMILY_SCRIPT: nPitchAndFamily |= 0x40; break; |
| case FAMILY_SWISS: nPitchAndFamily |= 0x20; break; |
| default: break; |
| } |
| |
| (*mpStm) << nPitchAndFamily; |
| |
| for( i = 0; i < 32; i++ ) |
| (*mpStm) << (sal_Unicode) ( ( i < aFontName.Len() ) ? aFontName.GetChar( i ) : 0 ); |
| |
| // dummy elfFullName |
| for( i = 0; i < 64; i++ ) |
| (*mpStm) << (sal_Unicode) 0; |
| |
| // dummy elfStyle |
| for( i = 0; i < 32; i++ ) |
| (*mpStm) << (sal_Unicode) 0; |
| |
| // dummy elfVersion, elfStyleSize, elfMatch, elfReserved |
| (*mpStm) << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 ; |
| |
| // dummy elfVendorId |
| (*mpStm) << (sal_uInt32) 0; |
| |
| // dummy elfCulture |
| (*mpStm) << (sal_uInt32) 0; |
| |
| // dummy elfPanose |
| (*mpStm) << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0; |
| |
| // fill record to get a record size divideable by 4 |
| (*mpStm) << (sal_uInt16) 0; |
| |
| ImplEndRecord(); |
| |
| // TextAlign |
| sal_uInt32 nTextAlign; |
| |
| switch( rFont.GetAlign() ) |
| { |
| case ALIGN_TOP: nTextAlign = TA_TOP; break; |
| case ALIGN_BOTTOM: nTextAlign = TA_BOTTOM; break; |
| default: nTextAlign = TA_BASELINE; break; |
| } |
| nTextAlign |= mnHorTextAlign; |
| |
| ImplBeginRecord( WIN_EMR_SETTEXTALIGN ); |
| (*mpStm) << nTextAlign; |
| ImplEndRecord(); |
| |
| // Text color |
| ImplBeginRecord( WIN_EMR_SETTEXTCOLOR ); |
| ImplWriteColor( maVDev.GetTextColor() ); |
| ImplEndRecord(); |
| |
| ImplBeginRecord( WIN_EMR_SELECTOBJECT ); |
| (*mpStm) << mnTextHandle; |
| ImplEndRecord(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplWriteColor( const Color& rColor ) |
| { |
| sal_uInt32 nCol = rColor.GetRed(); |
| |
| nCol |= ( (sal_uInt32) rColor.GetGreen() ) << 8; |
| nCol |= ( (sal_uInt32) rColor.GetBlue() ) << 16; |
| |
| (*mpStm) << nCol; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplWriteRasterOp( RasterOp eRop ) |
| { |
| sal_uInt32 nROP2; |
| |
| switch( eRop ) |
| { |
| case ROP_INVERT: nROP2 = 6; break; |
| case ROP_XOR: nROP2 = 7; break; |
| default: nROP2 = 13;break; |
| } |
| |
| ImplBeginRecord( WIN_EMR_SETROP2 ); |
| (*mpStm) << nROP2; |
| ImplEndRecord(); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplWriteExtent( long nExtent ) |
| { |
| nExtent = maVDev.LogicToLogic( Size( nExtent, 0 ), maVDev.GetMapMode(), maDestMapMode ).Width(); |
| (*mpStm) << (sal_Int32) nExtent; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplWritePoint( const Point& rPoint ) |
| { |
| const Point aPoint( maVDev.LogicToLogic( rPoint, maVDev.GetMapMode(), maDestMapMode )); |
| (*mpStm) << (sal_Int32) aPoint.X() << (sal_Int32) aPoint.Y(); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplWriteSize( const Size& rSize) |
| { |
| const Size aSize( maVDev.LogicToLogic( rSize, maVDev.GetMapMode(), maDestMapMode )); |
| (*mpStm) << (sal_Int32) aSize.Width() << (sal_Int32) aSize.Height(); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplWriteRect( const Rectangle& rRect ) |
| { |
| const Rectangle aRect( maVDev.LogicToLogic ( rRect, maVDev.GetMapMode(), maDestMapMode )); |
| (*mpStm) << aRect.Left() << aRect.Top() << aRect.Right() << aRect.Bottom(); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplWritePolygonRecord( const Polygon& rPoly, sal_Bool bClose ) |
| { |
| if( rPoly.GetSize() ) |
| { |
| if( rPoly.HasFlags() ) |
| ImplWritePath( rPoly, bClose ); |
| else |
| { |
| if( bClose ) |
| ImplCheckFillAttr(); |
| |
| ImplCheckLineAttr(); |
| |
| ImplBeginRecord( bClose ? WIN_EMR_POLYGON : WIN_EMR_POLYLINE ); |
| ImplWriteRect( rPoly.GetBoundRect() ); |
| (*mpStm) << (sal_uInt32) rPoly.GetSize(); |
| |
| for( sal_uInt16 i = 0; i < rPoly.GetSize(); i++ ) |
| ImplWritePoint( rPoly[ i ] ); |
| |
| ImplEndRecord(); |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplWritePolyPolygonRecord( const PolyPolygon& rPolyPoly ) |
| { |
| sal_uInt16 n, i, nPolyCount = rPolyPoly.Count(); |
| |
| if( nPolyCount ) |
| { |
| if( 1 == nPolyCount ) |
| ImplWritePolygonRecord( rPolyPoly[ 0 ], sal_True ); |
| else |
| { |
| sal_Bool bHasFlags = sal_False; |
| sal_uInt32 nTotalPoints = 0; |
| |
| for( i = 0; i < nPolyCount; i++ ) |
| { |
| nTotalPoints += rPolyPoly[ i ].GetSize(); |
| if ( rPolyPoly[ i ].HasFlags() ) |
| bHasFlags = sal_True; |
| } |
| if( nTotalPoints ) |
| { |
| if ( bHasFlags ) |
| ImplWritePath( rPolyPoly, sal_True ); |
| else |
| { |
| ImplCheckFillAttr(); |
| ImplCheckLineAttr(); |
| |
| ImplBeginRecord( WIN_EMR_POLYPOLYGON ); |
| ImplWriteRect( rPolyPoly.GetBoundRect() ); |
| (*mpStm) << (sal_uInt32)nPolyCount << nTotalPoints; |
| |
| for( i = 0; i < nPolyCount; i++ ) |
| (*mpStm) << (sal_uInt32)rPolyPoly[ i ].GetSize(); |
| |
| for( i = 0; i < nPolyCount; i++ ) |
| { |
| const Polygon& rPoly = rPolyPoly[ i ]; |
| |
| for( n = 0; n < rPoly.GetSize(); n++ ) |
| ImplWritePoint( rPoly[ n ] ); |
| } |
| ImplEndRecord(); |
| } |
| } |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplWritePath( const PolyPolygon& rPolyPoly, sal_Bool bClosed ) |
| { |
| if ( bClosed ) |
| ImplCheckFillAttr(); |
| ImplCheckLineAttr(); |
| |
| ImplBeginRecord( WIN_EMR_BEGINPATH ); |
| ImplEndRecord(); |
| |
| sal_uInt16 i, n, o, nPolyCount = rPolyPoly.Count(); |
| for ( i = 0; i < nPolyCount; i++ ) |
| { |
| n = 0; |
| const Polygon& rPoly = rPolyPoly[ i ]; |
| while ( n < rPoly.GetSize() ) |
| { |
| if( n == 0 ) |
| { |
| ImplBeginRecord( WIN_EMR_MOVETOEX ); |
| ImplWritePoint( rPoly[ 0 ] ); |
| ImplEndRecord(); |
| n++; |
| continue; |
| } |
| |
| sal_uInt16 nBezPoints = 0; |
| |
| while ( ( ( nBezPoints + n + 2 ) < rPoly.GetSize() ) && ( rPoly.GetFlags( nBezPoints + n ) == POLY_CONTROL ) ) |
| nBezPoints += 3; |
| |
| if ( nBezPoints ) |
| { |
| ImplBeginRecord( WIN_EMR_POLYBEZIERTO ); |
| Polygon aNewPoly( nBezPoints + 1 ); |
| aNewPoly[ 0 ] = rPoly[ n - 1 ]; |
| for ( o = 0; o < nBezPoints; o++ ) |
| aNewPoly[ o + 1 ] = rPoly[ n + o ]; |
| ImplWriteRect( aNewPoly.GetBoundRect() ); |
| (*mpStm) << (sal_uInt32)nBezPoints; |
| for( o = 1; o < aNewPoly.GetSize(); o++ ) |
| ImplWritePoint( aNewPoly[ o ] ); |
| ImplEndRecord(); |
| n = n + nBezPoints; |
| } |
| else |
| { |
| sal_uInt16 nPoints = 1; |
| while( ( nPoints + n ) < rPoly.GetSize() && ( rPoly.GetFlags( nPoints + n ) != POLY_CONTROL ) ) |
| nPoints++; |
| |
| if ( nPoints > 1 ) |
| { |
| ImplBeginRecord( WIN_EMR_POLYLINETO ); |
| Polygon aNewPoly( nPoints + 1 ); |
| aNewPoly[ 0 ] = rPoly[ n - 1]; |
| for ( o = 1; o <= nPoints; o++ ) |
| aNewPoly[ o ] = rPoly[ n - 1 + o ]; |
| ImplWriteRect( aNewPoly.GetBoundRect() ); |
| (*mpStm) << (sal_uInt32)( nPoints ); |
| for( o = 1; o < aNewPoly.GetSize(); o++ ) |
| ImplWritePoint( aNewPoly[ o ] ); |
| ImplEndRecord(); |
| } |
| else |
| { |
| ImplBeginRecord( WIN_EMR_LINETO ); |
| ImplWritePoint( rPoly[ n ] ); |
| ImplEndRecord(); |
| } |
| n = n + nPoints; |
| } |
| if ( bClosed && ( n == rPoly.GetSize() ) ) |
| { |
| ImplBeginRecord( WIN_EMR_CLOSEFIGURE ); |
| ImplEndRecord(); |
| } |
| } |
| } |
| ImplBeginRecord( WIN_EMR_ENDPATH ); |
| ImplEndRecord(); |
| ImplBeginRecord( bClosed ? WIN_EMR_FILLPATH : WIN_EMR_STROKEPATH ); |
| ImplWriteRect( rPolyPoly.GetBoundRect() ); |
| ImplEndRecord(); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplWriteBmpRecord( const Bitmap& rBmp, const Point& rPt, |
| const Size& rSz, sal_uInt32 nROP ) |
| { |
| if( !!rBmp ) |
| { |
| SvMemoryStream aMemStm( 65535, 65535 ); |
| const Size aBmpSizePixel( rBmp.GetSizePixel() ); |
| |
| ImplBeginRecord( WIN_EMR_STRETCHDIBITS ); |
| ImplWriteRect( Rectangle( rPt, rSz ) ); |
| ImplWritePoint( rPt ); |
| (*mpStm) << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) aBmpSizePixel.Width() << (sal_Int32) aBmpSizePixel.Height(); |
| |
| // write offset positions and sizes later |
| const sal_uLong nOffPos = mpStm->Tell(); |
| mpStm->SeekRel( 16 ); |
| |
| (*mpStm) << (sal_uInt32) 0 << ( ( ROP_XOR == maVDev.GetRasterOp() && WIN_SRCCOPY == nROP ) ? WIN_SRCINVERT : nROP ); |
| ImplWriteSize( rSz ); |
| |
| WriteDIB(rBmp, aMemStm, true, false); |
| |
| sal_uInt32 nDIBSize = aMemStm.Tell(), nHeaderSize, nCompression, nColsUsed, nPalCount, nImageSize; |
| sal_uInt16 nBitCount; |
| |
| // get DIB parameters |
| aMemStm.Seek( 0 ); |
| aMemStm >> nHeaderSize; |
| aMemStm.SeekRel( 10 ); |
| aMemStm >> nBitCount >> nCompression >> nImageSize; |
| aMemStm.SeekRel( 8 ); |
| aMemStm >> nColsUsed; |
| |
| nPalCount = ( nBitCount <= 8 ) ? ( nColsUsed ? nColsUsed : ( 1 << (sal_uInt32) nBitCount ) ) : |
| ( ( 3 == nCompression ) ? 12 : 0 ); |
| |
| mpStm->Write( aMemStm.GetData(), nDIBSize ); |
| |
| const sal_uLong nEndPos = mpStm->Tell(); |
| mpStm->Seek( nOffPos ); |
| (*mpStm) << (sal_uInt32) 80 << (sal_uInt32)( nHeaderSize + ( nPalCount << 2 ) ); |
| (*mpStm) << (sal_uInt32)( 80 + ( nHeaderSize + ( nPalCount << 2 ) ) ) << nImageSize; |
| mpStm->Seek( nEndPos ); |
| |
| ImplEndRecord(); |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplWriteTextRecord( const Point& rPos, const String rText, const sal_Int32* pDXArray, sal_uInt32 nWidth ) |
| { |
| xub_StrLen nLen = rText.Len(), i; |
| |
| if( nLen ) |
| { |
| sal_uInt32 nNormWidth; |
| sal_Int32* pOwnArray; |
| sal_Int32* pDX; |
| |
| // get text sizes |
| if( pDXArray ) |
| { |
| pOwnArray = NULL; |
| nNormWidth = maVDev.GetTextWidth( rText ); |
| pDX = (sal_Int32*) pDXArray; |
| } |
| else |
| { |
| pOwnArray = new sal_Int32[ nLen ]; |
| nNormWidth = maVDev.GetTextArray( rText, pOwnArray ); |
| pDX = pOwnArray; |
| } |
| |
| if( nLen > 1 ) |
| { |
| nNormWidth = pDX[ nLen - 2 ] + maVDev.GetTextWidth( rText.GetChar( nLen - 1 ) ); |
| |
| if( nWidth && nNormWidth && ( nWidth != nNormWidth ) ) |
| { |
| const double fFactor = (double) nWidth / nNormWidth; |
| |
| for( i = 0; i < ( nLen - 1 ); i++ ) |
| pDX[ i ] = FRound( pDX[ i ] * fFactor ); |
| } |
| } |
| |
| // write text record |
| ImplBeginRecord( WIN_EMR_EXTTEXTOUTW ); |
| |
| ImplWriteRect( Rectangle( rPos, Size( nNormWidth, maVDev.GetTextHeight() ) ) ); |
| (*mpStm) << (sal_uInt32)1; |
| (*mpStm) << (sal_Int32) 0 << (sal_Int32) 0; |
| ImplWritePoint( rPos ); |
| (*mpStm) << (sal_uInt32) nLen << (sal_uInt32) 76 << (sal_uInt32) 2; |
| (*mpStm) << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) 0; |
| (*mpStm) << (sal_uInt32) ( 76 + ( nLen << 1 ) + ( (nLen & 1 ) ? 2 : 0 ) ); |
| |
| // write text |
| for( i = 0; i < nLen; i++ ) |
| (*mpStm) << (sal_Unicode)rText.GetChar( i ); |
| |
| // padding word |
| if( nLen & 1 ) |
| (*mpStm) << (sal_uInt16) 0; |
| |
| // write DX array |
| ImplWriteExtent( pDX[ 0 ] ); |
| |
| if( nLen > 1 ) |
| { |
| for( i = 1; i < ( nLen - 1 ); i++ ) |
| ImplWriteExtent( pDX[ i ] - pDX[ i - 1 ] ); |
| |
| ImplWriteExtent( pDX[ nLen - 2 ] / ( nLen - 1 ) ); |
| } |
| |
| ImplEndRecord(); |
| delete[] pOwnArray; |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::Impl_handleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon) |
| { |
| if(rLinePolygon.count()) |
| { |
| basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon); |
| basegfx::B2DPolyPolygon aFillPolyPolygon; |
| |
| rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon); |
| |
| if(aLinePolyPolygon.count()) |
| { |
| for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++) |
| { |
| const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a)); |
| ImplWritePolygonRecord( Polygon(aCandidate), sal_False ); |
| } |
| } |
| |
| if(aFillPolyPolygon.count()) |
| { |
| const Color aOldLineColor(maVDev.GetLineColor()); |
| const Color aOldFillColor(maVDev.GetFillColor()); |
| |
| maVDev.SetLineColor(); |
| maVDev.SetFillColor(aOldLineColor); |
| |
| for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++) |
| { |
| const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a)); |
| ImplWritePolyPolygonRecord(PolyPolygon(Polygon(aPolygon))); |
| } |
| |
| maVDev.SetLineColor(aOldLineColor); |
| maVDev.SetFillColor(aOldFillColor); |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void EMFWriter::ImplWrite( const GDIMetaFile& rMtf ) |
| { |
| for( sal_uLong j = 0, nActionCount = rMtf.GetActionCount(); j < nActionCount; j++ ) |
| { |
| const MetaAction* pAction = rMtf.GetAction( j ); |
| const sal_uInt16 nType = pAction->GetType(); |
| |
| switch( nType ) |
| { |
| case( META_PIXEL_ACTION ): |
| { |
| const MetaPixelAction* pA = (const MetaPixelAction*) pAction; |
| |
| ImplCheckLineAttr(); |
| ImplBeginRecord( WIN_EMR_SETPIXELV ); |
| ImplWritePoint( pA->GetPoint() ); |
| ImplWriteColor( pA->GetColor() ); |
| ImplEndRecord(); |
| } |
| break; |
| |
| case( META_POINT_ACTION ): |
| { |
| if( maVDev.IsLineColor() ) |
| { |
| const MetaPointAction* pA = (const MetaPointAction*) pAction; |
| |
| ImplCheckLineAttr(); |
| ImplBeginRecord( WIN_EMR_SETPIXELV ); |
| ImplWritePoint( pA->GetPoint() ); |
| ImplWriteColor( maVDev.GetLineColor() ); |
| ImplEndRecord(); |
| } |
| } |
| break; |
| |
| case( META_LINE_ACTION ): |
| { |
| if( maVDev.IsLineColor() ) |
| { |
| const MetaLineAction* pA = (const MetaLineAction*) pAction; |
| |
| if(pA->GetLineInfo().IsDefault()) |
| { |
| ImplCheckLineAttr(); |
| |
| ImplBeginRecord( WIN_EMR_MOVETOEX ); |
| ImplWritePoint( pA->GetStartPoint() ); |
| ImplEndRecord(); |
| |
| ImplBeginRecord( WIN_EMR_LINETO ); |
| ImplWritePoint( pA->GetEndPoint() ); |
| ImplEndRecord(); |
| |
| ImplBeginRecord( WIN_EMR_SETPIXELV ); |
| ImplWritePoint( pA->GetEndPoint() ); |
| ImplWriteColor( maVDev.GetLineColor() ); |
| ImplEndRecord(); |
| } |
| else |
| { |
| // LineInfo used; handle Dash/Dot and fat lines |
| basegfx::B2DPolygon aPolygon; |
| aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y())); |
| aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y())); |
| Impl_handleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon); |
| } |
| } |
| } |
| break; |
| |
| case( META_RECT_ACTION ): |
| { |
| if( maVDev.IsLineColor() || maVDev.IsFillColor() ) |
| { |
| const MetaRectAction* pA = (const MetaRectAction*) pAction; |
| |
| ImplCheckFillAttr(); |
| ImplCheckLineAttr(); |
| |
| ImplBeginRecord( WIN_EMR_RECTANGLE ); |
| ImplWriteRect( pA->GetRect() ); |
| ImplEndRecord(); |
| } |
| } |
| break; |
| |
| case( META_ROUNDRECT_ACTION ): |
| { |
| if( maVDev.IsLineColor() || maVDev.IsFillColor() ) |
| { |
| const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pAction; |
| |
| ImplCheckFillAttr(); |
| ImplCheckLineAttr(); |
| |
| ImplBeginRecord( WIN_EMR_ROUNDRECT ); |
| ImplWriteRect( pA->GetRect() ); |
| ImplWriteSize( Size( pA->GetHorzRound(), pA->GetVertRound() ) ); |
| ImplEndRecord(); |
| } |
| } |
| break; |
| |
| case( META_ELLIPSE_ACTION ): |
| { |
| if( maVDev.IsLineColor() || maVDev.IsFillColor() ) |
| { |
| const MetaEllipseAction* pA = (const MetaEllipseAction*) pAction; |
| |
| ImplCheckFillAttr(); |
| ImplCheckLineAttr(); |
| |
| ImplBeginRecord( WIN_EMR_ELLIPSE ); |
| ImplWriteRect( pA->GetRect() ); |
| ImplEndRecord(); |
| } |
| } |
| break; |
| |
| case( META_ARC_ACTION ): |
| case( META_PIE_ACTION ): |
| case( META_CHORD_ACTION ): |
| case( META_POLYGON_ACTION ): |
| { |
| if( maVDev.IsLineColor() || maVDev.IsFillColor() ) |
| { |
| Polygon aPoly; |
| |
| switch( nType ) |
| { |
| case( META_ARC_ACTION ): |
| { |
| const MetaArcAction* pA = (const MetaArcAction*) pAction; |
| aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_ARC ); |
| } |
| break; |
| |
| case( META_PIE_ACTION ): |
| { |
| const MetaPieAction* pA = (const MetaPieAction*) pAction; |
| aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_PIE ); |
| } |
| break; |
| |
| case( META_CHORD_ACTION ): |
| { |
| const MetaChordAction* pA = (const MetaChordAction*) pAction; |
| aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_CHORD ); |
| } |
| break; |
| |
| case( META_POLYGON_ACTION ): |
| aPoly = ( (const MetaPolygonAction*) pAction )->GetPolygon(); |
| break; |
| } |
| |
| ImplWritePolygonRecord( aPoly, nType != META_ARC_ACTION ); |
| } |
| } |
| break; |
| |
| case( META_POLYLINE_ACTION ): |
| { |
| if( maVDev.IsLineColor() ) |
| { |
| const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pAction; |
| const Polygon& rPoly = pA->GetPolygon(); |
| |
| if( rPoly.GetSize() ) |
| { |
| if(pA->GetLineInfo().IsDefault()) |
| { |
| ImplWritePolygonRecord( rPoly, sal_False ); |
| } |
| else |
| { |
| // LineInfo used; handle Dash/Dot and fat lines |
| Impl_handleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon()); |
| } |
| } |
| } |
| } |
| break; |
| |
| case( META_POLYPOLYGON_ACTION ): |
| { |
| if( maVDev.IsLineColor() || maVDev.IsFillColor() ) |
| ImplWritePolyPolygonRecord( ( (const MetaPolyPolygonAction*) pAction )->GetPolyPolygon() ); |
| } |
| break; |
| |
| case( META_GRADIENT_ACTION ): |
| { |
| const MetaGradientAction* pA = (const MetaGradientAction*) pAction; |
| GDIMetaFile aTmpMtf; |
| |
| maVDev.AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf ); |
| ImplWrite( aTmpMtf ); |
| } |
| break; |
| |
| case META_HATCH_ACTION: |
| { |
| const MetaHatchAction* pA = (const MetaHatchAction*) pAction; |
| GDIMetaFile aTmpMtf; |
| |
| maVDev.AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf ); |
| ImplWrite( aTmpMtf ); |
| } |
| break; |
| |
| case META_TRANSPARENT_ACTION: |
| { |
| ImplCheckFillAttr(); |
| ImplCheckLineAttr(); |
| ImplWritePolyPolygonRecord( ( (MetaTransparentAction*) pAction )->GetPolyPolygon() ); |
| } |
| break; |
| |
| case META_FLOATTRANSPARENT_ACTION: |
| { |
| const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pAction; |
| |
| GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() ); |
| Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() ); |
| const Size aSrcSize( aTmpMtf.GetPrefSize() ); |
| const Point aDestPt( pA->GetPoint() ); |
| const Size aDestSize( pA->GetSize() ); |
| const double fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0; |
| const double fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0; |
| long nMoveX, nMoveY; |
| |
| if( fScaleX != 1.0 || fScaleY != 1.0 ) |
| { |
| aTmpMtf.Scale( fScaleX, fScaleY ); |
| aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY ); |
| } |
| |
| nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y(); |
| |
| if( nMoveX || nMoveY ) |
| aTmpMtf.Move( nMoveX, nMoveY ); |
| |
| ImplCheckFillAttr(); |
| ImplCheckLineAttr(); |
| ImplCheckTextAttr(); |
| ImplWrite( aTmpMtf ); |
| } |
| break; |
| |
| case( META_EPS_ACTION ): |
| { |
| const MetaEPSAction* pA = (const MetaEPSAction*) pAction; |
| const GDIMetaFile aSubstitute( pA->GetSubstitute() ); |
| |
| for( sal_uLong i = 0, nCount = aSubstitute.GetActionCount(); i < nCount; i++ ) |
| { |
| const MetaAction* pSubstAct = aSubstitute.GetAction( i ); |
| if( pSubstAct->GetType() == META_BMPSCALE_ACTION ) |
| { |
| maVDev.Push( PUSH_ALL ); |
| ImplBeginRecord( WIN_EMR_SAVEDC ); |
| ImplEndRecord(); |
| |
| MapMode aMapMode( aSubstitute.GetPrefMapMode() ); |
| Size aOutSize( maVDev.LogicToLogic( pA->GetSize(), maVDev.GetMapMode(), aMapMode ) ); |
| aMapMode.SetScaleX( Fraction( aOutSize.Width(), aSubstitute.GetPrefSize().Width() ) ); |
| aMapMode.SetScaleY( Fraction( aOutSize.Height(), aSubstitute.GetPrefSize().Height() ) ); |
| aMapMode.SetOrigin( maVDev.LogicToLogic( pA->GetPoint(), maVDev.GetMapMode(), aMapMode ) ); |
| maVDev.SetMapMode( aMapMode ); |
| ImplWrite( aSubstitute ); |
| |
| maVDev.Pop(); |
| ImplBeginRecord( WIN_EMR_RESTOREDC ); |
| (*mpStm) << (sal_Int32) -1; |
| ImplEndRecord(); |
| break; |
| } |
| } |
| } |
| break; |
| |
| case META_BMP_ACTION: |
| { |
| const MetaBmpAction* pA = (const MetaBmpAction *) pAction; |
| ImplWriteBmpRecord( pA->GetBitmap(), pA->GetPoint(), maVDev.PixelToLogic( pA->GetBitmap().GetSizePixel() ), WIN_SRCCOPY ); |
| } |
| break; |
| |
| case META_BMPSCALE_ACTION: |
| { |
| const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction; |
| ImplWriteBmpRecord( pA->GetBitmap(), pA->GetPoint(), pA->GetSize(), WIN_SRCCOPY ); |
| } |
| break; |
| |
| case META_BMPSCALEPART_ACTION: |
| { |
| const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pAction; |
| Bitmap aTmp( pA->GetBitmap() ); |
| |
| if( aTmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ) ) |
| ImplWriteBmpRecord( aTmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCCOPY ); |
| } |
| break; |
| |
| case META_BMPEX_ACTION: |
| { |
| const MetaBmpExAction* pA = (const MetaBmpExAction *) pAction; |
| Bitmap aBmp( pA->GetBitmapEx().GetBitmap() ); |
| Bitmap aMsk( pA->GetBitmapEx().GetMask() ); |
| |
| if( !!aMsk ) |
| { |
| aBmp.Replace( aMsk, COL_WHITE ); |
| aMsk.Invert(); |
| ImplWriteBmpRecord( aMsk, pA->GetPoint(), maVDev.PixelToLogic( aMsk.GetSizePixel() ), WIN_SRCPAINT ); |
| ImplWriteBmpRecord( aBmp, pA->GetPoint(), maVDev.PixelToLogic( aBmp.GetSizePixel() ), WIN_SRCAND ); |
| } |
| else |
| ImplWriteBmpRecord( aBmp, pA->GetPoint(), aBmp.GetSizePixel(), WIN_SRCCOPY ); |
| } |
| break; |
| |
| case META_BMPEXSCALE_ACTION: |
| { |
| const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction; |
| Bitmap aBmp( pA->GetBitmapEx().GetBitmap() ); |
| Bitmap aMsk( pA->GetBitmapEx().GetMask() ); |
| |
| if( !!aMsk ) |
| { |
| aBmp.Replace( aMsk, COL_WHITE ); |
| aMsk.Invert(); |
| ImplWriteBmpRecord( aMsk, pA->GetPoint(), pA->GetSize(), WIN_SRCPAINT ); |
| ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCAND ); |
| } |
| else |
| ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCCOPY ); |
| } |
| break; |
| |
| case META_BMPEXSCALEPART_ACTION: |
| { |
| const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pAction; |
| BitmapEx aBmpEx( pA->GetBitmapEx() ); |
| aBmpEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ); |
| Bitmap aBmp( aBmpEx.GetBitmap() ); |
| Bitmap aMsk( aBmpEx.GetMask() ); |
| |
| if( !!aMsk ) |
| { |
| aBmp.Replace( aMsk, COL_WHITE ); |
| aMsk.Invert(); |
| ImplWriteBmpRecord( aMsk, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCPAINT ); |
| ImplWriteBmpRecord( aBmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCAND ); |
| } |
| else |
| ImplWriteBmpRecord( aBmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCCOPY ); |
| } |
| break; |
| |
| case META_TEXT_ACTION: |
| { |
| const MetaTextAction* pA = (const MetaTextAction*) pAction; |
| const String aText( pA->GetText(), pA->GetIndex(), pA->GetLen() ); |
| |
| ImplCheckTextAttr(); |
| ImplWriteTextRecord( pA->GetPoint(), aText, NULL, 0 ); |
| } |
| break; |
| |
| case META_TEXTRECT_ACTION: |
| { |
| const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction; |
| const String aText( pA->GetText() ); |
| |
| ImplCheckTextAttr(); |
| ImplWriteTextRecord( pA->GetRect().TopLeft(), aText, NULL, 0 ); |
| } |
| break; |
| |
| case META_TEXTARRAY_ACTION: |
| { |
| const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction; |
| const String aText( pA->GetText(), pA->GetIndex(), pA->GetLen() ); |
| |
| ImplCheckTextAttr(); |
| ImplWriteTextRecord( pA->GetPoint(), aText, pA->GetDXArray(), 0 ); |
| } |
| break; |
| |
| case META_STRETCHTEXT_ACTION: |
| { |
| const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction; |
| const String aText( pA->GetText(), pA->GetIndex(), pA->GetLen() ); |
| |
| ImplCheckTextAttr(); |
| ImplWriteTextRecord( pA->GetPoint(), aText, NULL, pA->GetWidth() ); |
| } |
| break; |
| |
| case( META_LINECOLOR_ACTION ): |
| { |
| ( (MetaAction*) pAction )->Execute( &maVDev ); |
| mbLineChanged = sal_True; |
| } |
| break; |
| |
| case( META_FILLCOLOR_ACTION ): |
| { |
| ( (MetaAction*) pAction )->Execute( &maVDev ); |
| mbFillChanged = sal_True; |
| } |
| break; |
| |
| case( META_TEXTCOLOR_ACTION ): |
| case( META_TEXTLINECOLOR_ACTION ): |
| case( META_TEXTFILLCOLOR_ACTION ): |
| case( META_TEXTALIGN_ACTION ): |
| case( META_FONT_ACTION ): |
| { |
| ( (MetaAction*) pAction )->Execute( &maVDev ); |
| mbTextChanged = sal_True; |
| } |
| break; |
| |
| case( META_ISECTRECTCLIPREGION_ACTION ): |
| { |
| ( (MetaAction*) pAction )->Execute( &maVDev ); |
| |
| ImplBeginRecord( WIN_EMR_INTERSECTCLIPRECT ); |
| ImplWriteRect( ( (MetaISectRectClipRegionAction*) pAction )->GetRect() ); |
| ImplEndRecord(); |
| } |
| break; |
| |
| case( META_CLIPREGION_ACTION ): |
| case( META_ISECTREGIONCLIPREGION_ACTION ): |
| case( META_MOVECLIPREGION_ACTION ): |
| { |
| ( (MetaAction*) pAction )->Execute( &maVDev ); |
| } |
| break; |
| |
| case( META_REFPOINT_ACTION ): |
| case( META_MAPMODE_ACTION ): |
| ( (MetaAction*) pAction )->Execute( &maVDev ); |
| break; |
| |
| case( META_PUSH_ACTION ): |
| { |
| ( (MetaAction*) pAction )->Execute( &maVDev ); |
| |
| ImplBeginRecord( WIN_EMR_SAVEDC ); |
| ImplEndRecord(); |
| } |
| break; |
| |
| case( META_POP_ACTION ): |
| { |
| ( (MetaAction*) pAction )->Execute( &maVDev ); |
| |
| ImplBeginRecord( WIN_EMR_RESTOREDC ); |
| (*mpStm) << (sal_Int32) -1; |
| ImplEndRecord(); |
| |
| ImplWriteRasterOp( maVDev.GetRasterOp() ); |
| mbLineChanged = mbFillChanged = mbTextChanged = sal_True; |
| } |
| break; |
| |
| case( META_RASTEROP_ACTION ): |
| { |
| ( (MetaAction*) pAction )->Execute( &maVDev ); |
| ImplWriteRasterOp( ( (MetaRasterOpAction*) pAction )->GetRasterOp() ); |
| } |
| break; |
| |
| case( META_LAYOUTMODE_ACTION ): |
| { |
| sal_uInt32 nLayoutMode = ( (MetaLayoutModeAction*) pAction )->GetLayoutMode(); |
| mnHorTextAlign = 0; |
| if (nLayoutMode & TEXT_LAYOUT_BIDI_RTL) |
| { |
| mnHorTextAlign = TA_RIGHT | TA_RTLREADING; |
| } |
| if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_RIGHT) |
| mnHorTextAlign |= TA_RIGHT; |
| else if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_LEFT) |
| mnHorTextAlign &= ~TA_RIGHT; |
| break; |
| } |
| |
| case( META_MASK_ACTION ): |
| case( META_MASKSCALE_ACTION ): |
| case( META_MASKSCALEPART_ACTION ): |
| case( META_WALLPAPER_ACTION ): |
| case( META_TEXTLINE_ACTION ): |
| case( META_COMMENT_ACTION ): |
| case( META_GRADIENTEX_ACTION ): |
| { |
| // !!! >>> we don't want to support these actions |
| } |
| break; |
| |
| default: |
| DBG_ERROR( ( ByteString( "EMFWriter::ImplWriteActions: unsupported MetaAction #" ) += ByteString::CreateFromInt32( nType ) ).GetBuffer() ); |
| break; |
| } |
| } |
| } |